Merge "AudioFlinger: enforce OP_RECORD_AUDIO during recording" into qt-dev
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 25a81eb..d24cb81 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -28,6 +28,10 @@
#include "ACameraCaptureSession.inc"
+ACameraDevice::~ACameraDevice() {
+ mDevice->stopLooper();
+}
+
namespace android {
namespace acam {
@@ -116,14 +120,10 @@
if (!isClosed()) {
disconnectLocked(session);
}
+ LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
+ "CameraDevice looper should've been stopped before ~CameraDevice");
mCurrentSession = nullptr;
- if (mCbLooper != nullptr) {
- mCbLooper->unregisterHandler(mHandler->id());
- mCbLooper->stop();
- }
}
- mCbLooper.clear();
- mHandler.clear();
}
void
@@ -892,6 +892,16 @@
return;
}
+void CameraDevice::stopLooper() {
+ Mutex::Autolock _l(mDeviceLock);
+ if (mCbLooper != nullptr) {
+ mCbLooper->unregisterHandler(mHandler->id());
+ mCbLooper->stop();
+ }
+ mCbLooper.clear();
+ mHandler.clear();
+}
+
CameraDevice::CallbackHandler::CallbackHandler(const char* id) : mId(id) {
}
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index c92a95f..7a35bf0 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -109,6 +109,9 @@
inline ACameraDevice* getWrapper() const { return mWrapper; };
+ // Stop the looper thread and unregister the handler
+ void stopLooper();
+
private:
friend ACameraCaptureSession;
camera_status_t checkCameraClosedOrErrorLocked() const;
@@ -354,7 +357,7 @@
sp<ACameraMetadata> chars) :
mDevice(new android::acam::CameraDevice(id, cb, chars, this)) {}
- ~ACameraDevice() {};
+ ~ACameraDevice();
/*******************
* NDK public APIs *
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 7cd832a..8dd6e00 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -7689,14 +7689,14 @@
* case, when the application configures a RAW stream, the camera device will make sure
* the active physical camera will remain active to ensure consistent RAW output
* behavior, and not switch to other physical cameras.</p>
- * <p>To maintain backward compatibility, the capture request and result metadata tags
- * required for basic camera functionalities will be solely based on the
- * logical camera capabiltity. Other request and result metadata tags, on the other
- * hand, will be based on current active physical camera. For example, the physical
- * cameras' sensor sensitivity and lens capability could be different from each other.
- * So when the application manually controls sensor exposure time/gain, or does manual
- * focus control, it must checks the current active physical camera's exposure, gain,
- * and focus distance range.</p>
+ * <p>The capture request and result metadata tags required for backward compatible camera
+ * functionalities will be solely based on the logical camera capabiltity. On the other
+ * hand, the use of manual capture controls (sensor or post-processing) with a
+ * logical camera may result in unexpected behavior when the HAL decides to switch
+ * between physical cameras with different characteristics under the hood. For example,
+ * when the application manually sets exposure time and sensitivity while zooming in,
+ * the brightness of the camera images may suddenly change because HAL switches from one
+ * physical camera to the other.</p>
*
* @see ACAMERA_LENS_DISTORTION
* @see ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION
@@ -8330,7 +8330,7 @@
* fire the flash for flash power metering during precapture, and then fire the flash
* for the final capture, if a flash is available on the device and the AE mode is set to
* enable the flash.</p>
- * <p>Devices that initially shipped with Android version <a href="https://developer.android.com/reference/android/os/Build.VERSION_CODES.html#Q">Q</a> or newer will not include any LEGACY-level devices.</p>
+ * <p>Devices that initially shipped with Android version <a href="https://developer.android.com/reference/android/os/Build/VERSION_CODES.html#Q">Q</a> or newer will not include any LEGACY-level devices.</p>
*
* @see ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER
* @see ACAMERA_REQUEST_AVAILABLE_CAPABILITIES
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index a43d707..35c8355 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -44,6 +44,10 @@
using namespace android;
+ACameraDevice::~ACameraDevice() {
+ mDevice->stopLooper();
+}
+
namespace android {
namespace acam {
@@ -130,13 +134,9 @@
disconnectLocked(session);
}
mCurrentSession = nullptr;
- if (mCbLooper != nullptr) {
- mCbLooper->unregisterHandler(mHandler->id());
- mCbLooper->stop();
- }
+ LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
+ "CameraDevice looper should've been stopped before ~CameraDevice");
}
- mCbLooper.clear();
- mHandler.clear();
}
void
@@ -1400,6 +1400,16 @@
}
}
+void CameraDevice::stopLooper() {
+ Mutex::Autolock _l(mDeviceLock);
+ if (mCbLooper != nullptr) {
+ mCbLooper->unregisterHandler(mHandler->id());
+ mCbLooper->stop();
+ }
+ mCbLooper.clear();
+ mHandler.clear();
+}
+
/**
* Camera service callback implementation
*/
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index 829b084..3328a85 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -133,6 +133,9 @@
bool setDeviceMetadataQueues();
inline ACameraDevice* getWrapper() const { return mWrapper; };
+ // Stop the looper thread and unregister the handler
+ void stopLooper();
+
private:
friend ACameraCaptureSession;
@@ -383,7 +386,7 @@
sp<ACameraMetadata> chars) :
mDevice(new android::acam::CameraDevice(id, cb, std::move(chars), this)) {}
- ~ACameraDevice() {};
+ ~ACameraDevice();
/*******************
* NDK public APIs *
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index 23a35e5..f164f28 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -62,10 +62,8 @@
secure, keyId, iv, mode, pattern, subSamples, source, offset, destination,
[&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) {
status = toStatus_1_0(hStatus);
- if (status == Status::OK) {
- bytesWritten = hBytesWritten;
- detailedError = hDetailedError;
- }
+ bytesWritten = hBytesWritten;
+ detailedError = hDetailedError;
}
);
@@ -109,6 +107,10 @@
"destination decrypt buffer base not set");
return Void();
}
+ } else {
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
+ "destination type not supported");
+ return Void();
}
sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
@@ -126,38 +128,45 @@
(static_cast<void *>(sourceBase->getPointer()));
uint8_t* srcPtr = static_cast<uint8_t *>(base + source.offset + offset);
void* destPtr = NULL;
- if (destination.type == BufferType::SHARED_MEMORY) {
- const SharedBuffer& destBuffer = destination.nonsecureMemory;
- sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
- if (destBase == nullptr) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
- return Void();
- }
-
- if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
- _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
- return Void();
- }
- destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
- } else if (destination.type == BufferType::NATIVE_HANDLE) {
- native_handle_t *handle = const_cast<native_handle_t *>(
- destination.secureMemory.getNativeHandle());
- destPtr = static_cast<void *>(handle);
+ // destination.type == BufferType::SHARED_MEMORY
+ const SharedBuffer& destBuffer = destination.nonsecureMemory;
+ sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
+ if (destBase == nullptr) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
+ return Void();
}
+ if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
+ return Void();
+ }
+ destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
+
+
// Calculate the output buffer size and determine if any subsamples are
// encrypted.
size_t destSize = 0;
bool haveEncryptedSubsamples = false;
for (size_t i = 0; i < subSamples.size(); i++) {
const SubSample &subSample = subSamples[i];
- destSize += subSample.numBytesOfClearData;
- destSize += subSample.numBytesOfEncryptedData;
+ if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize)) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample clear size overflow");
+ return Void();
+ }
+ if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize)) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample encrypted size overflow");
+ return Void();
+ }
if (subSample.numBytesOfEncryptedData > 0) {
haveEncryptedSubsamples = true;
}
}
+ if (destSize > destBuffer.size) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample sum too large");
+ return Void();
+ }
+
if (mode == Mode::UNENCRYPTED) {
if (haveEncryptedSubsamples) {
_hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 6509a88..6dab70b 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -127,14 +127,14 @@
}
switch (mBitrateMode->value) {
- case C2Config::BITRATE_VARIABLE:
- mBitrateControlMode = VPX_VBR;
- break;
case C2Config::BITRATE_CONST:
- default:
mBitrateControlMode = VPX_CBR;
break;
- break;
+ case C2Config::BITRATE_VARIABLE:
+ [[fallthrough]];
+ default:
+ mBitrateControlMode = VPX_VBR;
+ break;
}
setCodecSpecificInterface();
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
index 90758f9..62ccd1b 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.h
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -275,7 +275,7 @@
addParameter(
DefineParam(mBitrateMode, C2_PARAMKEY_BITRATE_MODE)
.withDefault(new C2StreamBitrateModeTuning::output(
- 0u, C2Config::BITRATE_CONST))
+ 0u, C2Config::BITRATE_VARIABLE))
.withFields({
C2F(mBitrateMode, value).oneOf({
C2Config::BITRATE_CONST, C2Config::BITRATE_VARIABLE })
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index cc8c17a..51d417a 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -176,9 +176,9 @@
DIR_INPUT = 0x00000000,
DIR_OUTPUT = 0x10000000,
- IS_STREAM_FLAG = 0x00100000,
- STREAM_ID_MASK = 0x03E00000,
- STREAM_ID_SHIFT = 21,
+ IS_STREAM_FLAG = 0x02000000,
+ STREAM_ID_MASK = 0x01F00000,
+ STREAM_ID_SHIFT = 20,
MAX_STREAM_ID = STREAM_ID_MASK >> STREAM_ID_SHIFT,
STREAM_MASK = IS_STREAM_FLAG | STREAM_ID_MASK,
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
index 687754b..65f0d09 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
@@ -15,19 +15,19 @@
*/
cc_test {
- name: "VtsHidlC2V1_0TargetAudioDecTest",
- defaults: ["VtsMediaC2V1_0Defaults"],
+ name: "VtsHalMediaC2V1_0TargetAudioDecTest",
+ defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: [
- "VtsHidlC2V1_0TargetAudioDecTest.cpp",
+ "VtsHalMediaC2V1_0TargetAudioDecTest.cpp",
//"media_audio_hidl_test_common.cpp"
],
}
cc_test {
- name: "VtsHidlC2V1_0TargetAudioEncTest",
- defaults: ["VtsMediaC2V1_0Defaults"],
+ name: "VtsHalMediaC2V1_0TargetAudioEncTest",
+ defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: [
- "VtsHidlC2V1_0TargetAudioEncTest.cpp",
+ "VtsHalMediaC2V1_0TargetAudioEncTest.cpp",
//"media_audio_hidl_test_common.cpp"
],
}
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
similarity index 99%
rename from media/codec2/hidl/1.0/vts/functional/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
rename to media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index 6469735..a8a552c 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -547,6 +547,10 @@
if (mCompName == raw) {
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
+ } else if (mCompName == g711alaw || mCompName == g711mlaw) {
+ // g711 test data is all 1-channel and has no embedded config info.
+ bitStreamInfo[0] = 8000;
+ bitStreamInfo[1] = 1;
} else {
ASSERT_NO_FATAL_FAILURE(
getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
similarity index 100%
rename from media/codec2/hidl/1.0/vts/functional/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp
rename to media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
diff --git a/media/codec2/hidl/1.0/vts/functional/common/Android.bp b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
index da0061a..a011ba3 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
@@ -1,5 +1,5 @@
cc_library_static {
- name: "VtsMediaC2V1_0CommonUtil",
+ name: "VtsHalMediaC2V1_0CommonUtil",
defaults: [
"VtsHalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
@@ -17,14 +17,14 @@
}
cc_defaults {
- name: "VtsMediaC2V1_0Defaults",
+ name: "VtsHalMediaC2V1_0Defaults",
defaults: [
"VtsHalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
],
static_libs: [
- "VtsMediaC2V1_0CommonUtil",
+ "VtsHalMediaC2V1_0CommonUtil",
],
shared_libs: [
diff --git a/media/codec2/hidl/1.0/vts/functional/common/README.md b/media/codec2/hidl/1.0/vts/functional/common/README.md
index 3deab10..f2f579c 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/README.md
+++ b/media/codec2/hidl/1.0/vts/functional/common/README.md
@@ -1,31 +1,36 @@
-## Codec2 VTS Hal @ 1.0 tests ##
----
-#### master :
+# Codec2 VTS Hal @ 1.0 tests #
+
+## master :
Functionality of master is to enumerate all the Codec2 components available in C2 media service.
-usage: VtsHidlC2V1\_0TargetMasterTest -I default
+usage: `VtsHalMediaC2V1_0TargetMasterTest -I default`
-#### component :
+## component :
Functionality of component test is to validate common functionality across all the Codec2 components available in C2 media service. For a standard C2 component, these tests are expected to pass.
-usage: VtsHidlC2V1\_0TargetComponentTest -I software -C <comp name>
-example: VtsHidlC2V1\_0TargetComponentTest -I software -C c2.android.vorbis.decoder
+usage: `VtsHalMediaC2V1_0TargetComponentTest -I software -C <comp name>`
-#### audio :
-Functionality of audio test is to validate audio specific functionality Codec2 components. The resource files for this test are taken from media/codec2/hidl/1.0/vts/functional/res. The path to these files on the device is required to be given for bitstream tests.
+example: `VtsHalMediaC2V1_0TargetComponentTest -I software -C c2.android.vorbis.decoder`
-usage: VtsHidlC2V1\_0TargetAudioDecTest -I default -C <comp name> -P /sdcard/res/
-usage: VtsHidlC2V1\_0TargetAudioEncTest -I software -C <comp name> -P /sdcard/res/
+## audio :
+Functionality of audio test is to validate audio specific functionality of Codec2 components. The resource files for this test are taken from `frameworks/av/media/codec2/hidl/1.0/vts/functional/res`. The path to these files on the device can be specified with `-P`. (If the device path is omitted, `/data/local/tmp/media/` is the default value.)
-example: VtsHidlC2V1\_0TargetAudioDecTest -I software -C c2.android.flac.decoder -P /sdcard/res/
-example: VtsHidlC2V1\_0TargetAudioEncTest -I software -C c2.android.opus.encoder -P /sdcard/res/
+usage: `VtsHalMediaC2V1_0TargetAudioDecTest -I default -C <comp name> -P <path to resource files>`
-#### video :
-Functionality of video test is to validate video specific functionality Codec2 components. The resource files for this test are taken from media/codec2/hidl/1.0/vts/functional/res. The path to these files on the device is required to be given for bitstream tests.
+usage: `VtsHalMediaC2V1_0TargetAudioEncTest -I software -C <comp name> -P <path to resource files>`
-usage: VtsHidlC2V1\_0TargetVideoDecTest -I default -C <comp name> -P /sdcard/res/
-usage: VtsHidlC2V1\_0TargetVideoEncTest -I software -C <comp name> -P /sdcard/res/
+example: `VtsHalMediaC2V1_0TargetAudioDecTest -I software -C c2.android.flac.decoder -P /data/local/tmp/media/`
-example: VtsHidlC2V1\_0TargetVideoDecTest -I software -C c2.android.avc.decoder -P /sdcard/res/
-example: VtsHidlC2V1\_0TargetVideoEncTest -I software -C c2.android.vp9.encoder -P /sdcard/res/
+example: `VtsHalMediaC2V1_0TargetAudioEncTest -I software -C c2.android.opus.encoder -P /data/local/tmp/media/`
+
+## video :
+Functionality of video test is to validate video specific functionality of Codec2 components. The resource files for this test are taken from `frameworks/av/media/codec2/hidl/1.0/vts/functional/res`. The path to these files on the device can be specified with `-P`. (If the device path is omitted, `/data/local/tmp/media/` is the default value.)
+
+usage: `VtsHalMediaC2V1_0TargetVideoDecTest -I default -C <comp name> -P <path to resource files>`
+
+usage: `VtsHalMediaC2V1_0TargetVideoEncTest -I software -C <comp name> -P <path to resource files>`
+
+example: `VtsHalMediaC2V1_0TargetVideoDecTest -I software -C c2.android.avc.decoder -P /data/local/tmp/media/`
+
+example: `VtsHalMediaC2V1_0TargetVideoEncTest -I software -C c2.android.vp9.encoder -P /data/local/tmp/media/`
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index c577dac..db59e54 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -118,7 +118,7 @@
registerTestService<IComponentStore>();
}
- ComponentTestEnvironment() : res("/sdcard/media/") {}
+ ComponentTestEnvironment() : res("/data/local/tmp/media/") {}
void setComponent(const char* _component) { component = _component; }
diff --git a/media/codec2/hidl/1.0/vts/functional/component/Android.bp b/media/codec2/hidl/1.0/vts/functional/component/Android.bp
index 4b913b6..7ec64ee 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/component/Android.bp
@@ -15,8 +15,8 @@
*/
cc_test {
- name: "VtsHidlC2V1_0TargetComponentTest",
- defaults: ["VtsMediaC2V1_0Defaults"],
- srcs: ["VtsHidlC2V1_0TargetComponentTest.cpp"],
+ name: "VtsHalMediaC2V1_0TargetComponentTest",
+ defaults: ["VtsHalMediaC2V1_0Defaults"],
+ srcs: ["VtsHalMediaC2V1_0TargetComponentTest.cpp"],
}
diff --git a/media/codec2/hidl/1.0/vts/functional/component/VtsHidlC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
similarity index 95%
rename from media/codec2/hidl/1.0/vts/functional/component/VtsHidlC2V1_0TargetComponentTest.cpp
rename to media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
index 74548b5..9dc541c 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/VtsHidlC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
@@ -144,8 +144,7 @@
// Queueing an empty WorkBundle
std::list<std::unique_ptr<C2Work>> workList;
- err = mComponent->queue(&workList);
- ASSERT_EQ(err, C2_OK);
+ mComponent->queue(&workList);
err = mComponent->reset();
ASSERT_EQ(err, C2_OK);
@@ -183,33 +182,23 @@
// Test Multiple Start Stop Reset Test
TEST_F(Codec2ComponentHidlTest, MultipleStartStopReset) {
ALOGV("Multiple Start Stop and Reset Test");
- c2_status_t err = C2_OK;
for (size_t i = 0; i < MAX_RETRY; i++) {
- err = mComponent->start();
- ASSERT_EQ(err, C2_OK);
-
- err = mComponent->stop();
- ASSERT_EQ(err, C2_OK);
+ mComponent->start();
+ mComponent->stop();
}
- err = mComponent->start();
- ASSERT_EQ(err, C2_OK);
+ ASSERT_EQ(mComponent->start(), C2_OK);
for (size_t i = 0; i < MAX_RETRY; i++) {
- err = mComponent->reset();
- ASSERT_EQ(err, C2_OK);
+ mComponent->reset();
}
- err = mComponent->start();
- ASSERT_EQ(err, C2_OK);
-
- err = mComponent->stop();
- ASSERT_EQ(err, C2_OK);
+ ASSERT_EQ(mComponent->start(), C2_OK);
+ ASSERT_EQ(mComponent->stop(), C2_OK);
// Second stop should return error
- err = mComponent->stop();
- ASSERT_NE(err, C2_OK);
+ ASSERT_NE(mComponent->stop(), C2_OK);
}
// Test Component Release API
@@ -233,8 +222,7 @@
ASSERT_EQ(failures.size(), 0u);
for (size_t i = 0; i < MAX_RETRY; i++) {
- err = mComponent->release();
- ASSERT_EQ(err, C2_OK);
+ mComponent->release();
}
}
@@ -332,14 +320,12 @@
timeConsumed = getNowUs() - startTime;
ALOGV("mComponent->queue() timeConsumed=%" PRId64 " us", timeConsumed);
CHECK_TIMEOUT(timeConsumed, QUEUE_TIME_OUT, "queue()");
- ASSERT_EQ(err, C2_OK);
startTime = getNowUs();
err = mComponent->flush(C2Component::FLUSH_COMPONENT, &workList);
timeConsumed = getNowUs() - startTime;
ALOGV("mComponent->flush() timeConsumed=%" PRId64 " us", timeConsumed);
CHECK_TIMEOUT(timeConsumed, FLUSH_TIME_OUT, "flush()");
- ASSERT_EQ(err, C2_OK);
startTime = getNowUs();
err = mComponent->stop();
diff --git a/media/codec2/hidl/1.0/vts/functional/master/Android.bp b/media/codec2/hidl/1.0/vts/functional/master/Android.bp
index e164d68..53e323e 100644
--- a/media/codec2/hidl/1.0/vts/functional/master/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/master/Android.bp
@@ -15,8 +15,8 @@
*/
cc_test {
- name: "VtsHidlC2V1_0TargetMasterTest",
- defaults: ["VtsMediaC2V1_0Defaults"],
- srcs: ["VtsHidlC2V1_0TargetMasterTest.cpp"],
+ name: "VtsHalMediaC2V1_0TargetMasterTest",
+ defaults: ["VtsHalMediaC2V1_0Defaults"],
+ srcs: ["VtsHalMediaC2V1_0TargetMasterTest.cpp"],
}
diff --git a/media/codec2/hidl/1.0/vts/functional/master/VtsHidlC2V1_0TargetMasterTest.cpp b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
similarity index 100%
rename from media/codec2/hidl/1.0/vts/functional/master/VtsHidlC2V1_0TargetMasterTest.cpp
rename to media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
diff --git a/media/codec2/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index 6e57ee7..be35b02 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -15,14 +15,14 @@
*/
cc_test {
- name: "VtsHidlC2V1_0TargetVideoDecTest",
- defaults: ["VtsMediaC2V1_0Defaults"],
- srcs: ["VtsHidlC2V1_0TargetVideoDecTest.cpp"],
+ name: "VtsHalMediaC2V1_0TargetVideoDecTest",
+ defaults: ["VtsHalMediaC2V1_0Defaults"],
+ srcs: ["VtsHalMediaC2V1_0TargetVideoDecTest.cpp"],
}
cc_test {
- name: "VtsHidlC2V1_0TargetVideoEncTest",
- defaults: ["VtsMediaC2V1_0Defaults"],
- srcs: ["VtsHidlC2V1_0TargetVideoEncTest.cpp"],
+ name: "VtsHalMediaC2V1_0TargetVideoEncTest",
+ defaults: ["VtsHalMediaC2V1_0Defaults"],
+ srcs: ["VtsHalMediaC2V1_0TargetVideoEncTest.cpp"],
}
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHidlC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
similarity index 97%
rename from media/codec2/hidl/1.0/vts/functional/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
rename to media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 33fa848..5e28750 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -46,6 +46,10 @@
explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
: C2Buffer(
{block->share(block->offset(), block->size(), ::C2Fence())}) {}
+
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block, size_t size)
+ : C2Buffer(
+ {block->share(block->offset(), size, ::C2Fence())}) {}
};
static ComponentTestEnvironment* gEnv = nullptr;
@@ -120,6 +124,13 @@
mTimestampUs = 0u;
mTimestampDevTest = false;
if (mCompName == unknown_comp) mDisableTest = true;
+
+ C2SecureModeTuning secureModeTuning{};
+ mComponent->query({ &secureModeTuning }, {}, C2_MAY_BLOCK, nullptr);
+ if (secureModeTuning.value == C2Config::SM_READ_PROTECTED) {
+ mDisableTest = true;
+ }
+
if (mDisableTest) std::cout << "[ WARN ] Test Disabled \n";
}
@@ -371,11 +382,12 @@
ASSERT_EQ(eleStream.gcount(), size);
work->input.buffers.clear();
+ auto alignedSize = ALIGN(size, PAGE_SIZE);
if (size) {
std::shared_ptr<C2LinearBlock> block;
ASSERT_EQ(C2_OK,
linearPool->fetchLinearBlock(
- size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+ alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
&block));
ASSERT_TRUE(block);
@@ -385,13 +397,13 @@
fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
break;
}
- ASSERT_EQ((size_t)size, view.capacity());
+ ASSERT_EQ((size_t)alignedSize, view.capacity());
ASSERT_EQ(0u, view.offset());
- ASSERT_EQ((size_t)size, view.size());
+ ASSERT_EQ((size_t)alignedSize, view.size());
memcpy(view.base(), data, size);
- work->input.buffers.emplace_back(new LinearBuffer(block));
+ work->input.buffers.emplace_back(new LinearBuffer(block, size));
free(data);
}
work->worklets.clear();
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHidlC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
similarity index 89%
rename from media/codec2/hidl/1.0/vts/functional/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
rename to media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 6bcf840..c1f5a92 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -284,15 +284,16 @@
std::list<std::unique_ptr<C2Work>>& workQueue,
std::list<uint64_t>& flushedIndices,
std::shared_ptr<C2BlockPool>& graphicPool,
- std::ifstream& eleStream, uint32_t frameID,
- uint32_t nFrames, uint32_t nWidth, int32_t nHeight,
- bool flushed = false,bool signalEOS = true) {
+ std::ifstream& eleStream, bool& disableTest,
+ uint32_t frameID, uint32_t nFrames, uint32_t nWidth,
+ int32_t nHeight, bool flushed = false, bool signalEOS = true) {
typedef std::unique_lock<std::mutex> ULock;
uint32_t maxRetry = 0;
int bytesCount = nWidth * nHeight * 3 >> 1;
int32_t timestampIncr = ENCODER_TIMESTAMP_INCREMENT;
uint64_t timestamp = 0;
+ c2_status_t err = C2_OK;
while (1) {
if (nFrames == 0) break;
uint32_t flags = 0;
@@ -333,16 +334,21 @@
ASSERT_EQ(eleStream.gcount(), bytesCount);
}
std::shared_ptr<C2GraphicBlock> block;
- ASSERT_EQ(
- C2_OK,
- graphicPool->fetchGraphicBlock(
+ err = graphicPool->fetchGraphicBlock(
nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
- {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
+ {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+ if (err != C2_OK) {
+ fprintf(stderr, "fetchGraphicBlock failed : %d\n", err);
+ disableTest = true;
+ break;
+ }
+
ASSERT_TRUE(block);
// Graphic View
C2GraphicView view = block->map().get();
if (view.error() != C2_OK) {
fprintf(stderr, "C2GraphicBlock::map() failed : %d", view.error());
+ disableTest = true;
break;
}
@@ -420,8 +426,16 @@
ASSERT_EQ(mComponent->start(), C2_OK);
ASSERT_NO_FATAL_FAILURE(
encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
0, ENC_NUM_FRAMES, nWidth, nHeight, false, signalEOS));
+ // mDisableTest will be set if buffer was not fetched properly.
+ // This may happen when resolution is not proper but config suceeded
+ // In this cases, we skip encoding the input stream
+ if (mDisableTest) {
+ std::cout << "[ WARN ] Test Disabled \n";
+ ASSERT_EQ(mComponent->stop(), C2_OK);
+ return;
+ }
// If EOS is not sent, sending empty input with EOS flag
inputFrames = ENC_NUM_FRAMES;
@@ -531,8 +545,17 @@
ALOGV("mURL : %s", mURL);
ASSERT_NO_FATAL_FAILURE(
encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
0, numFramesFlushed, nWidth, nHeight));
+ // mDisableTest will be set if buffer was not fetched properly.
+ // This may happen when resolution is not proper but config suceeded
+ // In this cases, we skip encoding the input stream
+ if (mDisableTest) {
+ std::cout << "[ WARN ] Test Disabled \n";
+ ASSERT_EQ(mComponent->stop(), C2_OK);
+ return;
+ }
+
std::list<std::unique_ptr<C2Work>> flushedWork;
c2_status_t err =
mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
@@ -561,10 +584,19 @@
mFlushedIndices.clear();
ASSERT_NO_FATAL_FAILURE(
encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
numFramesFlushed, numFrames - numFramesFlushed,
nWidth, nHeight, true));
eleStream.close();
+ // mDisableTest will be set if buffer was not fetched properly.
+ // This may happen when resolution is not proper but config suceeded
+ // In this cases, we skip encoding the input stream
+ if (mDisableTest) {
+ std::cout << "[ WARN ] Test Disabled \n";
+ ASSERT_EQ(mComponent->stop(), C2_OK);
+ return;
+ }
+
err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
ASSERT_NO_FATAL_FAILURE(
@@ -607,19 +639,19 @@
ASSERT_NO_FATAL_FAILURE(
encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
0, 1, nWidth, nHeight, false, false));
// Feed larger input buffer.
ASSERT_NO_FATAL_FAILURE(
encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
1, 1, nWidth*2, nHeight*2, false, false));
// Feed smaller input buffer.
ASSERT_NO_FATAL_FAILURE(
encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
2, 1, nWidth/2, nHeight/2, false, true));
// blocking call to ensures application to Wait till all the inputs are
@@ -629,15 +661,13 @@
waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
if (mFramesReceived != 3) {
- ALOGE("Input buffer count and Output buffer count mismatch");
- ALOGE("framesReceived : %d inputFrames : 3", mFramesReceived);
- ASSERT_TRUE(false);
+ std::cout << "[ WARN ] Component didn't receive all buffers back \n";
+ ALOGW("framesReceived : %d inputFrames : 3", mFramesReceived);
}
if (mFailedWorkReceived == 0) {
- ALOGE("Expected failed frame count mismatch");
- ALOGE("failedFramesReceived : %d", mFailedWorkReceived);
- ASSERT_TRUE(false);
+ std::cout << "[ WARN ] Expected failed frame count mismatch \n";
+ ALOGW("failedFramesReceived : %d", mFailedWorkReceived);
}
ASSERT_EQ(mComponent->stop(), C2_OK);
@@ -665,8 +695,17 @@
ASSERT_NO_FATAL_FAILURE(
encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, 0,
- MAX_INPUT_BUFFERS, nWidth, nHeight));
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
+ 0, MAX_INPUT_BUFFERS, nWidth, nHeight, false, true));
+
+ // mDisableTest will be set if buffer was not fetched properly.
+ // This may happen when resolution is not proper but config suceeded
+ // In this cases, we skip encoding the input stream
+ if (mDisableTest) {
+ std::cout << "[ WARN ] Test Disabled \n";
+ ASSERT_EQ(mComponent->stop(), C2_OK);
+ return;
+ }
ALOGD("Waiting for input consumption");
ASSERT_NO_FATAL_FAILURE(
@@ -676,6 +715,7 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
ASSERT_EQ(mComponent->reset(), C2_OK);
}
+
INSTANTIATE_TEST_CASE_P(NonStdSizes, Codec2VideoEncResolutionTest, ::testing::Values(
std::make_pair(52, 18),
std::make_pair(365, 365),
diff --git a/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
index dd45557..e37ca38 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
@@ -23,6 +23,8 @@
#define ENC_DEFAULT_FRAME_HEIGHT 288
#define MAX_ITERATIONS 128
+#define ALIGN(_sz, _align) ((_sz + (_align - 1)) & ~(_align - 1))
+
/*
* Common video utils
*/
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 2b417a6..5ed54f1 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -959,9 +959,9 @@
std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
char const* serviceName) {
- uint32_t inputSurfaceSetting = ::android::base::GetUintProperty(
- "debug.stagefright.c2inputsurface", uint32_t(0));
- if (inputSurfaceSetting == 0) {
+ int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
+ "debug.stagefright.c2inputsurface", int32_t(0));
+ if (inputSurfaceSetting <= 0) {
return nullptr;
}
size_t index = GetServiceNames().size();
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 8ae80ee..9c84c71 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -9,6 +9,7 @@
"CCodecConfig.cpp",
"Codec2Buffer.cpp",
"Codec2InfoBuilder.cpp",
+ "Omx2IGraphicBufferSource.cpp",
"PipelineWatcher.cpp",
"ReflectedParamUpdater.cpp",
"SkipCutBuffer.cpp",
@@ -41,8 +42,10 @@
"libmedia",
"libmedia_omx",
"libsfplugin_ccodec_utils",
+ "libstagefright_bufferqueue_helper",
"libstagefright_codecbase",
"libstagefright_foundation",
+ "libstagefright_omx",
"libstagefright_omx_utils",
"libstagefright_xmlparser",
"libui",
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index 3a93c2a..78d221e 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -36,6 +36,7 @@
#include <media/stagefright/MediaErrors.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
+#include <utils/Thread.h>
#include "C2OMXNode.h"
@@ -50,16 +51,128 @@
} // namespace
+class C2OMXNode::QueueThread : public Thread {
+public:
+ QueueThread() : Thread(false) {}
+ ~QueueThread() override = default;
+ void queue(
+ const std::shared_ptr<Codec2Client::Component> &comp,
+ int fenceFd,
+ std::unique_ptr<C2Work> &&work,
+ android::base::unique_fd &&fd0,
+ android::base::unique_fd &&fd1) {
+ Mutexed<Jobs>::Locked jobs(mJobs);
+ auto it = jobs->queues.try_emplace(comp, comp, systemTime()).first;
+ it->second.workList.emplace_back(
+ std::move(work), fenceFd, std::move(fd0), std::move(fd1));
+ jobs->cond.broadcast();
+ }
+
+protected:
+ bool threadLoop() override {
+ constexpr nsecs_t kIntervalNs = nsecs_t(10) * 1000 * 1000; // 10ms
+ constexpr nsecs_t kWaitNs = kIntervalNs * 2;
+ for (int i = 0; i < 2; ++i) {
+ Mutexed<Jobs>::Locked jobs(mJobs);
+ nsecs_t nowNs = systemTime();
+ bool queued = false;
+ for (auto it = jobs->queues.begin(); it != jobs->queues.end(); ) {
+ Queue &queue = it->second;
+ if (queue.workList.empty()
+ || nowNs - queue.lastQueuedTimestampNs < kIntervalNs) {
+ ++it;
+ continue;
+ }
+ std::shared_ptr<Codec2Client::Component> comp = queue.component.lock();
+ if (!comp) {
+ it = jobs->queues.erase(it);
+ continue;
+ }
+ std::list<std::unique_ptr<C2Work>> items;
+ std::vector<int> fenceFds;
+ std::vector<android::base::unique_fd> uniqueFds;
+ while (!queue.workList.empty()) {
+ items.push_back(std::move(queue.workList.front().work));
+ fenceFds.push_back(queue.workList.front().fenceFd);
+ uniqueFds.push_back(std::move(queue.workList.front().fd0));
+ uniqueFds.push_back(std::move(queue.workList.front().fd1));
+ queue.workList.pop_front();
+ }
+
+ jobs.unlock();
+ for (int fenceFd : fenceFds) {
+ sp<Fence> fence(new Fence(fenceFd));
+ fence->waitForever(LOG_TAG);
+ }
+ comp->queue(&items);
+ for (android::base::unique_fd &ufd : uniqueFds) {
+ (void)ufd.release();
+ }
+ jobs.lock();
+
+ it = jobs->queues.upper_bound(comp);
+ queued = true;
+ }
+ if (queued) {
+ return true;
+ }
+ if (i == 0) {
+ jobs.waitForConditionRelative(jobs->cond, kWaitNs);
+ }
+ }
+ return true;
+ }
+
+private:
+ struct WorkFence {
+ WorkFence(std::unique_ptr<C2Work> &&w, int fd) : work(std::move(w)), fenceFd(fd) {}
+
+ WorkFence(
+ std::unique_ptr<C2Work> &&w,
+ int fd,
+ android::base::unique_fd &&uniqueFd0,
+ android::base::unique_fd &&uniqueFd1)
+ : work(std::move(w)),
+ fenceFd(fd),
+ fd0(std::move(uniqueFd0)),
+ fd1(std::move(uniqueFd1)) {}
+
+ std::unique_ptr<C2Work> work;
+ int fenceFd;
+ android::base::unique_fd fd0;
+ android::base::unique_fd fd1;
+ };
+ struct Queue {
+ Queue(const std::shared_ptr<Codec2Client::Component> &comp, nsecs_t timestamp)
+ : component(comp), lastQueuedTimestampNs(timestamp) {}
+ Queue(const Queue &) = delete;
+ Queue &operator =(const Queue &) = delete;
+
+ std::weak_ptr<Codec2Client::Component> component;
+ std::list<WorkFence> workList;
+ nsecs_t lastQueuedTimestampNs;
+ };
+ struct Jobs {
+ std::map<std::weak_ptr<Codec2Client::Component>,
+ Queue,
+ std::owner_less<std::weak_ptr<Codec2Client::Component>>> queues;
+ Condition cond;
+ };
+ Mutexed<Jobs> mJobs;
+};
+
C2OMXNode::C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp)
: mComp(comp), mFrameIndex(0), mWidth(0), mHeight(0), mUsage(0),
- mAdjustTimestampGapUs(0), mFirstInputFrame(true) {
+ mAdjustTimestampGapUs(0), mFirstInputFrame(true),
+ mQueueThread(new QueueThread) {
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS);
+ mQueueThread->run("C2OMXNode", PRIORITY_AUDIO);
}
status_t C2OMXNode::freeNode() {
mComp.reset();
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
- return OK;
+ return mQueueThread->requestExitAndWait();
}
status_t C2OMXNode::sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
@@ -216,11 +329,6 @@
status_t C2OMXNode::emptyBuffer(
buffer_id buffer, const OMXBuffer &omxBuf,
OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
- // TODO: better fence handling
- if (fenceFd >= 0) {
- sp<Fence> fence = new Fence(fenceFd);
- fence->waitForever(LOG_TAG);
- }
std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
if (!comp) {
return NO_INIT;
@@ -299,22 +407,8 @@
}
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
- std::list<std::unique_ptr<C2Work>> items;
- uint64_t index = work->input.ordinal.frameIndex.peeku();
- items.push_back(std::move(work));
-
- c2_status_t err = comp->queue(&items);
- if (err != C2_OK) {
- (void)fd0.release();
- (void)fd1.release();
- return UNKNOWN_ERROR;
- }
-
- mBufferIdsInUse.lock()->emplace(index, buffer);
-
- // release ownership of the fds
- (void)fd0.release();
- (void)fd1.release();
+ mBufferIdsInUse.lock()->emplace(work->input.ordinal.frameIndex.peeku(), buffer);
+ mQueueThread->queue(comp, fenceFd, std::move(work), std::move(fd0), std::move(fd1));
return OK;
}
diff --git a/media/codec2/sfplugin/C2OMXNode.h b/media/codec2/sfplugin/C2OMXNode.h
index 3ca6c0a..1717c96 100644
--- a/media/codec2/sfplugin/C2OMXNode.h
+++ b/media/codec2/sfplugin/C2OMXNode.h
@@ -113,6 +113,9 @@
c2_cntr64_t mPrevCodecTimestamp; // adjusted (codec) timestamp for previous frame
Mutexed<std::map<uint64_t, buffer_id>> mBufferIdsInUse;
+
+ class QueueThread;
+ sp<QueueThread> mQueueThread;
};
} // namespace android
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index aa7189c..9d1cc60 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -45,6 +45,7 @@
#include "CCodec.h"
#include "CCodecBufferChannel.h"
#include "InputSurfaceWrapper.h"
+#include "Omx2IGraphicBufferSource.h"
extern "C" android::PersistentSurface *CreateInputSurface();
@@ -1067,6 +1068,7 @@
OmxStatus s;
android::sp<HGraphicBufferProducer> gbp;
android::sp<HGraphicBufferSource> gbs;
+
using ::android::hardware::Return;
Return<void> transStatus = omx->createInputSurface(
[&s, &gbp, &gbs](
@@ -1852,15 +1854,30 @@
// Create Codec 2.0 input surface
extern "C" android::PersistentSurface *CreateInputSurface() {
+ using namespace android;
// Attempt to create a Codec2's input surface.
- std::shared_ptr<android::Codec2Client::InputSurface> inputSurface =
- android::Codec2Client::CreateInputSurface();
+ std::shared_ptr<Codec2Client::InputSurface> inputSurface =
+ Codec2Client::CreateInputSurface();
if (!inputSurface) {
- return nullptr;
+ if (property_get_int32("debug.stagefright.c2inputsurface", 0) == -1) {
+ sp<IGraphicBufferProducer> gbp;
+ sp<OmxGraphicBufferSource> gbs = new OmxGraphicBufferSource();
+ status_t err = gbs->initCheck();
+ if (err != OK) {
+ ALOGE("Failed to create persistent input surface: error %d", err);
+ return nullptr;
+ }
+ return new PersistentSurface(
+ gbs->getIGraphicBufferProducer(),
+ sp<IGraphicBufferSource>(
+ new Omx2IGraphicBufferSource(gbs)));
+ } else {
+ return nullptr;
+ }
}
- return new android::PersistentSurface(
+ return new PersistentSurface(
inputSurface->getGraphicBufferProducer(),
- static_cast<android::sp<android::hidl::base::V1_0::IBase>>(
+ static_cast<sp<android::hidl::base::V1_0::IBase>>(
inputSurface->getHalInterface()));
}
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 8be9a1d..8308292 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -220,7 +220,6 @@
const std::shared_ptr<CCodecCallback> &callback)
: mHeapSeqNum(-1),
mCCodecCallback(callback),
- mDelay(0),
mFrameIndex(0u),
mFirstValidFrameIndex(0u),
mMetaMode(MODE_NONE),
@@ -814,7 +813,6 @@
size_t numInputSlots = inputDelayValue + pipelineDelayValue + kSmoothnessFactor;
size_t numOutputSlots = outputDelayValue + kSmoothnessFactor;
- mDelay = inputDelayValue + pipelineDelayValue + outputDelayValue;
// TODO: get this from input format
bool secure = mComponent->getName().find(".secure") != std::string::npos;
@@ -888,6 +886,8 @@
bool forceArrayMode = false;
Mutexed<Input>::Locked input(mInput);
+ input->inputDelay = inputDelayValue;
+ input->pipelineDelay = pipelineDelayValue;
input->numSlots = numInputSlots;
input->extraBuffers.flush();
input->numExtraSlots = 0u;
@@ -896,6 +896,9 @@
input->buffers.reset(new DummyInputBuffers(mName));
} else if (mMetaMode == MODE_ANW) {
input->buffers.reset(new GraphicMetadataInputBuffers(mName));
+ // This is to ensure buffers do not get released prematurely.
+ // TODO: handle this without going into array mode
+ forceArrayMode = true;
} else {
input->buffers.reset(new GraphicInputBuffers(numInputSlots, mName));
}
@@ -1054,6 +1057,7 @@
}
Mutexed<Output>::Locked output(mOutput);
+ output->outputDelay = outputDelayValue;
output->numSlots = numOutputSlots;
if (graphic) {
if (outputSurface) {
@@ -1377,25 +1381,35 @@
(void)mPipelineWatcher.lock()->outputDelay(outputDelay.value);
bool outputBuffersChanged = false;
- Mutexed<Output>::Locked output(mOutput);
- output->outputDelay = outputDelay.value;
- size_t numOutputSlots = outputDelay.value + kSmoothnessFactor;
- if (output->numSlots < numOutputSlots) {
- output->numSlots = numOutputSlots;
- if (output->buffers->isArrayMode()) {
- OutputBuffersArray *array =
- (OutputBuffersArray *)output->buffers.get();
- ALOGV("[%s] onWorkDone: growing output buffer array to %zu",
- mName, numOutputSlots);
- array->grow(numOutputSlots);
- outputBuffersChanged = true;
+ size_t numOutputSlots = 0;
+ {
+ Mutexed<Output>::Locked output(mOutput);
+ output->outputDelay = outputDelay.value;
+ numOutputSlots = outputDelay.value + kSmoothnessFactor;
+ if (output->numSlots < numOutputSlots) {
+ output->numSlots = numOutputSlots;
+ if (output->buffers->isArrayMode()) {
+ OutputBuffersArray *array =
+ (OutputBuffersArray *)output->buffers.get();
+ ALOGV("[%s] onWorkDone: growing output buffer array to %zu",
+ mName, numOutputSlots);
+ array->grow(numOutputSlots);
+ outputBuffersChanged = true;
+ }
}
+ numOutputSlots = output->numSlots;
}
- output.unlock();
if (outputBuffersChanged) {
mCCodecCallback->onOutputBuffersChanged();
}
+
+ uint32_t depth = mReorderStash.lock()->depth();
+ Mutexed<OutputSurface>::Locked output(mOutputSurface);
+ output->maxDequeueBuffers = numOutputSlots + depth + kRenderingDepth;
+ if (output->surface) {
+ output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
+ }
}
}
break;
@@ -1620,7 +1634,12 @@
// When client pushed EOS, we want all the work to be done quickly.
// Otherwise, component may have stalled work due to input starvation up to
// the sum of the delay in the pipeline.
- size_t n = mInputMetEos ? 0 : mDelay;
+ size_t n = 0;
+ if (!mInputMetEos) {
+ size_t outputDelay = mOutput.lock()->outputDelay;
+ Mutexed<Input>::Locked input(mInput);
+ n = input->inputDelay + input->pipelineDelay + outputDelay;
+ }
return mPipelineWatcher.lock()->elapsed(PipelineWatcher::Clock::now(), n);
}
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index ae57678..ee3455d 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -228,8 +228,6 @@
QueueSync mQueueSync;
std::vector<std::unique_ptr<C2Param>> mParamsToBeSet;
- size_t mDelay;
-
struct Input {
Input();
@@ -306,6 +304,7 @@
const C2WorkOrdinalStruct &ordinal);
void defer(const Entry &entry);
bool hasPending() const;
+ uint32_t depth() const { return mDepth; }
private:
std::list<Entry> mPending;
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 5ebd5bd..26c702d 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -439,6 +439,10 @@
});
}
+size_t BuffersArrayImpl::arraySize() const {
+ return mBuffers.size();
+}
+
// InputBuffersArray
void InputBuffersArray::initialize(
@@ -883,11 +887,24 @@
mAlloc = [format = mFormat, size] {
return new LocalLinearBuffer(format, new ABuffer(size));
};
+ ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
break;
}
- // TODO: add support
- case C2BufferData::GRAPHIC: [[fallthrough]];
+ case C2BufferData::GRAPHIC: {
+ // This is only called for RawGraphicOutputBuffers.
+ mAlloc = [format = mFormat,
+ lbp = LocalBufferPool::Create(kMaxLinearBufferSize * mImpl.arraySize())] {
+ return ConstGraphicBlockBuffer::AllocateEmpty(
+ format,
+ [lbp](size_t capacity) {
+ return lbp->newBuffer(capacity);
+ });
+ };
+ ALOGD("[%s] reallocating with graphic buffer: format = %s",
+ mName, mFormat->debugString().c_str());
+ break;
+ }
case C2BufferData::INVALID: [[fallthrough]];
case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index e4f2809..2cb6b81 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -478,6 +478,11 @@
*/
size_t numClientBuffers() const;
+ /**
+ * Return the size of the array.
+ */
+ size_t arraySize() const;
+
private:
std::string mImplName; ///< name for debugging
const char *mName; ///< C-string version of name
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 702ad6f..5c8ad56 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -25,6 +25,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <nativebase/nativebase.h>
+#include <ui/Fence.h>
#include <C2AllocatorGralloc.h>
#include <C2BlockInternal.h>
@@ -590,7 +591,12 @@
std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
meta->pBuffer = 0;
- // TODO: fence
+ // TODO: wrap this in C2Fence so that the component can wait when it
+ // actually starts processing.
+ if (meta->nFenceFd >= 0) {
+ sp<Fence> fence(new Fence(meta->nFenceFd));
+ fence->waitForever(LOG_TAG);
+ }
return C2Buffer::CreateGraphicBuffer(
block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
#else
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index c54c601..6b75eba 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -194,7 +194,8 @@
// TODO: get this from intf() as well, but how do we map them to
// MediaCodec color formats?
bool encoder = trait.kind == C2Component::KIND_ENCODER;
- if (mediaType.find("video") != std::string::npos) {
+ if (mediaType.find("video") != std::string::npos
+ || mediaType.find("image") != std::string::npos) {
// vendor video codecs prefer opaque format
if (trait.name.find("android") == std::string::npos) {
caps->addColorFormat(COLOR_FormatSurface);
diff --git a/media/codec2/sfplugin/Omx2IGraphicBufferSource.cpp b/media/codec2/sfplugin/Omx2IGraphicBufferSource.cpp
new file mode 100644
index 0000000..764fa00
--- /dev/null
+++ b/media/codec2/sfplugin/Omx2IGraphicBufferSource.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Omx2IGraphicBufferSource"
+#include <android-base/logging.h>
+
+#include "Omx2IGraphicBufferSource.h"
+
+#include <android/BnOMXBufferSource.h>
+#include <media/OMXBuffer.h>
+#include <media/stagefright/omx/OMXUtils.h>
+
+#include <OMX_Component.h>
+#include <OMX_Index.h>
+#include <OMX_IndexExt.h>
+
+namespace android {
+
+namespace /* unnamed */ {
+
+// OmxGraphicBufferSource -> IOMXBufferSource
+
+struct OmxGbs2IOmxBs : public BnOMXBufferSource {
+ sp<OmxGraphicBufferSource> mBase;
+ OmxGbs2IOmxBs(sp<OmxGraphicBufferSource> const& base) : mBase{base} {}
+ BnStatus onOmxExecuting() override {
+ return mBase->onOmxExecuting();
+ }
+ BnStatus onOmxIdle() override {
+ return mBase->onOmxIdle();
+ }
+ BnStatus onOmxLoaded() override {
+ return mBase->onOmxLoaded();
+ }
+ BnStatus onInputBufferAdded(int32_t bufferId) override {
+ return mBase->onInputBufferAdded(bufferId);
+ }
+ BnStatus onInputBufferEmptied(
+ int32_t bufferId,
+ OMXFenceParcelable const& fenceParcel) override {
+ return mBase->onInputBufferEmptied(bufferId, fenceParcel.get());
+ }
+};
+
+struct OmxNodeWrapper : public IOmxNodeWrapper {
+ sp<IOMXNode> mBase;
+ OmxNodeWrapper(sp<IOMXNode> const& base) : mBase{base} {}
+ status_t emptyBuffer(
+ int32_t bufferId, uint32_t flags,
+ const sp<GraphicBuffer> &buffer,
+ int64_t timestamp, int fenceFd) override {
+ return mBase->emptyBuffer(bufferId, buffer, flags, timestamp, fenceFd);
+ }
+ void dispatchDataSpaceChanged(
+ int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+ omx_message msg{};
+ msg.type = omx_message::EVENT;
+ msg.fenceFd = -1;
+ msg.u.event_data.event = OMX_EventDataSpaceChanged;
+ msg.u.event_data.data1 = dataSpace;
+ msg.u.event_data.data2 = aspects;
+ msg.u.event_data.data3 = pixelFormat;
+ mBase->dispatchMessage(msg);
+ }
+};
+
+} // unnamed namespace
+
+// Omx2IGraphicBufferSource
+Omx2IGraphicBufferSource::Omx2IGraphicBufferSource(
+ sp<OmxGraphicBufferSource> const& base)
+ : mBase{base},
+ mOMXBufferSource{new OmxGbs2IOmxBs(base)} {
+}
+
+BnStatus Omx2IGraphicBufferSource::setSuspend(
+ bool suspend, int64_t timeUs) {
+ return BnStatus::fromStatusT(mBase->setSuspend(suspend, timeUs));
+}
+
+BnStatus Omx2IGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+ int64_t repeatAfterUs) {
+ return BnStatus::fromStatusT(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
+}
+
+BnStatus Omx2IGraphicBufferSource::setMaxFps(float maxFps) {
+ return BnStatus::fromStatusT(mBase->setMaxFps(maxFps));
+}
+
+BnStatus Omx2IGraphicBufferSource::setTimeLapseConfig(
+ double fps, double captureFps) {
+ return BnStatus::fromStatusT(mBase->setTimeLapseConfig(fps, captureFps));
+}
+
+BnStatus Omx2IGraphicBufferSource::setStartTimeUs(
+ int64_t startTimeUs) {
+ return BnStatus::fromStatusT(mBase->setStartTimeUs(startTimeUs));
+}
+
+BnStatus Omx2IGraphicBufferSource::setStopTimeUs(
+ int64_t stopTimeUs) {
+ return BnStatus::fromStatusT(mBase->setStopTimeUs(stopTimeUs));
+}
+
+BnStatus Omx2IGraphicBufferSource::getStopTimeOffsetUs(
+ int64_t *stopTimeOffsetUs) {
+ return BnStatus::fromStatusT(mBase->getStopTimeOffsetUs(stopTimeOffsetUs));
+}
+
+BnStatus Omx2IGraphicBufferSource::setColorAspects(
+ int32_t aspects) {
+ return BnStatus::fromStatusT(mBase->setColorAspects(aspects));
+}
+
+BnStatus Omx2IGraphicBufferSource::setTimeOffsetUs(
+ int64_t timeOffsetsUs) {
+ return BnStatus::fromStatusT(mBase->setTimeOffsetUs(timeOffsetsUs));
+}
+
+BnStatus Omx2IGraphicBufferSource::signalEndOfInputStream() {
+ return BnStatus::fromStatusT(mBase->signalEndOfInputStream());
+}
+
+BnStatus Omx2IGraphicBufferSource::configure(
+ const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+ if (omxNode == NULL) {
+ return BnStatus::fromServiceSpecificError(BAD_VALUE);
+ }
+
+ // Do setInputSurface() first, the node will try to enable metadata
+ // mode on input, and does necessary error checking. If this fails,
+ // we can't use this input surface on the node.
+ status_t err = omxNode->setInputSurface(mOMXBufferSource);
+ if (err != NO_ERROR) {
+ ALOGE("Unable to set input surface: %d", err);
+ return BnStatus::fromServiceSpecificError(err);
+ }
+
+ uint32_t consumerUsage;
+ if (omxNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ &consumerUsage, sizeof(consumerUsage)) != OK) {
+ consumerUsage = 0;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = 0; // kPortIndexInput
+
+ err = omxNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
+ if (err != NO_ERROR) {
+ ALOGE("Failed to get port definition: %d", err);
+ return BnStatus::fromServiceSpecificError(UNKNOWN_ERROR);
+ }
+
+ return BnStatus::fromStatusT(mBase->configure(
+ new OmxNodeWrapper(omxNode),
+ dataSpace,
+ def.nBufferCountActual,
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight,
+ consumerUsage));
+}
+
+} // namespace android
+
diff --git a/media/codec2/sfplugin/Omx2IGraphicBufferSource.h b/media/codec2/sfplugin/Omx2IGraphicBufferSource.h
new file mode 100644
index 0000000..20fd1ec
--- /dev/null
+++ b/media/codec2/sfplugin/Omx2IGraphicBufferSource.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OMX_2_IGRAPHICBUFFERSOURCE_H_
+#define OMX_2_IGRAPHICBUFFERSOURCE_H_
+
+#include <android/BnGraphicBufferSource.h>
+#include <media/stagefright/omx/OmxGraphicBufferSource.h>
+
+namespace android {
+
+using BnStatus = ::android::binder::Status;
+
+struct Omx2IGraphicBufferSource : public BnGraphicBufferSource {
+ sp<OmxGraphicBufferSource> mBase;
+ sp<IOMXBufferSource> mOMXBufferSource;
+ Omx2IGraphicBufferSource(sp<OmxGraphicBufferSource> const& base);
+ BnStatus configure(const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+ BnStatus setSuspend(bool suspend, int64_t timeUs) override;
+ BnStatus setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
+ BnStatus setMaxFps(float maxFps) override;
+ BnStatus setTimeLapseConfig(double fps, double captureFps) override;
+ BnStatus setStartTimeUs(int64_t startTimeUs) override;
+ BnStatus setStopTimeUs(int64_t stopTimeUs) override;
+ BnStatus getStopTimeOffsetUs(int64_t *stopTimeOffsetUs) override;
+ BnStatus setColorAspects(int32_t aspects) override;
+ BnStatus setTimeOffsetUs(int64_t timeOffsetsUs) override;
+ BnStatus signalEndOfInputStream() override;
+};
+
+} // namespace android
+
+#endif // OMX_2_IGRAPHICBUFFERSOURCE_H_
+
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index ca69810..b6ddfab 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -50,8 +50,10 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.bufferqueue@2.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"android.hardware.media.bufferpool@2.0",
"libbase",
"libbinder",
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 286c48a..af97e61 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -20,6 +20,8 @@
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
#include <cutils/native_handle.h>
#include <hardware/gralloc.h>
@@ -29,7 +31,7 @@
namespace android {
-namespace {
+namespace /* unnamed */ {
enum : uint64_t {
/**
* Usage mask that is passed through from gralloc to Codec 2.0 usage.
@@ -40,7 +42,7 @@
// verify that passthrough mask is within the platform mask
static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
-}
+} // unnamed
C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
// gralloc does not support WRITE_PROTECTED
@@ -59,39 +61,59 @@
(expected & PASSTHROUGH_USAGE_MASK));
}
-using ::android::hardware::graphics::allocator::V2_0::IAllocator;
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using ::android::hardware::graphics::mapper::V2_0::Error;
-using ::android::hardware::graphics::mapper::V2_0::IMapper;
-using ::android::hardware::graphics::mapper::V2_0::YCbCrLayout;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_vec;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using PixelFormat2 = ::android::hardware::graphics::common::V1_0::PixelFormat;
+using PixelFormat3 = ::android::hardware::graphics::common::V1_2::PixelFormat;
-namespace {
+using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
+using BufferDescriptor2 = ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
+using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
-struct BufferDescriptorInfo {
- IMapper::BufferDescriptorInfo mapperInfo;
+using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
+using BufferDescriptor3 = ::android::hardware::graphics::mapper::V3_0::BufferDescriptor;
+using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
+using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
+
+namespace /* unnamed */ {
+
+struct BufferDescriptorInfo2 {
+ IMapper2::BufferDescriptorInfo mapperInfo;
uint32_t stride;
};
-}
+struct BufferDescriptorInfo3 {
+ IMapper3::BufferDescriptorInfo mapperInfo;
+ uint32_t stride;
+};
/* ===================================== GRALLOC ALLOCATION ==================================== */
-static c2_status_t maperr2error(Error maperr) {
+c2_status_t maperr2error(Error2 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_CANNOT_DO;
+ case Error2::NONE: return C2_OK;
+ case Error2::BAD_DESCRIPTOR: return C2_BAD_VALUE;
+ case Error2::BAD_BUFFER: return C2_BAD_VALUE;
+ case Error2::BAD_VALUE: return C2_BAD_VALUE;
+ case Error2::NO_RESOURCES: return C2_NO_MEMORY;
+ case Error2::UNSUPPORTED: return C2_CANNOT_DO;
}
return C2_CORRUPTED;
}
-static
+c2_status_t maperr2error(Error3 maperr) {
+ switch (maperr) {
+ case Error3::NONE: return C2_OK;
+ case Error3::BAD_DESCRIPTOR: return C2_BAD_VALUE;
+ case Error3::BAD_BUFFER: return C2_BAD_VALUE;
+ case Error3::BAD_VALUE: return C2_BAD_VALUE;
+ case Error3::NO_RESOURCES: return C2_NO_MEMORY;
+ case Error3::UNSUPPORTED: return C2_CANNOT_DO;
+ }
+ return C2_CORRUPTED;
+}
+
bool native_handle_is_invalid(const native_handle_t *const handle) {
// perform basic validation of a native handle
if (handle == nullptr) {
@@ -230,23 +252,6 @@
return res;
}
- static native_handle_t* UnwrapNativeHandle(
- const C2Handle *const handle,
- uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
- const ExtraData *xd = getExtraData(handle);
- if (xd == nullptr || xd->magic != MAGIC) {
- return nullptr;
- }
- *generation = xd->generation;
- *igbp_id = unsigned(xd->igbp_id_lo) | uint64_t(unsigned(xd->igbp_id_hi)) << 32;
- *igbp_slot = xd->igbp_slot;
- native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
- if (res != nullptr) {
- memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
- }
- return res;
- }
-
static const C2HandleGralloc* Import(
const C2Handle *const handle,
uint32_t *width, uint32_t *height, uint32_t *format,
@@ -268,16 +273,12 @@
}
};
+} // unnamed namespace
+
native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
return C2HandleGralloc::UnwrapNativeHandle(handle);
}
-native_handle_t *UnwrapNativeCodec2GrallocHandle(
- const C2Handle *const handle,
- uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
- return C2HandleGralloc::UnwrapNativeHandle(handle, generation, igbp_id, igbp_slot);
-}
-
C2Handle *WrapNativeCodec2GrallocHandle(
const native_handle_t *const handle,
uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
@@ -309,8 +310,14 @@
// internal methods
// |handle| will be moved.
C2AllocationGralloc(
- const BufferDescriptorInfo &info,
- const sp<IMapper> &mapper,
+ const BufferDescriptorInfo2 &info,
+ const sp<IMapper2> &mapper,
+ hidl_handle &hidlHandle,
+ const C2HandleGralloc *const handle,
+ C2Allocator::id_t allocatorId);
+ C2AllocationGralloc(
+ const BufferDescriptorInfo3 &info,
+ const sp<IMapper3> &mapper,
hidl_handle &hidlHandle,
const C2HandleGralloc *const handle,
C2Allocator::id_t allocatorId);
@@ -318,8 +325,10 @@
c2_status_t status() const;
private:
- const BufferDescriptorInfo mInfo;
- const sp<IMapper> mMapper;
+ const BufferDescriptorInfo2 mInfo2{};
+ const sp<IMapper2> mMapper2{nullptr};
+ const BufferDescriptorInfo3 mInfo3{};
+ const sp<IMapper3> mMapper3{nullptr};
const hidl_handle mHidlHandle;
const C2HandleGralloc *mHandle;
buffer_handle_t mBuffer;
@@ -330,14 +339,31 @@
};
C2AllocationGralloc::C2AllocationGralloc(
- const BufferDescriptorInfo &info,
- const sp<IMapper> &mapper,
+ const BufferDescriptorInfo2 &info,
+ const sp<IMapper2> &mapper,
hidl_handle &hidlHandle,
const C2HandleGralloc *const handle,
C2Allocator::id_t allocatorId)
: C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
- mInfo(info),
- mMapper(mapper),
+ mInfo2(info),
+ mMapper2(mapper),
+ mHidlHandle(std::move(hidlHandle)),
+ mHandle(handle),
+ mBuffer(nullptr),
+ mLockedHandle(nullptr),
+ mLocked(false),
+ mAllocatorId(allocatorId) {
+}
+
+C2AllocationGralloc::C2AllocationGralloc(
+ const BufferDescriptorInfo3 &info,
+ const sp<IMapper3> &mapper,
+ hidl_handle &hidlHandle,
+ const C2HandleGralloc *const handle,
+ C2Allocator::id_t allocatorId)
+ : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
+ mInfo3(info),
+ mMapper3(mapper),
mHidlHandle(std::move(hidlHandle)),
mHandle(handle),
mBuffer(nullptr),
@@ -353,7 +379,17 @@
unmap(addr, C2Rect(), nullptr);
}
if (mBuffer) {
- mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
+ if (mMapper2) {
+ if (!mMapper2->freeBuffer(const_cast<native_handle_t *>(
+ mBuffer)).isOk()) {
+ ALOGE("failed transaction: freeBuffer");
+ }
+ } else {
+ if (!mMapper3->freeBuffer(const_cast<native_handle_t *>(
+ mBuffer)).isOk()) {
+ ALOGE("failed transaction: freeBuffer");
+ }
+ }
}
if (mHandle) {
native_handle_delete(
@@ -388,13 +424,29 @@
c2_status_t err = C2_OK;
if (!mBuffer) {
- mMapper->importBuffer(
- mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- mBuffer = static_cast<buffer_handle_t>(buffer);
- }
- });
+ if (mMapper2) {
+ if (!mMapper2->importBuffer(
+ mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ mBuffer = static_cast<buffer_handle_t>(buffer);
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: importBuffer");
+ return C2_CORRUPTED;
+ }
+ } else {
+ if (!mMapper3->importBuffer(
+ mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ mBuffer = static_cast<buffer_handle_t>(buffer);
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: importBuffer (@3.0)");
+ return C2_CORRUPTED;
+ }
+ }
if (err != C2_OK) {
ALOGD("importBuffer failed: %d", err);
return err;
@@ -409,30 +461,66 @@
if (mHandle) {
mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
}
- mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
- mBuffer, mInfo.mapperInfo.width, mInfo.mapperInfo.height,
- (uint32_t)mInfo.mapperInfo.format, mInfo.mapperInfo.usage, mInfo.stride,
- generation, igbp_id, igbp_slot);
+ if (mMapper2) {
+ mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
+ mBuffer, mInfo2.mapperInfo.width, mInfo2.mapperInfo.height,
+ (uint32_t)mInfo2.mapperInfo.format, mInfo2.mapperInfo.usage,
+ mInfo2.stride, generation, igbp_id, igbp_slot);
+ } else {
+ mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
+ mBuffer, mInfo3.mapperInfo.width, mInfo3.mapperInfo.height,
+ (uint32_t)mInfo3.mapperInfo.format, mInfo3.mapperInfo.usage,
+ mInfo3.stride, generation, igbp_id, igbp_slot);
+ }
}
- switch (mInfo.mapperInfo.format) {
- case PixelFormat::RGBA_1010102: {
+ PixelFormat3 format = mMapper2 ?
+ PixelFormat3(mInfo2.mapperInfo.format) :
+ PixelFormat3(mInfo3.mapperInfo.format);
+ switch (format) {
+ case PixelFormat3::RGBA_1010102: {
// TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
// Surface. In all other cases it is RGBA. We don't know which case it is here, so
// default to YUV for now.
void *pointer = nullptr;
- mMapper->lock(
- const_cast<native_handle_t *>(mBuffer),
- grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
- // TODO: fence
- hidl_handle(),
- [&err, &pointer](const auto &maperr, const auto &mapPointer) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- pointer = mapPointer;
- }
- });
+ if (mMapper2) {
+ if (!mMapper2->lock(
+ const_cast<native_handle_t *>(mBuffer),
+ grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto &maperr, const auto &mapPointer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: lock(RGBA_1010102)");
+ return C2_CORRUPTED;
+ }
+ } else {
+ if (!mMapper3->lock(
+ const_cast<native_handle_t *>(mBuffer),
+ grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto &maperr, const auto &mapPointer,
+ int32_t bytesPerPixel, int32_t bytesPerStride) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ (void)bytesPerPixel;
+ (void)bytesPerStride;
+ }).isOk()) {
+ ALOGE("failed transaction: lock(RGBA_1010102) (@3.0)");
+ return C2_CORRUPTED;
+ }
+ }
if (err != C2_OK) {
ALOGD("lock failed: %d", err);
return err;
@@ -445,10 +533,13 @@
layout->type = C2PlanarLayout::TYPE_YUVA;
layout->numPlanes = 4;
layout->rootPlanes = 1;
+ int32_t stride = mMapper2 ?
+ int32_t(mInfo2.stride) :
+ int32_t(mInfo3.stride);
layout->planes[C2PlanarLayout::PLANE_Y] = {
C2PlaneInfo::CHANNEL_Y, // channel
4, // colInc
- 4 * (int32_t)mInfo.stride, // rowInc
+ 4 * stride, // rowInc
1, // mColSampling
1, // mRowSampling
32, // allocatedDepth
@@ -461,7 +552,7 @@
layout->planes[C2PlanarLayout::PLANE_U] = {
C2PlaneInfo::CHANNEL_CB, // channel
4, // colInc
- 4 * (int32_t)mInfo.stride, // rowInc
+ 4 * stride, // rowInc
1, // mColSampling
1, // mRowSampling
32, // allocatedDepth
@@ -474,7 +565,7 @@
layout->planes[C2PlanarLayout::PLANE_V] = {
C2PlaneInfo::CHANNEL_CR, // channel
4, // colInc
- 4 * (int32_t)mInfo.stride, // rowInc
+ 4 * stride, // rowInc
1, // mColSampling
1, // mRowSampling
32, // allocatedDepth
@@ -487,7 +578,7 @@
layout->planes[C2PlanarLayout::PLANE_A] = {
C2PlaneInfo::CHANNEL_A, // channel
4, // colInc
- 4 * (int32_t)mInfo.stride, // rowInc
+ 4 * stride, // rowInc
1, // mColSampling
1, // mRowSampling
32, // allocatedDepth
@@ -500,23 +591,49 @@
break;
}
- case PixelFormat::RGBA_8888:
+ case PixelFormat3::RGBA_8888:
// TODO: alpha channel
// fall-through
- case PixelFormat::RGBX_8888: {
+ case PixelFormat3::RGBX_8888: {
void *pointer = nullptr;
- mMapper->lock(
- const_cast<native_handle_t *>(mBuffer),
- grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
- // TODO: fence
- hidl_handle(),
- [&err, &pointer](const auto &maperr, const auto &mapPointer) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- pointer = mapPointer;
- }
- });
+ if (mMapper2) {
+ if (!mMapper2->lock(
+ const_cast<native_handle_t *>(mBuffer),
+ grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto &maperr, const auto &mapPointer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: lock(RGBA_8888)");
+ return C2_CORRUPTED;
+ }
+ } else {
+ if (!mMapper3->lock(
+ const_cast<native_handle_t *>(mBuffer),
+ grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto &maperr, const auto &mapPointer,
+ int32_t bytesPerPixel, int32_t bytesPerStride) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ (void)bytesPerPixel;
+ (void)bytesPerStride;
+ }).isOk()) {
+ ALOGE("failed transaction: lock(RGBA_8888) (@3.0)");
+ return C2_CORRUPTED;
+ }
+ }
if (err != C2_OK) {
ALOGD("lock failed: %d", err);
return err;
@@ -527,10 +644,13 @@
layout->type = C2PlanarLayout::TYPE_RGB;
layout->numPlanes = 3;
layout->rootPlanes = 1;
+ int32_t stride = mMapper2 ?
+ int32_t(mInfo2.stride) :
+ int32_t(mInfo3.stride);
layout->planes[C2PlanarLayout::PLANE_R] = {
C2PlaneInfo::CHANNEL_R, // channel
4, // colInc
- 4 * (int32_t)mInfo.stride, // rowInc
+ 4 * stride, // rowInc
1, // mColSampling
1, // mRowSampling
8, // allocatedDepth
@@ -543,7 +663,7 @@
layout->planes[C2PlanarLayout::PLANE_G] = {
C2PlaneInfo::CHANNEL_G, // channel
4, // colInc
- 4 * (int32_t)mInfo.stride, // rowInc
+ 4 * stride, // rowInc
1, // mColSampling
1, // mRowSampling
8, // allocatedDepth
@@ -556,7 +676,7 @@
layout->planes[C2PlanarLayout::PLANE_B] = {
C2PlaneInfo::CHANNEL_B, // channel
4, // colInc
- 4 * (int32_t)mInfo.stride, // rowInc
+ 4 * stride, // rowInc
1, // mColSampling
1, // mRowSampling
8, // allocatedDepth
@@ -569,23 +689,65 @@
break;
}
- case PixelFormat::YCBCR_420_888:
+ case PixelFormat3::YCBCR_420_888:
// fall-through
- case PixelFormat::YV12:
+ case PixelFormat3::YV12:
// fall-through
default: {
+ struct YCbCrLayout {
+ void* y;
+ void* cb;
+ void* cr;
+ uint32_t yStride;
+ uint32_t cStride;
+ uint32_t chromaStep;
+ };
YCbCrLayout ycbcrLayout;
- mMapper->lockYCbCr(
- const_cast<native_handle_t *>(mBuffer), grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
- // TODO: fence
- hidl_handle(),
- [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- ycbcrLayout = mapLayout;
- }
- });
+ if (mMapper2) {
+ if (!mMapper2->lockYCbCr(
+ const_cast<native_handle_t *>(mBuffer), grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ ycbcrLayout = YCbCrLayout{
+ mapLayout.y,
+ mapLayout.cb,
+ mapLayout.cr,
+ mapLayout.yStride,
+ mapLayout.cStride,
+ mapLayout.chromaStep};
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: lockYCbCr");
+ return C2_CORRUPTED;
+ }
+ } else {
+ if (!mMapper3->lockYCbCr(
+ const_cast<native_handle_t *>(mBuffer), grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ ycbcrLayout = YCbCrLayout{
+ mapLayout.y,
+ mapLayout.cb,
+ mapLayout.cr,
+ mapLayout.yStride,
+ mapLayout.cStride,
+ mapLayout.chromaStep};
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: lockYCbCr (@3.0)");
+ return C2_CORRUPTED;
+ }
+ }
if (err != C2_OK) {
ALOGD("lockYCbCr failed: %d", err);
return err;
@@ -662,17 +824,37 @@
std::lock_guard<std::mutex> lock(mMappedLock);
c2_status_t err = C2_OK;
- mMapper->unlock(
- const_cast<native_handle_t *>(mBuffer),
- [&err, &fence](const auto &maperr, const auto &releaseFence) {
- // TODO
- (void) fence;
- (void) releaseFence;
- err = maperr2error(maperr);
- if (err == C2_OK) {
- // TODO: fence
- }
- });
+ if (mMapper2) {
+ if (!mMapper2->unlock(
+ const_cast<native_handle_t *>(mBuffer),
+ [&err, &fence](const auto &maperr, const auto &releaseFence) {
+ // TODO
+ (void) fence;
+ (void) releaseFence;
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ // TODO: fence
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: unlock");
+ return C2_CORRUPTED;
+ }
+ } else {
+ if (!mMapper3->unlock(
+ const_cast<native_handle_t *>(mBuffer),
+ [&err, &fence](const auto &maperr, const auto &releaseFence) {
+ // TODO
+ (void) fence;
+ (void) releaseFence;
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ // TODO: fence
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: unlock (@3.0)");
+ return C2_CORRUPTED;
+ }
+ }
if (err == C2_OK) {
mLocked = false;
}
@@ -713,8 +895,10 @@
private:
std::shared_ptr<C2Allocator::Traits> mTraits;
c2_status_t mInit;
- sp<IAllocator> mAllocator;
- sp<IMapper> mMapper;
+ sp<IAllocator2> mAllocator2;
+ sp<IMapper2> mMapper2;
+ sp<IAllocator3> mAllocator3;
+ sp<IMapper3> mMapper3;
const bool mBufferQueue;
};
@@ -734,10 +918,18 @@
mTraits = std::make_shared<C2Allocator::Traits>(traits);
// gralloc allocator is a singleton, so all objects share a global service
- mAllocator = IAllocator::getService();
- mMapper = IMapper::getService();
- if (mAllocator == nullptr || mMapper == nullptr) {
- mInit = C2_CORRUPTED;
+ mAllocator3 = IAllocator3::getService();
+ mMapper3 = IMapper3::getService();
+ if (!mAllocator3 || !mMapper3) {
+ mAllocator3 = nullptr;
+ mMapper3 = nullptr;
+ mAllocator2 = IAllocator2::getService();
+ mMapper2 = IMapper2::getService();
+ if (!mAllocator2 || !mMapper2) {
+ mAllocator2 = nullptr;
+ mMapper2 = nullptr;
+ mInit = C2_CORRUPTED;
+ }
}
}
@@ -748,84 +940,176 @@
ALOGV("allocating buffer with usage %#llx => %#llx",
(long long)usage.expected, (long long)grallocUsage);
- BufferDescriptorInfo info = {
- {
- width,
- height,
- 1u, // layerCount
- (PixelFormat)format,
- grallocUsage,
- },
- 0u, // stride placeholder
- };
c2_status_t err = C2_OK;
- BufferDescriptor desc;
- mMapper->createDescriptor(
- info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- desc = descriptor;
- }
- });
- if (err != C2_OK) {
- return err;
+ hidl_handle buffer{};
+
+ if (mMapper2) {
+ BufferDescriptorInfo2 info = {
+ {
+ width,
+ height,
+ 1u, // layerCount
+ PixelFormat2(format),
+ grallocUsage,
+ },
+ 0u, // stride placeholder
+ };
+ BufferDescriptor2 desc;
+ if (!mMapper2->createDescriptor(
+ info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ desc = descriptor;
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: createDescriptor");
+ return C2_CORRUPTED;
+ }
+ if (err != C2_OK) {
+ return err;
+ }
+
+ // IAllocator shares IMapper error codes.
+ if (!mAllocator2->allocate(
+ desc,
+ 1u,
+ [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
+ err = maperr2error(maperr);
+ if (err != C2_OK) {
+ return;
+ }
+ if (buffers.size() != 1u) {
+ err = C2_CORRUPTED;
+ return;
+ }
+ info.stride = stride;
+ buffer = buffers[0];
+ }).isOk()) {
+ ALOGE("failed transaction: allocate");
+ return C2_CORRUPTED;
+ }
+ if (err != C2_OK) {
+ return err;
+ }
+ allocation->reset(new C2AllocationGralloc(
+ info, mMapper2, buffer,
+ C2HandleGralloc::WrapAndMoveNativeHandle(
+ buffer.getNativeHandle(),
+ width, height,
+ format, grallocUsage, info.stride,
+ 0, 0, mBufferQueue ? ~0 : 0),
+ mTraits->id));
+ return C2_OK;
+ } else {
+ BufferDescriptorInfo3 info = {
+ {
+ width,
+ height,
+ 1u, // layerCount
+ PixelFormat3(format),
+ grallocUsage,
+ },
+ 0u, // stride placeholder
+ };
+ BufferDescriptor3 desc;
+ if (!mMapper3->createDescriptor(
+ info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ desc = descriptor;
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: createDescriptor");
+ return C2_CORRUPTED;
+ }
+ if (err != C2_OK) {
+ return err;
+ }
+
+ // IAllocator shares IMapper error codes.
+ if (!mAllocator3->allocate(
+ desc,
+ 1u,
+ [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
+ err = maperr2error(maperr);
+ if (err != C2_OK) {
+ return;
+ }
+ if (buffers.size() != 1u) {
+ err = C2_CORRUPTED;
+ return;
+ }
+ info.stride = stride;
+ buffer = buffers[0];
+ }).isOk()) {
+ ALOGE("failed transaction: allocate");
+ return C2_CORRUPTED;
+ }
+ if (err != C2_OK) {
+ return err;
+ }
+ allocation->reset(new C2AllocationGralloc(
+ info, mMapper3, buffer,
+ C2HandleGralloc::WrapAndMoveNativeHandle(
+ buffer.getNativeHandle(),
+ width, height,
+ format, grallocUsage, info.stride,
+ 0, 0, mBufferQueue ? ~0 : 0),
+ mTraits->id));
+ return C2_OK;
}
-
- // IAllocator shares IMapper error codes.
- hidl_handle buffer;
- mAllocator->allocate(
- desc,
- 1u,
- [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
- err = maperr2error(maperr);
- if (err != C2_OK) {
- return;
- }
- if (buffers.size() != 1u) {
- err = C2_CORRUPTED;
- return;
- }
- info.stride = stride;
- buffer = buffers[0];
- });
- if (err != C2_OK) {
- return err;
- }
-
-
- allocation->reset(new C2AllocationGralloc(
- info, mMapper, buffer,
- C2HandleGralloc::WrapAndMoveNativeHandle(
- buffer.getNativeHandle(),
- info.mapperInfo.width, info.mapperInfo.height,
- (uint32_t)info.mapperInfo.format, info.mapperInfo.usage, info.stride,
- 0, 0, mBufferQueue ? ~0 : 0),
- mTraits->id));
- return C2_OK;
}
c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
- BufferDescriptorInfo info;
- info.mapperInfo.layerCount = 1u;
- uint32_t generation;
- uint64_t igbp_id;
- uint32_t igbp_slot;
- const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
- handle,
- &info.mapperInfo.width, &info.mapperInfo.height,
- (uint32_t *)&info.mapperInfo.format, (uint64_t *)&info.mapperInfo.usage, &info.stride,
- &generation, &igbp_id, &igbp_slot);
- if (grallocHandle == nullptr) {
- return C2_BAD_VALUE;
+ if (mMapper2) {
+ BufferDescriptorInfo2 info;
+ info.mapperInfo.layerCount = 1u;
+ uint32_t generation;
+ uint64_t igbp_id;
+ uint32_t igbp_slot;
+ const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
+ handle,
+ &info.mapperInfo.width, &info.mapperInfo.height,
+ (uint32_t *)&info.mapperInfo.format,
+ (uint64_t *)&info.mapperInfo.usage,
+ &info.stride,
+ &generation, &igbp_id, &igbp_slot);
+ if (grallocHandle == nullptr) {
+ return C2_BAD_VALUE;
+ }
+
+ hidl_handle hidlHandle;
+ hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
+
+ allocation->reset(new C2AllocationGralloc(
+ info, mMapper2, hidlHandle, grallocHandle, mTraits->id));
+ return C2_OK;
+ } else {
+ BufferDescriptorInfo3 info;
+ info.mapperInfo.layerCount = 1u;
+ uint32_t generation;
+ uint64_t igbp_id;
+ uint32_t igbp_slot;
+ const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
+ handle,
+ &info.mapperInfo.width, &info.mapperInfo.height,
+ (uint32_t *)&info.mapperInfo.format,
+ (uint64_t *)&info.mapperInfo.usage,
+ &info.stride,
+ &generation, &igbp_id, &igbp_slot);
+ if (grallocHandle == nullptr) {
+ return C2_BAD_VALUE;
+ }
+
+ hidl_handle hidlHandle;
+ hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
+
+ allocation->reset(new C2AllocationGralloc(
+ info, mMapper3, hidlHandle, grallocHandle, mTraits->id));
+ return C2_OK;
}
-
- hidl_handle hidlHandle;
- hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
-
- allocation->reset(new C2AllocationGralloc(info, mMapper, hidlHandle, grallocHandle, mTraits->id));
- return C2_OK;
}
C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 5fa48a8..8304f74 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -413,6 +413,7 @@
}
sp<GraphicBuffer> &slotBuffer = mBuffers[slot];
+ uint32_t outGeneration;
if (bufferNeedsReallocation || !slotBuffer) {
if (!slotBuffer) {
slotBuffer = new GraphicBuffer();
@@ -421,7 +422,7 @@
// instead of a new allocation.
Return<void> transResult = mProducer->requestBuffer(
slot,
- [&status, &slotBuffer](
+ [&status, &slotBuffer, &outGeneration](
HStatus hStatus,
HBuffer const& hBuffer,
uint32_t generationNumber){
@@ -429,17 +430,23 @@
h2b(hBuffer, &slotBuffer) &&
slotBuffer) {
slotBuffer->setGenerationNumber(generationNumber);
+ outGeneration = generationNumber;
} else {
status = android::BAD_VALUE;
}
});
if (!transResult.isOk()) {
+ slotBuffer.clear();
return C2_BAD_VALUE;
} else if (status != android::NO_ERROR) {
slotBuffer.clear();
(void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
return C2_BAD_VALUE;
}
+ if (mGeneration == 0) {
+ // getting generation # lazily due to dequeue failure.
+ mGeneration = outGeneration;
+ }
}
if (slotBuffer) {
ALOGV("buffer wraps %llu %d", (unsigned long long)mProducerId, slot);
@@ -563,6 +570,10 @@
producerId = static_cast<uint64_t>(transResult);
// TODO: provide gneration number from parameter.
haveGeneration = getGenerationNumber(producer, &generation);
+ if (!haveGeneration) {
+ ALOGW("get generationNumber failed %llu",
+ (unsigned long long)producerId);
+ }
}
int migrated = 0;
{
@@ -580,10 +591,10 @@
}
}
int32_t oldGeneration = mGeneration;
- if (producer && haveGeneration) {
+ if (producer) {
mProducer = producer;
mProducerId = producerId;
- mGeneration = generation;
+ mGeneration = haveGeneration ? generation : 0;
} else {
mProducer = nullptr;
mProducerId = 0;
@@ -591,7 +602,7 @@
ALOGW("invalid producer producer(%d), generation(%d)",
(bool)producer, haveGeneration);
}
- if (mProducer) { // migrate buffers
+ if (mProducer && haveGeneration) { // migrate buffers
for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
std::shared_ptr<C2BufferQueueBlockPoolData> data =
mPoolDatas[i].lock();
diff --git a/media/libmedia/xsd/vts/Android.bp b/media/libmedia/xsd/vts/Android.bp
index b590a12..4739504 100644
--- a/media/libmedia/xsd/vts/Android.bp
+++ b/media/libmedia/xsd/vts/Android.bp
@@ -24,6 +24,7 @@
"libxml2",
],
shared_libs: [
+ "libbase",
"liblog",
],
cflags: [
diff --git a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
index ff9b060..7729d52 100644
--- a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
+++ b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/properties.h>
#include "utility/ValidateXml.h"
TEST(CheckConfig, mediaProfilesValidation) {
@@ -21,8 +25,12 @@
"Verify that the media profiles file "
"is valid according to the schema");
- const char* location = "/vendor/etc";
+ std::string mediaSettingsPath = android::base::GetProperty("media.settings.xml", "");
+ if (mediaSettingsPath.empty()) {
+ mediaSettingsPath.assign("/vendor/etc/media_profiles_V1_0.xml");
+ }
- EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS("media_profiles_V1_0.xml", {location},
+ EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(android::base::Basename(mediaSettingsPath).c_str(),
+ {android::base::Dirname(mediaSettingsPath).c_str()},
"/data/local/tmp/media_profiles.xsd");
}
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 2cd920a..4653711 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1578,7 +1578,7 @@
}
if (mPreparing) {
- notifyPreparedAndCleanup(finalStatus);
+ notifyPreparedAndCleanup(finalStatus == ERROR_END_OF_STREAM ? OK : finalStatus);
mPreparing = false;
} else if (mSentPauseOnBuffering) {
sendCacheStats();
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp
index 48414d7..5880e32 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp
@@ -52,7 +52,11 @@
PV_BitstreamByteAlign(stream);
BitstreamReadBits32(stream, resync_marker_length);
- *next_MB = (int) BitstreamReadBits16(stream, nbits);
+ int mbnum = (int) BitstreamReadBits16(stream, nbits);
+ if (mbnum < 0) {
+ return PV_FAIL;
+ }
+ *next_MB = mbnum;
// if (*next_MB <= video->mbnum) /* needs more investigation */
// *next_MB = video->mbnum+1;
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index f18f789..679b091 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -1355,6 +1355,14 @@
int tmpHeight = (tmpDisplayHeight + 15) & -16;
int tmpWidth = (tmpDisplayWidth + 15) & -16;
+ if (tmpWidth > video->width)
+ {
+ // while allowed by the spec, this decoder does not actually
+ // support an increase in size.
+ ALOGE("width increase not supported");
+ status = PV_FAIL;
+ goto return_point;
+ }
if (tmpHeight * tmpWidth > video->size)
{
// This is just possibly "b/37079296".
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index e260cae..7d03d98 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -72,7 +72,6 @@
cfi: true,
},
- compile_multilib: "32",
}
cc_library_shared {
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
index 9d7c57d..16c8af8 100644
--- a/media/libstagefright/xmlparser/api/current.txt
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -138,7 +138,12 @@
public class Variant {
ctor public Variant();
+ method public java.util.List<media.codecs.Alias> getAlias_optional();
+ method public java.util.List<media.codecs.Quirk> getAttribute_optional();
+ method public java.util.List<media.codecs.Feature> getFeature_optional();
+ method public java.util.List<media.codecs.Limit> getLimit_optional();
method public String getName();
+ method public java.util.List<media.codecs.Quirk> getQuirk_optional();
method public void setName(String);
}
diff --git a/media/libstagefright/xmlparser/media_codecs.xsd b/media/libstagefright/xmlparser/media_codecs.xsd
index 63ec5d0..3b5681f 100644
--- a/media/libstagefright/xmlparser/media_codecs.xsd
+++ b/media/libstagefright/xmlparser/media_codecs.xsd
@@ -107,6 +107,13 @@
<xs:attribute name="value" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Variant">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="Quirk" type="Quirk"/>
+ <xs:element name="Attribute" type="Quirk"/>
+ <xs:element name="Alias" type="Alias"/>
+ <xs:element name="Limit" type="Limit"/>
+ <xs:element name="Feature" type="Feature"/>
+ </xs:choice>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Setting">
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a6730fc..1d4dacd 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2396,7 +2396,8 @@
for (size_t i = 0; i < mInputs.size(); i++) {
const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
if (input->clientsList().size() == 0
- || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) {
+ || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())
+ || (input->getAudioPort()->getFlags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
inputsToClose.push_back(mInputs.keyAt(i));
} else {
bool close = false;
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
index 9525ad2..8ebaa2b 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
@@ -58,8 +58,8 @@
entry = staticInfo.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
if (entry.count == 5) {
- mInstrinsicCalibration.reserve(5);
- mInstrinsicCalibration.insert(mInstrinsicCalibration.end(), entry.data.f,
+ mIntrinsicCalibration.reserve(5);
+ mIntrinsicCalibration.insert(mIntrinsicCalibration.end(), entry.data.f,
entry.data.f + 5);
} else {
ALOGW("%s: Intrinsic calibration absent from camera characteristics!", __FUNCTION__);
@@ -323,12 +323,12 @@
depthPhoto.mMaxJpegSize = maxDepthJpegSize;
// The camera intrinsic calibration layout is as follows:
// [focalLengthX, focalLengthY, opticalCenterX, opticalCenterY, skew]
- if (mInstrinsicCalibration.size() == 5) {
- memcpy(depthPhoto.mInstrinsicCalibration, mInstrinsicCalibration.data(),
- sizeof(depthPhoto.mInstrinsicCalibration));
- depthPhoto.mIsInstrinsicCalibrationValid = 1;
+ if (mIntrinsicCalibration.size() == 5) {
+ memcpy(depthPhoto.mIntrinsicCalibration, mIntrinsicCalibration.data(),
+ sizeof(depthPhoto.mIntrinsicCalibration));
+ depthPhoto.mIsIntrinsicCalibrationValid = 1;
} else {
- depthPhoto.mIsInstrinsicCalibrationValid = 0;
+ depthPhoto.mIsIntrinsicCalibrationValid = 0;
}
// The camera lens distortion contains the following lens correction coefficients.
// [kappa_1, kappa_2, kappa_3 kappa_4, kappa_5]
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.h b/services/camera/libcameraservice/api2/DepthCompositeStream.h
index 1bf31f4..975c59b 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.h
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.h
@@ -124,7 +124,7 @@
ssize_t mMaxJpegSize;
std::vector<std::tuple<size_t, size_t>> mSupportedDepthSizes;
- std::vector<float> mInstrinsicCalibration, mLensDistortion;
+ std::vector<float> mIntrinsicCalibration, mLensDistortion;
bool mIsLogicalCamera;
void* mDepthPhotoLibHandle;
process_depth_photo_frame mDepthPhotoProcess;
diff --git a/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp b/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
index fc79150..3c90de0 100644
--- a/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
+++ b/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
@@ -61,6 +61,13 @@
using dynamic_depth::Profile;
using dynamic_depth::Profiles;
+template<>
+struct std::default_delete<jpeg_compress_struct> {
+ inline void operator()(jpeg_compress_struct* cinfo) const {
+ jpeg_destroy_compress(cinfo);
+ }
+};
+
namespace android {
namespace camera3 {
@@ -118,16 +125,16 @@
bool mSuccess;
} dmgr;
- jpeg_compress_struct cinfo = {};
+ std::unique_ptr<jpeg_compress_struct> cinfo = std::make_unique<jpeg_compress_struct>();
jpeg_error_mgr jerr;
// Initialize error handling with standard callbacks, but
// then override output_message (to print to ALOG) and
// error_exit to set a flag and print a message instead
// of killing the whole process.
- cinfo.err = jpeg_std_error(&jerr);
+ cinfo->err = jpeg_std_error(&jerr);
- cinfo.err->output_message = [](j_common_ptr cinfo) {
+ cinfo->err->output_message = [](j_common_ptr cinfo) {
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
@@ -135,7 +142,7 @@
ALOGE("libjpeg error: %s", buffer);
};
- cinfo.err->error_exit = [](j_common_ptr cinfo) {
+ cinfo->err->error_exit = [](j_common_ptr cinfo) {
(*cinfo->err->output_message)(cinfo);
if(cinfo->client_data) {
auto & dmgr = *static_cast<CustomJpegDestMgr*>(cinfo->client_data);
@@ -144,12 +151,12 @@
};
// Now that we initialized some callbacks, let's create our compressor
- jpeg_create_compress(&cinfo);
+ jpeg_create_compress(cinfo.get());
dmgr.mBuffer = static_cast<JOCTET*>(out);
dmgr.mBufferSize = maxOutSize;
dmgr.mEncodedSize = 0;
dmgr.mSuccess = true;
- cinfo.client_data = static_cast<void*>(&dmgr);
+ cinfo->client_data = static_cast<void*>(&dmgr);
// These lambdas become C-style function pointers and as per C++11 spec
// may not capture anything.
@@ -171,28 +178,28 @@
dmgr.mEncodedSize = dmgr.mBufferSize - dmgr.free_in_buffer;
ALOGV("%s:%d Done with jpeg: %zu", __FUNCTION__, __LINE__, dmgr.mEncodedSize);
};
- cinfo.dest = reinterpret_cast<struct jpeg_destination_mgr*>(&dmgr);
- cinfo.image_width = width;
- cinfo.image_height = height;
- cinfo.input_components = 1;
- cinfo.in_color_space = JCS_GRAYSCALE;
+ cinfo->dest = static_cast<struct jpeg_destination_mgr*>(&dmgr);
+ cinfo->image_width = width;
+ cinfo->image_height = height;
+ cinfo->input_components = 1;
+ cinfo->in_color_space = JCS_GRAYSCALE;
// Initialize defaults and then override what we want
- jpeg_set_defaults(&cinfo);
+ jpeg_set_defaults(cinfo.get());
- jpeg_set_quality(&cinfo, jpegQuality, 1);
- jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);
- cinfo.raw_data_in = 0;
- cinfo.dct_method = JDCT_IFAST;
+ jpeg_set_quality(cinfo.get(), jpegQuality, 1);
+ jpeg_set_colorspace(cinfo.get(), JCS_GRAYSCALE);
+ cinfo->raw_data_in = 0;
+ cinfo->dct_method = JDCT_IFAST;
- cinfo.comp_info[0].h_samp_factor = 1;
- cinfo.comp_info[1].h_samp_factor = 1;
- cinfo.comp_info[2].h_samp_factor = 1;
- cinfo.comp_info[0].v_samp_factor = 1;
- cinfo.comp_info[1].v_samp_factor = 1;
- cinfo.comp_info[2].v_samp_factor = 1;
+ cinfo->comp_info[0].h_samp_factor = 1;
+ cinfo->comp_info[1].h_samp_factor = 1;
+ cinfo->comp_info[2].h_samp_factor = 1;
+ cinfo->comp_info[0].v_samp_factor = 1;
+ cinfo->comp_info[1].v_samp_factor = 1;
+ cinfo->comp_info[2].v_samp_factor = 1;
- jpeg_start_compress(&cinfo, TRUE);
+ jpeg_start_compress(cinfo.get(), TRUE);
if (exifOrientation != ExifOrientation::ORIENTATION_UNDEFINED) {
std::unique_ptr<ExifUtils> utils(ExifUtils::create());
@@ -204,19 +211,19 @@
if (utils->generateApp1()) {
const uint8_t* exifBuffer = utils->getApp1Buffer();
size_t exifBufferSize = utils->getApp1Length();
- jpeg_write_marker(&cinfo, JPEG_APP0 + 1, static_cast<const JOCTET*>(exifBuffer),
+ jpeg_write_marker(cinfo.get(), JPEG_APP0 + 1, static_cast<const JOCTET*>(exifBuffer),
exifBufferSize);
} else {
ALOGE("%s: Unable to generate App1 buffer", __FUNCTION__);
}
}
- for (size_t i = 0; i < cinfo.image_height; i++) {
+ for (size_t i = 0; i < cinfo->image_height; i++) {
auto currentRow = static_cast<JSAMPROW>(in + i*width);
- jpeg_write_scanlines(&cinfo, ¤tRow, /*num_lines*/1);
+ jpeg_write_scanlines(cinfo.get(), ¤tRow, /*num_lines*/1);
}
- jpeg_finish_compress(&cinfo);
+ jpeg_finish_compress(cinfo.get());
actualSize = dmgr.mEncodedSize;
if (dmgr.mSuccess) {
@@ -430,12 +437,12 @@
return BAD_VALUE;
}
- // It is not possible to generate an imaging model without instrinsic calibration.
- if (inputFrame.mIsInstrinsicCalibrationValid) {
+ // It is not possible to generate an imaging model without intrinsic calibration.
+ if (inputFrame.mIsIntrinsicCalibrationValid) {
// The camera intrinsic calibration layout is as follows:
// [focalLengthX, focalLengthY, opticalCenterX, opticalCenterY, skew]
- const dynamic_depth::Point<double> focalLength(inputFrame.mInstrinsicCalibration[0],
- inputFrame.mInstrinsicCalibration[1]);
+ const dynamic_depth::Point<double> focalLength(inputFrame.mIntrinsicCalibration[0],
+ inputFrame.mIntrinsicCalibration[1]);
size_t width = inputFrame.mMainJpegWidth;
size_t height = inputFrame.mMainJpegHeight;
if (switchDimensions) {
@@ -444,9 +451,9 @@
}
const Dimension imageSize(width, height);
ImagingModelParams imagingParams(focalLength, imageSize);
- imagingParams.principal_point.x = inputFrame.mInstrinsicCalibration[2];
- imagingParams.principal_point.y = inputFrame.mInstrinsicCalibration[3];
- imagingParams.skew = inputFrame.mInstrinsicCalibration[4];
+ imagingParams.principal_point.x = inputFrame.mIntrinsicCalibration[2];
+ imagingParams.principal_point.y = inputFrame.mIntrinsicCalibration[3];
+ imagingParams.skew = inputFrame.mIntrinsicCalibration[4];
// The camera lens distortion contains the following lens correction coefficients.
// [kappa_1, kappa_2, kappa_3 kappa_4, kappa_5]
diff --git a/services/camera/libcameraservice/common/DepthPhotoProcessor.h b/services/camera/libcameraservice/common/DepthPhotoProcessor.h
index 6a2fbff..ba5ca9e 100644
--- a/services/camera/libcameraservice/common/DepthPhotoProcessor.h
+++ b/services/camera/libcameraservice/common/DepthPhotoProcessor.h
@@ -39,8 +39,8 @@
size_t mMaxJpegSize;
uint8_t mJpegQuality;
uint8_t mIsLogical;
- float mInstrinsicCalibration[5];
- uint8_t mIsInstrinsicCalibrationValid;
+ float mIntrinsicCalibration[5];
+ uint8_t mIsIntrinsicCalibrationValid;
float mLensDistortion[5];
uint8_t mIsLensDistortionValid;
DepthPhotoOrientation mOrientation;
@@ -57,8 +57,8 @@
mMaxJpegSize(0),
mJpegQuality(100),
mIsLogical(0),
- mInstrinsicCalibration{0.f},
- mIsInstrinsicCalibrationValid(0),
+ mIntrinsicCalibration{0.f},
+ mIsIntrinsicCalibrationValid(0),
mLensDistortion{0.f},
mIsLensDistortionValid(0),
mOrientation(DepthPhotoOrientation::DEPTH_ORIENTATION_0_DEGREES) {}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 9771f9e..a8e80fa 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -4364,7 +4364,7 @@
int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
- if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
dstStream->setFormatOverride(false);
dstStream->setDataSpaceOverride(false);
if (dst->format != overrideFormat) {
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 2df084b..fd9b4b0 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -68,7 +68,7 @@
mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX),
mBufferLimitLatency(kBufferLimitLatencyBinSize),
mFormatOverridden(false),
- mOriginalFormat(-1),
+ mOriginalFormat(format),
mDataSpaceOverridden(false),
mOriginalDataSpace(HAL_DATASPACE_UNKNOWN),
mPhysicalCameraId(physicalCameraId),
@@ -125,9 +125,6 @@
void Camera3Stream::setFormatOverride(bool formatOverridden) {
mFormatOverridden = formatOverridden;
- if (formatOverridden && mOriginalFormat == -1) {
- mOriginalFormat = camera3_stream::format;
- }
}
bool Camera3Stream::isFormatOverridden() const {
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 533318f..67afd0f 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -582,9 +582,9 @@
static const int32_t kBufferLimitLatencyBinSize = 33; //in ms
CameraLatencyHistogram mBufferLimitLatency;
- //Keep track of original format in case it gets overridden
+ //Keep track of original format when the stream is created in case it gets overridden
bool mFormatOverridden;
- int mOriginalFormat;
+ const int mOriginalFormat;
//Keep track of original dataSpace in case it gets overridden
bool mDataSpaceOverridden;