Merge "CameraMetadata: avoid memory leak in case allocate_camera_metadata fails." into sc-dev
diff --git a/apex/mediatranscoding.rc b/apex/mediatranscoding.rc
index 24306a2..ae9f8ba 100644
--- a/apex/mediatranscoding.rc
+++ b/apex/mediatranscoding.rc
@@ -8,4 +8,5 @@
ioprio rt 4
# Restrict to little cores only with system-background cpuset.
writepid /dev/cpuset/system-background/tasks
+ interface aidl media.transcoding
disabled
diff --git a/camera/Android.bp b/camera/Android.bp
index 2c01496..6878c20 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -119,6 +119,8 @@
"aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl",
"aidl/android/hardware/camera2/ICameraDeviceUser.aidl",
"aidl/android/hardware/camera2/ICameraOfflineSession.aidl",
+ "aidl/android/hardware/camera2/ICameraInjectionCallback.aidl",
+ "aidl/android/hardware/camera2/ICameraInjectionSession.aidl",
],
path: "aidl",
}
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 459ad15..873d738 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -20,6 +20,8 @@
import android.hardware.ICameraClient;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.ICameraInjectionCallback;
+import android.hardware.camera2.ICameraInjectionSession;
import android.hardware.camera2.params.VendorTagDescriptor;
import android.hardware.camera2.params.VendorTagDescriptorCache;
import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
@@ -161,6 +163,9 @@
boolean supportsCameraApi(String cameraId, int apiVersion);
// Determines if a cameraId is a hidden physical camera of a logical multi-camera.
boolean isHiddenPhysicalCamera(String cameraId);
+ // Inject the external camera to replace the internal camera session.
+ ICameraInjectionSession injectCamera(String packageName, String internalCamId,
+ String externalCamId, in ICameraInjectionCallback CameraInjectionCallback);
void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder);
diff --git a/camera/aidl/android/hardware/camera2/ICameraInjectionCallback.aidl b/camera/aidl/android/hardware/camera2/ICameraInjectionCallback.aidl
new file mode 100644
index 0000000..9791352
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/ICameraInjectionCallback.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.hardware.camera2;
+
+import android.hardware.camera2.ICameraInjectionSession;
+
+/**
+ * Binder interface used to call back the error state injected by the external camera,
+ * and camera service can be switched back to internal camera when binder signals process death.
+ *
+ * @hide
+ */
+interface ICameraInjectionCallback
+{
+ // Error codes for onInjectionError
+ // To indicate all invalid error codes
+ const int ERROR_INJECTION_INVALID_ERROR = -1;
+ // To indicate the camera injection session has encountered a fatal error, such as injection
+ // init failure, configure failure or injecting failure etc.
+ const int ERROR_INJECTION_SESSION = 0;
+ // To indicate the camera service has encountered a fatal error.
+ const int ERROR_INJECTION_SERVICE = 1;
+ // To indicate the injection camera does not support certain camera functions, such as
+ // unsupport stream format, no capture/record function or no multi-camera function etc.
+ // When this error occurs, the default processing is still in the inject state, and the app is
+ // notified to display an error message and a black screen.
+ const int ERROR_INJECTION_UNSUPPORTED = 2;
+
+ oneway void onInjectionError(int errorCode);
+}
diff --git a/camera/aidl/android/hardware/camera2/ICameraInjectionSession.aidl b/camera/aidl/android/hardware/camera2/ICameraInjectionSession.aidl
new file mode 100644
index 0000000..c31c30b
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/ICameraInjectionSession.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.hardware.camera2;
+
+/** @hide */
+interface ICameraInjectionSession
+{
+ oneway void stopInjection();
+}
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index d1b4ede..1609c7b 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -4079,6 +4079,34 @@
ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION =
// int64[4*n]
ACAMERA_SCALER_START + 22,
+ /**
+ * <p>Whether the camera device supports multi-resolution input or output streams</p>
+ *
+ * <p>Type: byte (acamera_metadata_enum_android_scaler_multi_resolution_stream_supported_t)</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>A logical multi-camera or an ultra high resolution camera may support multi-resolution
+ * input or output streams. With multi-resolution output streams, the camera device is able
+ * to output different resolution images depending on the current active physical camera or
+ * pixel mode. With multi-resolution input streams, the camera device can reprocess images
+ * of different resolutions from different physical cameras or sensor pixel modes.</p>
+ * <p>When set to TRUE:
+ * * For a logical multi-camera, the camera framework derives
+ * android.scaler.multiResolutionStreamConfigurationMap by combining the
+ * ACAMERA_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS from its physical
+ * cameras.
+ * * For an ultra-high resolution sensor camera, the camera framework directly copies
+ * the value of ACAMERA_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS to
+ * android.scaler.multiResolutionStreamConfigurationMap.</p>
+ *
+ * @see ACAMERA_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS
+ */
+ ACAMERA_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED = // byte (acamera_metadata_enum_android_scaler_multi_resolution_stream_supported_t)
+ ACAMERA_SCALER_START + 24,
ACAMERA_SCALER_END,
/**
@@ -9116,6 +9144,14 @@
} acamera_metadata_enum_android_scaler_available_stream_configurations_maximum_resolution_t;
+// ACAMERA_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED
+typedef enum acamera_metadata_enum_acamera_scaler_multi_resolution_stream_supported {
+ ACAMERA_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_FALSE = 0,
+
+ ACAMERA_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE = 1,
+
+} acamera_metadata_enum_android_scaler_multi_resolution_stream_supported_t;
+
// ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
typedef enum acamera_metadata_enum_acamera_sensor_reference_illuminant1 {
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 3257f71..e0db1c4 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -382,7 +382,8 @@
return;
}
- mPlugin->notifyResolution(width, height);
+ auto hResult = mPlugin->notifyResolution(width, height);
+ ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
}
status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t> &sessionId) {
@@ -392,7 +393,8 @@
return mInitCheck;
}
- return toStatusT(mPlugin->setMediaDrmSession(toHidlVec(sessionId)));
+ auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId));
+ return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
}
status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const {
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 253a1fa..40d1e0c 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -888,7 +888,7 @@
Return<void> hResult;
if (mPluginV1_2 != NULL) {
- Return<void> hResult = mPluginV1_2->getProvisionRequest_1_2(
+ hResult = mPluginV1_2->getProvisionRequest_1_2(
toHidlString(certType), toHidlString(certAuthority),
[&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
const hidl_string& hDefaultUrl) {
@@ -900,7 +900,7 @@
}
);
} else {
- Return<void> hResult = mPlugin->getProvisionRequest(
+ hResult = mPlugin->getProvisionRequest(
toHidlString(certType), toHidlString(certAuthority),
[&](Status status, const hidl_vec<uint8_t>& hRequest,
const hidl_string& hDefaultUrl) {
@@ -1522,22 +1522,38 @@
return metricsString;
}
-bool DrmHal::requiresSecureDecoder(const char *mime) const {
+status_t DrmHal::requiresSecureDecoder(const char *mime, bool *required) const {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
return false;
}
- return mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
+ auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (required) {
+ *required = hResult;
+ }
+ return OK;
}
-bool DrmHal::requiresSecureDecoder(const char *mime,
- DrmPlugin::SecurityLevel securityLevel) const {
+status_t DrmHal::requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
return false;
}
auto hLevel = toHidlSecurityLevel(securityLevel);
- return mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
+ auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (required) {
+ *required = hResult;
+ }
+ return OK;
}
status_t DrmHal::setPlaybackId(Vector<uint8_t> const &sessionId, const char *playbackId) {
@@ -1545,10 +1561,8 @@
if (mPluginV1_4 == NULL) {
return ERROR_UNSUPPORTED;
}
- drm::V1_0::Status err = mPluginV1_4->setPlaybackId(
- toHidlVec(sessionId),
- hidl_string(playbackId));
- return toStatusT(err);
+ auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
+ return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
}
status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const {
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index ed3848d..0b117a3 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -82,7 +82,17 @@
auto factory = Hal::getService(instance);
if (factory != nullptr) {
instances[instance.c_str()] = Hal::descriptor;
- if (!uuid || factory->isCryptoSchemeSupported(uuid)) {
+ if (!uuid) {
+ factories.push_back(factory);
+ continue;
+ }
+ auto supported = factory->isCryptoSchemeSupported(uuid);
+ if (!supported.isOk()) {
+ LOG2BE(uuid, "isCryptoSchemeSupported txn failed: %s",
+ supported.description().c_str());
+ continue;
+ }
+ if (supported) {
factories.push_back(factory);
}
}
@@ -114,30 +124,42 @@
sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory> &factory,
const uint8_t uuid[16], const char *appPackageName) {
sp<::V1_0::IDrmPlugin> plugin;
- factory->createPlugin(toHidlArray16(uuid), hidl_string(appPackageName),
- [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
- if (status != ::V1_0::Status::OK) {
- LOG2BE(uuid, "MakeDrmPlugin failed: %d", status);
- return;
- }
- plugin = hPlugin;
- });
- return plugin;
+ auto err = factory->createPlugin(
+ toHidlArray16(uuid), hidl_string(appPackageName),
+ [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
+ if (status != ::V1_0::Status::OK) {
+ LOG2BE(uuid, "MakeDrmPlugin failed: %d", status);
+ return;
+ }
+ plugin = hPlugin;
+ });
+ if (err.isOk()) {
+ return plugin;
+ } else {
+ LOG2BE(uuid, "MakeDrmPlugin txn failed: %s", err.description().c_str());
+ return nullptr;
+ }
}
sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory> &factory,
const uint8_t uuid[16], const void *initData,
size_t initDataSize) {
sp<::V1_0::ICryptoPlugin> plugin;
- factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize),
- [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
- if (status != ::V1_0::Status::OK) {
- LOG2BE(uuid, "MakeCryptoPlugin failed: %d", status);
- return;
- }
- plugin = hPlugin;
- });
- return plugin;
+ auto err = factory->createPlugin(
+ toHidlArray16(uuid), toHidlVec(initData, initDataSize),
+ [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
+ if (status != ::V1_0::Status::OK) {
+ LOG2BE(uuid, "MakeCryptoPlugin failed: %d", status);
+ return;
+ }
+ plugin = hPlugin;
+ });
+ if (err.isOk()) {
+ return plugin;
+ } else {
+ LOG2BE(uuid, "MakeCryptoPlugin txn failed: %s", err.description().c_str());
+ return nullptr;
+ }
}
} // namespace
@@ -304,6 +326,9 @@
std::string GetExceptionMessage(status_t err, const char *msg,
const Vector<::V1_4::LogMessage> &logs) {
+ std::string ruler("==============================");
+ std::string header("Beginning of DRM Plugin Log");
+ std::string footer("End of DRM Plugin Log");
String8 msg8;
if (msg) {
msg8 += msg;
@@ -311,6 +336,7 @@
}
auto errStr = StrCryptoError(err);
msg8 += errStr.c_str();
+ msg8 += String8::format("\n%s %s %s", ruler.c_str(), header.c_str(), ruler.c_str());
for (auto log : logs) {
time_t seconds = log.timeMs / 1000;
@@ -322,9 +348,10 @@
}
char p = logPriorityToChar(log.priority);
- msg8 += String8::format("\n%s.%03d %c %s", timeStr.c_str(), ms, p, log.message.c_str());
+ msg8 += String8::format("\n %s.%03d %c %s", timeStr.c_str(), ms, p, log.message.c_str());
}
+ msg8 += String8::format("\n%s %s %s", ruler.c_str(), footer.c_str(), ruler.c_str());
return msg8.c_str();
}
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index c5206fa..7eb1dec 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -179,11 +179,10 @@
virtual status_t setListener(const sp<IDrmClient>& listener);
- virtual bool requiresSecureDecoder(const char *mime) const;
+ virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
- virtual bool requiresSecureDecoder(
- const char *mime,
- DrmPlugin::SecurityLevel securityLevel) const;
+ virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const;
virtual status_t setPlaybackId(
Vector<uint8_t> const &sessionId,
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index 80c5c9b..a88784d 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -154,12 +154,10 @@
virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
- virtual bool requiresSecureDecoder(
- const char *mime) const = 0;
+ virtual status_t requiresSecureDecoder(const char *mime, bool *required) const = 0;
- virtual bool requiresSecureDecoder(
- const char *mime,
- DrmPlugin::SecurityLevel securityLevel) const = 0;
+ virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const = 0;
virtual status_t setPlaybackId(
Vector<uint8_t> const &sessionId,
diff --git a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
index 0ac879c..e03a896 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
@@ -26,7 +26,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::SubSample;
@@ -79,7 +79,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index c49d5fe..6c68532 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -57,6 +57,7 @@
"android.hardware.drm@1.1",
"android.hardware.drm@1.2",
"android.hardware.drm@1.3",
+ "android.hardware.drm@1.4",
"libbase",
"libbinder",
"libcrypto",
@@ -110,18 +111,18 @@
}
cc_binary {
- name: "android.hardware.drm@1.3-service.clearkey",
+ name: "android.hardware.drm@1.4-service.clearkey",
defaults: ["clearkey_service_defaults"],
srcs: ["service.cpp"],
- init_rc: ["android.hardware.drm@1.3-service.clearkey.rc"],
- vintf_fragments: ["manifest_android.hardware.drm@1.3-service.clearkey.xml"],
+ init_rc: ["android.hardware.drm@1.4-service.clearkey.rc"],
+ vintf_fragments: ["manifest_android.hardware.drm@1.4-service.clearkey.xml"],
}
cc_binary {
- name: "android.hardware.drm@1.3-service-lazy.clearkey",
- overrides: ["android.hardware.drm@1.3-service.clearkey"],
+ name: "android.hardware.drm@1.4-service-lazy.clearkey",
+ overrides: ["android.hardware.drm@1.4-service.clearkey"],
defaults: ["clearkey_service_defaults"],
srcs: ["serviceLazy.cpp"],
- init_rc: ["android.hardware.drm@1.3-service-lazy.clearkey.rc"],
- vintf_fragments: ["manifest_android.hardware.drm@1.3-service.clearkey.xml"],
+ init_rc: ["android.hardware.drm@1.4-service-lazy.clearkey.rc"],
+ vintf_fragments: ["manifest_android.hardware.drm@1.4-service.clearkey.xml"],
}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
index 657a42f..d81f875 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
@@ -21,7 +21,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
sp<Buffer> decodeBase64(const std::string &s) {
@@ -169,7 +169,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
index 75f8395..dcb76f4 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
@@ -21,7 +21,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
Buffer::Buffer(size_t capacity)
@@ -47,7 +47,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
index bfb0e05..4ab33d3 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
@@ -22,7 +22,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_3 {
+namespace V1_4 {
namespace clearkey {
extern "C" {
@@ -38,7 +38,7 @@
} // extern "C"
} // namespace clearkey
-} // namespace V1_3
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
index a6ed3bd..0bebc3b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
@@ -27,11 +27,11 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_3 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_2::clearkey::CryptoPlugin;
+using ::android::hardware::drm::V1_4::clearkey::CryptoPlugin;
Return<bool> CryptoFactory::isCryptoSchemeSupported(
const hidl_array<uint8_t, 16> &uuid)
@@ -63,7 +63,7 @@
}
} // namespace clearkey
-} // namespace V1_3
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index 302dd39..b92f236 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -27,7 +27,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::BufferType;
@@ -236,7 +236,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4.
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
index 2415b6f..0385d8f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
@@ -38,7 +38,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
bool DeviceFiles::StoreLicense(
@@ -246,7 +246,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
index 1ce8269..14cb5c1 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
@@ -31,13 +31,13 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_3 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::Status;
using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::drm::V1_2::clearkey::DrmPlugin;
-using ::android::hardware::drm::V1_2::clearkey::SessionLibrary;
+using ::android::hardware::drm::V1_4::clearkey::DrmPlugin;
+using ::android::hardware::drm::V1_4::clearkey::SessionLibrary;
using ::android::hardware::Void;
Return<bool> DrmFactory::isCryptoSchemeSupported(
@@ -105,7 +105,7 @@
}
} // namespace clearkey
-} // namespace V1_3
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 6f69110..4318af4 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "hidl_ClearKeyPlugin"
#include <utils/Log.h>
+#include <chrono>
#include <stdio.h>
#include <inttypes.h>
@@ -58,7 +59,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) {
@@ -635,6 +636,68 @@
return Void();
}
+Return<void> DrmPlugin::getLogMessages(
+ getLogMessages_cb _hidl_cb) {
+ using std::chrono::duration_cast;
+ using std::chrono::milliseconds;
+ using std::chrono::system_clock;
+
+ auto timeMillis = duration_cast<milliseconds>(
+ system_clock::now().time_since_epoch()).count();
+
+ //TODO(b/182525516) Stub out for now
+ std::vector<LogMessage> logs = {
+ { timeMillis, LogPriority::DEFAULT, std::string() }};
+ _hidl_cb(drm::V1_4::Status::OK, toHidlVec(logs));
+ return Void();
+}
+
+Return<bool> DrmPlugin::requiresSecureDecoder(
+ const hidl_string& mime, SecurityLevel level) {
+ if (!strncasecmp(mime.c_str(), "video/", 6)) {
+ // Type is video, so check level to see if we require a secure decoder.
+ return level == SecurityLevel::HW_SECURE_DECODE;
+ } else {
+ // Type is not video, so never require a secure decoder.
+ return false;
+ }
+}
+
+Return<bool> DrmPlugin::requiresSecureDecoderDefault(const hidl_string& mime) {
+ UNUSED(mime);
+ // Clearkey only supports SW_SECURE_CRYPTO, so we always returns false
+ // regardless of mime type.
+ return false;
+}
+
+Return<Status> DrmPlugin::setPlaybackId(
+ const hidl_vec<uint8_t>& sessionId,
+ const hidl_string& playbackId) {
+ if (sessionId.size() == 0) {
+ ALOGE("Invalid empty session id");
+ return Status::BAD_VALUE;
+ }
+
+ std::vector<uint8_t> sid = toVector(sessionId);
+ sp<Session> session = mSessionLibrary->findSession(sid);
+ if (!session.get()) {
+ return Status::ERROR_DRM_SESSION_NOT_OPENED;
+ }
+
+ std::map<std::vector<uint8_t>, std::string>::iterator itr =
+ mPlaybackId.find(sid);
+ if (itr != mPlaybackId.end()) {
+ mPlaybackId[sid] = playbackId;
+ } else {
+ if (!mPlaybackId.insert(
+ std::pair<std::vector<uint8_t>, std::string>(sid, playbackId)).second) {
+ ALOGE("Failed to set playback Id");
+ return Status::ERROR_DRM_UNKNOWN;
+ }
+ }
+ return Status::OK;
+}
+
Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
SecurityLevel level) {
if (sessionId.size() == 0) {
@@ -702,8 +765,21 @@
"close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
};
- DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
- closeSessionNotOpenedMetric } };
+ // Set the setPlaybackId metric.
+ DrmMetricGroup::Attribute setPlaybackIdOKAttribute = {
+ "status", DrmMetricGroup::ValueType::INT64_TYPE,
+ (int64_t) Status::OK, 0.0, ""
+ };
+ std::string playbackId = mPlaybackId.begin()->second;
+ DrmMetricGroup::Value setPlaybackIdMetricValue = {
+ "value", DrmMetricGroup::ValueType::STRING_TYPE, 0, 0, playbackId.c_str()
+ };
+ DrmMetricGroup::Metric setPlaybackIdMetric = {
+ "set_playback_id", { setPlaybackIdOKAttribute }, { setPlaybackIdMetricValue }
+ };
+
+ DrmMetricGroup metrics = {{ openSessionMetric, closeSessionMetric,
+ closeSessionNotOpenedMetric, setPlaybackIdMetric }};
_hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
return Void();
@@ -907,7 +983,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
index 8513434..eccc843 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
@@ -31,7 +31,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
namespace {
@@ -180,7 +180,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
index 99668a7..45cc775 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
@@ -36,7 +36,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
JsonWebKey::JsonWebKey() {
@@ -271,7 +271,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
index 32cf2dc..e61db3f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
@@ -11,7 +11,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
std::string MemoryFileSystem::GetFileName(const std::string& path) {
@@ -93,7 +93,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
index a9d7016..cf668d4 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
@@ -28,7 +28,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::KeyValue;
@@ -95,7 +95,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
index 99fb30f..88afcc4 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::hidl_string;
@@ -86,7 +86,7 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
new file mode 100644
index 0000000..46aba88
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
@@ -0,0 +1,18 @@
+service vendor.drm-clearkey-hal-1-4 /vendor/bin/hw/android.hardware.drm@1.4-service-lazy.clearkey
+ interface android.hardware.drm@1.0::ICryptoFactory clearkey
+ interface android.hardware.drm@1.0::IDrmFactory clearkey
+ interface android.hardware.drm@1.1::ICryptoFactory clearkey
+ interface android.hardware.drm@1.1::IDrmFactory clearkey
+ interface android.hardware.drm@1.2::ICryptoFactory clearkey
+ interface android.hardware.drm@1.2::IDrmFactory clearkey
+ interface android.hardware.drm@1.3::ICryptoFactory clearkey
+ interface android.hardware.drm@1.3::IDrmFactory clearkey
+ interface android.hardware.drm@1.4::ICryptoFactory clearkey
+ interface android.hardware.drm@1.4::IDrmFactory clearkey
+ disabled
+ oneshot
+ class hal
+ user media
+ group media mediadrm
+ ioprio rt 4
+ writepid /dev/cpuset/foreground/tasks
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
new file mode 100644
index 0000000..8186933
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
@@ -0,0 +1,16 @@
+service vendor.drm-clearkey-hal-1-4 /vendor/bin/hw/android.hardware.drm@1.4-service.clearkey
+ interface android.hardware.drm@1.0::ICryptoFactory clearkey
+ interface android.hardware.drm@1.0::IDrmFactory clearkey
+ interface android.hardware.drm@1.1::ICryptoFactory clearkey
+ interface android.hardware.drm@1.1::IDrmFactory clearkey
+ interface android.hardware.drm@1.2::ICryptoFactory clearkey
+ interface android.hardware.drm@1.2::IDrmFactory clearkey
+ interface android.hardware.drm@1.3::ICryptoFactory clearkey
+ interface android.hardware.drm@1.3::IDrmFactory clearkey
+ interface android.hardware.drm@1.4::ICryptoFactory clearkey
+ interface android.hardware.drm@1.4::IDrmFactory clearkey
+ class hal
+ user media
+ group media mediadrm
+ ioprio rt 4
+ writepid /dev/cpuset/foreground/tasks
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
index 721f4c0..97794f7 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
@@ -22,7 +22,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::Status;
@@ -42,7 +42,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
index ec30cc1..2349f23 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
@@ -25,7 +25,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::sp;
@@ -38,7 +38,7 @@
void encodeBase64Url(const void *data, size_t size, std::string *out);
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
index c497e37..66aaa73 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
@@ -25,7 +25,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::sp;
@@ -54,7 +54,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
index b83ce69..8e47c45 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
@@ -22,7 +22,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
static const std::string kVendorKey("vendor");
@@ -55,7 +55,7 @@
static const uint8_t kMetricsData[] = { 0 };
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
index 03c434e..cd18029 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::KeyValue;
@@ -48,7 +48,7 @@
void operator=(const TypeName&) = delete;
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
index c1c188e..d4a8a17 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
@@ -17,17 +17,17 @@
#ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
#define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
-#include <android/hardware/drm/1.3/ICryptoFactory.h>
-#include <android/hardware/drm/1.3/IDrmFactory.h>
+#include <android/hardware/drm/1.4/ICryptoFactory.h>
+#include <android/hardware/drm/1.4/IDrmFactory.h>
namespace android {
namespace hardware {
namespace drm {
-namespace V1_3 {
+namespace V1_4 {
namespace clearkey {
-using ::android::hardware::drm::V1_3::ICryptoFactory;
-using ::android::hardware::drm::V1_3::IDrmFactory;
+using ::android::hardware::drm::V1_4::ICryptoFactory;
+using ::android::hardware::drm::V1_4::IDrmFactory;
extern "C" {
IDrmFactory* createDrmFactory();
@@ -35,7 +35,7 @@
}
} // namespace clearkey
-} // namespace V1_3
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
index cb4811b..e6b541f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
@@ -18,17 +18,17 @@
#define CLEARKEY_CRYPTO_FACTORY_H_
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.3/ICryptoFactory.h>
+#include <android/hardware/drm/1.4/ICryptoFactory.h>
#include "ClearKeyTypes.h"
namespace android {
namespace hardware {
namespace drm {
-namespace V1_3 {
+namespace V1_4 {
namespace clearkey {
-using ::android::hardware::drm::V1_3::ICryptoFactory;
+using ::android::hardware::drm::V1_4::ICryptoFactory;
using ::android::hardware::drm::V1_0::ICryptoPlugin;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
@@ -52,7 +52,7 @@
};
} // namespace clearkey
-} // namespace V1_3
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
index 23a64fa..a7b2427 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
@@ -34,7 +34,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
namespace drm = ::android::hardware::drm;
@@ -114,7 +114,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
index 554ae59..6466ac3 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
@@ -20,9 +20,11 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
+using ::android::hardware::drm::V1_2::clearkey::OfflineFile;
+
class DeviceFiles {
public:
typedef enum {
@@ -63,7 +65,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
index 63234cf..fea1ec8 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
@@ -17,15 +17,15 @@
#ifndef CLEARKEY_DRM_FACTORY_H_
#define CLEARKEY_DRM_FACTORY_H_
-#include <android/hardware/drm/1.2/IDrmPlugin.h>
-#include <android/hardware/drm/1.3/IDrmFactory.h>
+#include <android/hardware/drm/1.4/IDrmPlugin.h>
+#include <android/hardware/drm/1.4/IDrmFactory.h>
#include "ClearKeyTypes.h"
namespace android {
namespace hardware {
namespace drm {
-namespace V1_3 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_1::SecurityLevel;
@@ -63,7 +63,7 @@
};
} // namespace clearkey
-} // namespace V1_3
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index 894985b..5d6e3da 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -17,7 +17,7 @@
#ifndef CLEARKEY_DRM_PLUGIN_H_
#define CLEARKEY_DRM_PLUGIN_H_
-#include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.4/IDrmPlugin.h>
#include <android/hardware/drm/1.2/IDrmPluginListener.h>
#include <map>
@@ -32,7 +32,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
namespace drm = ::android::hardware::drm;
@@ -50,9 +50,12 @@
using drm::V1_1::HdcpLevel;
using drm::V1_1::SecureStopRelease;
using drm::V1_1::SecurityLevel;
-using drm::V1_2::IDrmPlugin;
using drm::V1_2::KeySetId;
using drm::V1_2::OfflineLicenseState;
+using drm::V1_4::clearkey::DeviceFiles;
+using drm::V1_4::clearkey::Session;
+using drm::V1_4::clearkey::SessionLibrary;
+using drm::V1_4::IDrmPlugin;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
@@ -199,6 +202,18 @@
Return<Status> setPropertyByteArray(
const hidl_string& name, const hidl_vec<uint8_t>& value) override;
+ Return<void> getLogMessages(
+ getLogMessages_cb _hidl_cb) override;
+
+ Return<Status> setPlaybackId(
+ const hidl_vec<uint8_t>& sessionId,
+ const hidl_string& playbackId) override;
+
+ Return<bool> requiresSecureDecoder(
+ const hidl_string& mime, SecurityLevel level) override;
+
+ Return<bool> requiresSecureDecoderDefault(const hidl_string& mime) override;
+
Return<Status> setCipherAlgorithm(
const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
if (sessionId.size() == 0 || algorithm.size() == 0) {
@@ -398,6 +413,7 @@
std::map<std::string, std::string> mStringProperties;
std::map<std::string, std::vector<uint8_t> > mByteArrayProperties;
std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap;
+ std::map<std::vector<uint8_t>, std::string> mPlaybackId;
std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
sp<IDrmPluginListener> mListener;
sp<IDrmPluginListener_V1_2> mListenerV1_2;
@@ -424,7 +440,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
index 889f511..59338c9 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::drm::V1_0::Status;
@@ -49,7 +49,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
index e57470c..40a2d74 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
@@ -23,7 +23,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
class JsonWebKey {
@@ -54,7 +54,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
index 6ac0e2c..a90d818 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
@@ -15,7 +15,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
// Using android file system requires clearkey plugin to update
@@ -64,7 +64,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
index a159e5a..05cb8c8 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
@@ -27,7 +27,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
namespace drm = ::android::hardware::drm;
@@ -73,7 +73,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
index 1e567b8..5e77438 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
@@ -26,7 +26,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::sp;
@@ -58,7 +58,7 @@
};
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
index b0f8607..22eeccd 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef CLEARKEY_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT
-#define CLEARKEY_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT
+#ifndef CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
+#define CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
#include <vector>
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace drm {
-namespace V1_2 {
+namespace V1_4 {
namespace clearkey {
using ::android::hardware::hidl_array;
@@ -80,9 +80,9 @@
}
} // namespace clearkey
-} // namespace V1_2
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
-#endif // CLEARKEY_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT
+#endif // CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml
new file mode 100644
index 0000000..31ddb5f
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.drm</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.4::ICryptoFactory/clearkey</fqname>
+ <fqname>@1.4::IDrmFactory/clearkey</fqname>
+ </hal>
+</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/service.cpp b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
index b62baae..d3d6905 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/service.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
@@ -25,10 +25,10 @@
using ::android::hardware::joinRpcThreadpool;
using ::android::sp;
-using android::hardware::drm::V1_3::ICryptoFactory;
-using android::hardware::drm::V1_3::IDrmFactory;
-using android::hardware::drm::V1_3::clearkey::CryptoFactory;
-using android::hardware::drm::V1_3::clearkey::DrmFactory;
+using android::hardware::drm::V1_4::ICryptoFactory;
+using android::hardware::drm::V1_4::IDrmFactory;
+using android::hardware::drm::V1_4::clearkey::CryptoFactory;
+using android::hardware::drm::V1_4::clearkey::DrmFactory;
int main(int /* argc */, char** /* argv */) {
sp<IDrmFactory> drmFactory = new DrmFactory;
diff --git a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
index b3e0179..358b5cc 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
@@ -25,10 +25,10 @@
using ::android::hardware::joinRpcThreadpool;
using ::android::sp;
-using android::hardware::drm::V1_3::ICryptoFactory;
-using android::hardware::drm::V1_3::IDrmFactory;
-using android::hardware::drm::V1_3::clearkey::CryptoFactory;
-using android::hardware::drm::V1_3::clearkey::DrmFactory;
+using android::hardware::drm::V1_4::ICryptoFactory;
+using android::hardware::drm::V1_4::IDrmFactory;
+using android::hardware::drm::V1_4::clearkey::CryptoFactory;
+using android::hardware::drm::V1_4::clearkey::DrmFactory;
using android::hardware::LazyServiceRegistrar;
int main(int /* argc */, char** /* argv */) {
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/bufferpool/2.0/BufferPoolClient.cpp
index 9308b81..cda23ff 100644
--- a/media/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/bufferpool/2.0/BufferPoolClient.cpp
@@ -29,7 +29,7 @@
namespace V2_0 {
namespace implementation {
-static constexpr int64_t kReceiveTimeoutUs = 1000000; // 100ms
+static constexpr int64_t kReceiveTimeoutUs = 2000000; // 2s
static constexpr int kPostMaxRetry = 3;
static constexpr int kCacheTtlUs = 1000000; // TODO: tune
static constexpr size_t kMaxCachedBufferCount = 64;
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index bab651f..0b121ad 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -28,6 +28,7 @@
#include <media/stagefright/foundation/AUtils.h>
#include <C2Debug.h>
+#include <Codec2Mapper.h>
#include <C2PlatformSupport.h>
#include <Codec2BufferUtils.h>
#include <SimpleC2Interface.h>
@@ -213,6 +214,42 @@
.withFields({C2F(mSyncFramePeriod, value).any()})
.withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps)
.build());
+
+ addParameter(
+ DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::input(
+ 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(ColorAspectsSetter)
+ .build());
+
+ addParameter(
+ DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::output(
+ 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mCodedColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mCodedColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mCodedColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mCodedColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(CodedColorAspectsSetter, mColorAspects)
+ .build());
}
static C2R InputDelaySetter(
@@ -359,6 +396,33 @@
return C2R::Ok();
}
+ static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
+ (void)mayBlock;
+ if (me.v.range > C2Color::RANGE_OTHER) {
+ me.set().range = C2Color::RANGE_OTHER;
+ }
+ if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+ me.set().primaries = C2Color::PRIMARIES_OTHER;
+ }
+ if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+ me.set().transfer = C2Color::TRANSFER_OTHER;
+ }
+ if (me.v.matrix > C2Color::MATRIX_OTHER) {
+ me.set().matrix = C2Color::MATRIX_OTHER;
+ }
+ return C2R::Ok();
+ }
+
+ static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+ const C2P<C2StreamColorAspectsInfo::input> &coded) {
+ (void)mayBlock;
+ me.set().range = coded.v.range;
+ me.set().primaries = coded.v.primaries;
+ me.set().transfer = coded.v.transfer;
+ me.set().matrix = coded.v.matrix;
+ return C2R::Ok();
+ }
+
IV_PROFILE_T getProfile_l() const {
switch (mProfileLevel->profile) {
case PROFILE_AVC_CONSTRAINED_BASELINE: [[fallthrough]];
@@ -418,6 +482,9 @@
std::shared_ptr<C2StreamGopTuning::output> getGop_l() const { return mGop; }
std::shared_ptr<C2StreamPictureQuantizationTuning::output> getPictureQuantization_l() const
{ return mPictureQuantization; }
+ std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() const {
+ return mCodedColorAspects;
+ }
private:
std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -430,6 +497,8 @@
std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
std::shared_ptr<C2StreamGopTuning::output> mGop;
std::shared_ptr<C2StreamPictureQuantizationTuning::output> mPictureQuantization;
+ std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
+ std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
};
#define ive_api_function ih264e_api_function
@@ -980,6 +1049,55 @@
return;
}
+c2_status_t C2SoftAvcEnc::setVuiParams()
+{
+ ColorAspects sfAspects;
+ if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
+ sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->range, &sfAspects.mRange)) {
+ sfAspects.mRange = android::ColorAspects::RangeUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->matrix, &sfAspects.mMatrixCoeffs)) {
+ sfAspects.mMatrixCoeffs = android::ColorAspects::MatrixUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->transfer, &sfAspects.mTransfer)) {
+ sfAspects.mTransfer = android::ColorAspects::TransferUnspecified;
+ }
+ int32_t primaries, transfer, matrixCoeffs;
+ bool range;
+ ColorUtils::convertCodecColorAspectsToIsoAspects(sfAspects,
+ &primaries,
+ &transfer,
+ &matrixCoeffs,
+ &range);
+ ih264e_vui_ip_t s_vui_params_ip {};
+ ih264e_vui_op_t s_vui_params_op {};
+
+ s_vui_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_vui_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_VUI_PARAMS;
+
+ s_vui_params_ip.u1_video_signal_type_present_flag = 1;
+ s_vui_params_ip.u1_colour_description_present_flag = 1;
+ s_vui_params_ip.u1_colour_primaries = primaries;
+ s_vui_params_ip.u1_transfer_characteristics = transfer;
+ s_vui_params_ip.u1_matrix_coefficients = matrixCoeffs;
+ s_vui_params_ip.u1_video_full_range_flag = range;
+
+ s_vui_params_ip.u4_size = sizeof(ih264e_vui_ip_t);
+ s_vui_params_op.u4_size = sizeof(ih264e_vui_op_t);
+
+ IV_STATUS_T status = ih264e_api_function(mCodecCtx, &s_vui_params_ip,
+ &s_vui_params_op);
+ if(status != IV_SUCCESS)
+ {
+ ALOGE("Unable to set vui params = 0x%x\n",
+ s_vui_params_op.u4_error_code);
+ return C2_CORRUPTED;
+ }
+ return C2_OK;
+}
+
c2_status_t C2SoftAvcEnc::initEncoder() {
IV_STATUS_T status;
WORD32 level;
@@ -999,6 +1117,7 @@
mIInterval = mIntf->getSyncFramePeriod_l();
mIDRInterval = mIntf->getSyncFramePeriod_l();
gop = mIntf->getGop_l();
+ mColorAspects = mIntf->getCodedColorAspects_l();
}
if (gop && gop->flexCount() > 0) {
uint32_t syncInterval = 1;
@@ -1223,6 +1342,9 @@
/* Video control Set Profile params */
setProfileParams();
+ /* Video control Set VUI params */
+ setVuiParams();
+
/* Video control Set in Encode header mode */
setEncMode(IVE_ENC_MODE_HEADER);
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.h b/media/codec2/components/avc/C2SoftAvcEnc.h
index 673a282..baf33e2 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.h
+++ b/media/codec2/components/avc/C2SoftAvcEnc.h
@@ -196,6 +196,7 @@
std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+ std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
uint32_t mOutBufferSize;
UWORD32 mHeaderGenerated;
@@ -229,6 +230,7 @@
c2_status_t setProfileParams();
c2_status_t setDeblockParams();
c2_status_t setVbvParams();
+ c2_status_t setVuiParams();
void logVersion();
c2_status_t setEncodeArgs(
ive_video_encode_ip_t *ps_encode_ip,
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 436a2c4..4bc1777 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -25,6 +25,7 @@
#include <media/stagefright/foundation/AUtils.h>
#include <C2Debug.h>
+#include <Codec2Mapper.h>
#include <C2PlatformSupport.h>
#include <Codec2BufferUtils.h>
#include <SimpleC2Interface.h>
@@ -208,6 +209,42 @@
.withSetter(
Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps)
.build());
+
+ addParameter(
+ DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::input(
+ 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(ColorAspectsSetter)
+ .build());
+
+ addParameter(
+ DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::output(
+ 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mCodedColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mCodedColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mCodedColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mCodedColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(CodedColorAspectsSetter, mColorAspects)
+ .build());
}
static C2R InputDelaySetter(
@@ -402,6 +439,34 @@
std::shared_ptr<C2StreamGopTuning::output> getGop_l() const {
return mGop;
}
+ static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
+ (void)mayBlock;
+ if (me.v.range > C2Color::RANGE_OTHER) {
+ me.set().range = C2Color::RANGE_OTHER;
+ }
+ if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+ me.set().primaries = C2Color::PRIMARIES_OTHER;
+ }
+ if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+ me.set().transfer = C2Color::TRANSFER_OTHER;
+ }
+ if (me.v.matrix > C2Color::MATRIX_OTHER) {
+ me.set().matrix = C2Color::MATRIX_OTHER;
+ }
+ return C2R::Ok();
+ }
+ static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+ const C2P<C2StreamColorAspectsInfo::input> &coded) {
+ (void)mayBlock;
+ me.set().range = coded.v.range;
+ me.set().primaries = coded.v.primaries;
+ me.set().transfer = coded.v.transfer;
+ me.set().matrix = coded.v.matrix;
+ return C2R::Ok();
+ }
+ std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() {
+ return mCodedColorAspects;
+ }
private:
std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -415,6 +480,8 @@
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
std::shared_ptr<C2StreamGopTuning::output> mGop;
+ std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
+ std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
};
static size_t GetCPUCoreCount() {
@@ -533,6 +600,32 @@
mBframes = maxBframes;
}
}
+ ColorAspects sfAspects;
+ if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
+ sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->range, &sfAspects.mRange)) {
+ sfAspects.mRange = android::ColorAspects::RangeUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->matrix, &sfAspects.mMatrixCoeffs)) {
+ sfAspects.mMatrixCoeffs = android::ColorAspects::MatrixUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->transfer, &sfAspects.mTransfer)) {
+ sfAspects.mTransfer = android::ColorAspects::TransferUnspecified;
+ }
+ int32_t primaries, transfer, matrixCoeffs;
+ bool range;
+ ColorUtils::convertCodecColorAspectsToIsoAspects(sfAspects,
+ &primaries,
+ &transfer,
+ &matrixCoeffs,
+ &range);
+ mEncParams.s_out_strm_prms.i4_vui_enable = 1;
+ mEncParams.s_vui_sei_prms.u1_colour_description_present_flag = 1;
+ mEncParams.s_vui_sei_prms.u1_colour_primaries = primaries;
+ mEncParams.s_vui_sei_prms.u1_transfer_characteristics = transfer;
+ mEncParams.s_vui_sei_prms.u1_matrix_coefficients = matrixCoeffs;
+ mEncParams.s_vui_sei_prms.u1_video_full_range_flag = range;
// update configuration
mEncParams.s_src_prms.i4_width = mSize->width;
mEncParams.s_src_prms.i4_height = mSize->height;
@@ -629,6 +722,7 @@
mQuality = mIntf->getQuality_l();
mGop = mIntf->getGop_l();
mRequestSync = mIntf->getRequestSync_l();
+ mColorAspects = mIntf->getCodedColorAspects_l();
}
c2_status_t status = initEncParams();
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index 5ea4602..9dbf682 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -89,6 +89,7 @@
std::shared_ptr<C2StreamQualityTuning::output> mQuality;
std::shared_ptr<C2StreamGopTuning::output> mGop;
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+ std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
#ifdef FILE_DUMP_ENABLE
char mInFile[200];
char mOutFile[200];
diff --git a/media/codec2/components/raw/C2SoftRawDec.cpp b/media/codec2/components/raw/C2SoftRawDec.cpp
index 31ca705..a03d4e2 100644
--- a/media/codec2/components/raw/C2SoftRawDec.cpp
+++ b/media/codec2/components/raw/C2SoftRawDec.cpp
@@ -87,7 +87,9 @@
.withFields({C2F(mPcmEncodingInfo, value).oneOf({
C2Config::PCM_16,
C2Config::PCM_8,
- C2Config::PCM_FLOAT})
+ C2Config::PCM_FLOAT,
+ C2Config::PCM_24,
+ C2Config::PCM_32})
})
.withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
.build());
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
index 5e34b8a..c98b802 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.h
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -345,6 +345,42 @@
.withFields({C2F(mRequestSync, value).oneOf({ C2_FALSE, C2_TRUE }) })
.withSetter(Setter<decltype(*mRequestSync)>::NonStrictValueWithNoDeps)
.build());
+
+ addParameter(
+ DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::input(
+ 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(ColorAspectsSetter)
+ .build());
+
+ addParameter(
+ DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::output(
+ 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mCodedColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mCodedColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mCodedColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mCodedColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(CodedColorAspectsSetter, mColorAspects)
+ .build());
}
static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) {
@@ -415,6 +451,31 @@
double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value;
return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.);
}
+ static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
+ (void)mayBlock;
+ if (me.v.range > C2Color::RANGE_OTHER) {
+ me.set().range = C2Color::RANGE_OTHER;
+ }
+ if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+ me.set().primaries = C2Color::PRIMARIES_OTHER;
+ }
+ if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+ me.set().transfer = C2Color::TRANSFER_OTHER;
+ }
+ if (me.v.matrix > C2Color::MATRIX_OTHER) {
+ me.set().matrix = C2Color::MATRIX_OTHER;
+ }
+ return C2R::Ok();
+ }
+ static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+ const C2P<C2StreamColorAspectsInfo::input> &coded) {
+ (void)mayBlock;
+ me.set().range = coded.v.range;
+ me.set().primaries = coded.v.primaries;
+ me.set().transfer = coded.v.transfer;
+ me.set().matrix = coded.v.matrix;
+ return C2R::Ok();
+ }
private:
std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -427,6 +488,8 @@
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
+ std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
+ std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
};
} // namespace android
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index f8aa672..9d9ed70 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -75,6 +75,10 @@
enum tiling_mode_t : uint32_t; ///< tiling modes
};
+struct C2PlatformConfig {
+ enum encoding_quality_level_t : uint32_t; ///< encoding quality level
+};
+
namespace {
enum C2ParamIndexKind : C2Param::type_index_t {
@@ -259,7 +263,11 @@
kParamIndexTunnelHandle, // int32[]
kParamIndexTunnelSystemTime, // int64
+ // dmabuf allocator
kParamIndexStoreDmaBufUsage, // store, struct
+
+ // encoding quality requirements
+ kParamIndexEncodingQualityLevel, // encoders, enum
};
}
@@ -384,6 +392,7 @@
namespace {
+// Codec bases are ordered by their date of introduction to the code base.
enum : uint32_t {
_C2_PL_MP2V_BASE = 0x1000,
_C2_PL_AAC_BASE = 0x2000,
@@ -394,12 +403,16 @@
_C2_PL_VP9_BASE = 0x7000,
_C2_PL_DV_BASE = 0x8000,
_C2_PL_AV1_BASE = 0x9000,
+ _C2_PL_VP8_BASE = 0xA000,
+ _C2_PL_MPEGH_BASE = 0xB000, // MPEG-H 3D Audio
C2_PROFILE_LEVEL_VENDOR_START = 0x70000000,
};
}
+// Profiles and levels for each codec are ordered based on how they are ordered in the
+// corresponding standard documents at introduction, and chronologically afterwards.
enum C2Config::profile_t : uint32_t {
PROFILE_UNUSED = 0, ///< profile is not used by this media type
@@ -547,6 +560,19 @@
PROFILE_AV1_0 = _C2_PL_AV1_BASE, ///< AV1 Profile 0 (4:2:0, 8 to 10 bit)
PROFILE_AV1_1, ///< AV1 Profile 1 (8 to 10 bit)
PROFILE_AV1_2, ///< AV1 Profile 2 (8 to 12 bit)
+
+ // VP8 profiles
+ PROFILE_VP8_0 = _C2_PL_VP8_BASE, ///< VP8 Profile 0
+ PROFILE_VP8_1, ///< VP8 Profile 1
+ PROFILE_VP8_2, ///< VP8 Profile 2
+ PROFILE_VP8_3, ///< VP8 Profile 3
+
+ // MPEG-H 3D Audio profiles
+ PROFILE_MPEGH_MAIN = _C2_PL_MPEGH_BASE, ///< MPEG-H Main
+ PROFILE_MPEGH_HIGH, ///< MPEG-H High
+ PROFILE_MPEGH_LC, ///< MPEG-H Low-complexity
+ PROFILE_MPEGH_BASELINE, ///< MPEG-H Baseline
+
};
enum C2Config::level_t : uint32_t {
@@ -689,6 +715,13 @@
LEVEL_AV1_7_1, ///< AV1 Level 7.1
LEVEL_AV1_7_2, ///< AV1 Level 7.2
LEVEL_AV1_7_3, ///< AV1 Level 7.3
+
+ // MPEG-H 3D Audio levels
+ LEVEL_MPEGH_1 = _C2_PL_MPEGH_BASE, ///< MPEG-H L1
+ LEVEL_MPEGH_2, ///< MPEG-H L2
+ LEVEL_MPEGH_3, ///< MPEG-H L3
+ LEVEL_MPEGH_4, ///< MPEG-H L4
+ LEVEL_MPEGH_5, ///< MPEG-H L5
};
struct C2ProfileLevelStruct {
@@ -1901,7 +1934,9 @@
C2ENUM(C2Config::pcm_encoding_t, uint32_t,
PCM_16,
PCM_8,
- PCM_FLOAT
+ PCM_FLOAT,
+ PCM_24,
+ PCM_32
)
typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::pcm_encoding_t>, kParamIndexPcmEncoding>
@@ -2331,6 +2366,23 @@
C2PortTunnelSystemTime;
constexpr char C2_PARAMKEY_OUTPUT_RENDER_TIME[] = "output.render-time";
+C2ENUM(C2PlatformConfig::encoding_quality_level_t, uint32_t,
+ NONE,
+ S_HANDHELD,
+ S_HANDHELD_PC
+);
+
+namespace android {
+
+/**
+ * Encoding quality level signaling.
+ */
+typedef C2GlobalParam<C2Setting,
+ C2SimpleValueStruct<C2EasyEnum<C2PlatformConfig::encoding_quality_level_t>>,
+ kParamIndexEncodingQualityLevel> C2EncodingQualityLevel;
+
+}
+
/// @}
#endif // C2CONFIG_H_
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index efc5813..58a568e 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -23,21 +23,18 @@
#include <stdio.h>
#include <algorithm>
-#include <C2AllocatorIon.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
#include <C2Config.h>
#include <C2Debug.h>
#include <codec2/hidl/client.h>
-using android::C2AllocatorIon;
-
#include "media_c2_hidl_test_common.h"
using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
-static std::vector<DecodeTestParameters> kDecodeTestParameters;
+static std::vector<DecodeTestParameters> gDecodeTestParameters;
using CsdFlushTestParameters = std::tuple<std::string, std::string, bool>;
-static std::vector<CsdFlushTestParameters> kCsdFlushTestParameters;
+static std::vector<CsdFlushTestParameters> gCsdFlushTestParameters;
struct CompToURL {
std::string mime;
@@ -45,7 +42,7 @@
std::string info;
};
-std::vector<CompToURL> kCompToURL = {
+std::vector<CompToURL> gCompToURL = {
{"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.info"},
{"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac",
"bbb_aac_stereo_128kbps_48000hz_multi_frame.info"},
@@ -290,11 +287,11 @@
// LookUpTable of clips and metadata for component testing
void Codec2AudioDecHidlTestBase::GetURLForComponent(char* mURL, char* info, size_t streamIndex) {
int streamCount = 0;
- for (size_t i = 0; i < kCompToURL.size(); ++i) {
- if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
+ for (size_t i = 0; i < gCompToURL.size(); ++i) {
+ if (mMime.find(gCompToURL[i].mime) != std::string::npos) {
if (streamCount == streamIndex) {
- strcat(mURL, kCompToURL[i].mURL.c_str());
- strcat(info, kCompToURL[i].info.c_str());
+ strcat(mURL, gCompToURL[i].mURL.c_str());
+ strcat(info, gCompToURL[i].info.c_str());
return;
}
streamCount++;
@@ -859,36 +856,36 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioDecHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioDecHidlTest, testing::ValuesIn(gTestParameters),
PrintInstanceTupleNameToString<>);
// DecodeTest with StreamIndex and EOS / No EOS
INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2AudioDecDecodeTest,
- testing::ValuesIn(kDecodeTestParameters),
+ testing::ValuesIn(gDecodeTestParameters),
PrintInstanceTupleNameToString<>);
INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2AudioDecCsdInputTests,
- testing::ValuesIn(kCsdFlushTestParameters),
+ testing::ValuesIn(gCsdFlushTestParameters),
PrintInstanceTupleNameToString<>);
} // anonymous namespace
int main(int argc, char** argv) {
parseArgs(argc, argv);
- kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER);
- for (auto params : kTestParameters) {
- kDecodeTestParameters.push_back(
+ gTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER);
+ for (auto params : gTestParameters) {
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true));
- kCsdFlushTestParameters.push_back(
+ gCsdFlushTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), true));
- kCsdFlushTestParameters.push_back(
+ gCsdFlushTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), false));
}
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index 562c77f..92b53a0 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -24,20 +24,17 @@
#include <algorithm>
#include <fstream>
-#include <C2AllocatorIon.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
#include <C2Config.h>
#include <C2Debug.h>
#include <codec2/hidl/client.h>
-using android::C2AllocatorIon;
-
#include "media_c2_hidl_test_common.h"
using EncodeTestParameters = std::tuple<std::string, std::string, bool, int32_t>;
-static std::vector<EncodeTestParameters> kEncodeTestParameters;
+static std::vector<EncodeTestParameters> gEncodeTestParameters;
class LinearBuffer : public C2Buffer {
public:
@@ -45,6 +42,8 @@
: C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
};
+constexpr uint32_t kMaxSamplesPerFrame = 256;
+
namespace {
class Codec2AudioEncHidlTestBase : public ::testing::Test {
@@ -98,7 +97,7 @@
// Get the test parameters from GetParam call.
virtual void getParams() {}
- void GetURLForComponent(char* mURL);
+ void GetURLForComponent(char* mURL, int32_t channelCount, int32_t sampleRate);
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
@@ -223,53 +222,105 @@
return false;
}
+c2_status_t getChannelCount(const std::shared_ptr<android::Codec2Client::Component>& component,
+ int32_t* nChannels) {
+ std::unique_ptr<C2StreamChannelCountInfo::input> channelCount =
+ std::make_unique<C2StreamChannelCountInfo::input>();
+ std::vector<C2FieldSupportedValuesQuery> validValueInfos = {
+ C2FieldSupportedValuesQuery::Current(
+ C2ParamField(channelCount.get(), &C2StreamChannelCountInfo::value))};
+ c2_status_t c2err = component->querySupportedValues(validValueInfos, C2_DONT_BLOCK);
+ if (c2err != C2_OK || validValueInfos.size() != 1u) {
+ ALOGE("querySupportedValues_vb failed for channelCount");
+ return c2err;
+ }
+
+ // setting default value of channelCount
+ *nChannels = 1;
+ const auto& c2FSV = validValueInfos[0].values;
+ switch (c2FSV.type) {
+ case C2FieldSupportedValues::type_t::RANGE: {
+ const auto& range = c2FSV.range;
+ uint32_t rmax = (uint32_t)(range.max).ref<uint32_t>();
+ if (rmax >= 2) {
+ *nChannels = 2;
+ } else {
+ *nChannels = 1;
+ }
+ break;
+ }
+ case C2FieldSupportedValues::type_t::VALUES: {
+ for (const C2Value::Primitive& prim : c2FSV.values) {
+ if ((uint32_t)prim.ref<uint32_t>() == 2) {
+ *nChannels = 2;
+ } else if ((uint32_t)prim.ref<uint32_t>() == 1) {
+ *nChannels = 1;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return C2_OK;
+}
+
+c2_status_t getSampleRate(const std::shared_ptr<android::Codec2Client::Component>& component,
+ int32_t* nSampleRate) {
+ // Use the default sample rate for components
+ std::vector<std::unique_ptr<C2Param>> queried;
+ c2_status_t c2err = component->query({}, {C2StreamSampleRateInfo::input::PARAM_TYPE},
+ C2_DONT_BLOCK, &queried);
+ if (c2err != C2_OK || queried.size() == 0) return c2err;
+
+ size_t offset = sizeof(C2Param);
+ C2Param* param = queried[0].get();
+ *nSampleRate = *(int32_t*)((uint8_t*)param + offset);
+
+ return C2_OK;
+}
+
+c2_status_t getSamplesPerFrame(const std::shared_ptr<android::Codec2Client::Component>& component,
+ int32_t nChannels, int32_t* samplesPerFrame) {
+ std::vector<std::unique_ptr<C2Param>> queried;
+ c2_status_t c2err = component->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE},
+ C2_DONT_BLOCK, &queried);
+ if (c2err != C2_OK || queried.size() == 0) return c2err;
+
+ size_t offset = sizeof(C2Param);
+ C2Param* param = queried[0].get();
+ uint32_t maxInputSize = *(uint32_t*)((uint8_t*)param + offset);
+ *samplesPerFrame = std::min((maxInputSize / (nChannels * 2)), kMaxSamplesPerFrame);
+
+ return C2_OK;
+}
+
// Get config params for a component
-bool getConfigParams(std::string mime, int32_t* nChannels, int32_t* nSampleRate,
- int32_t* samplesPerFrame) {
- if (mime.find("mp4a-latm") != std::string::npos) {
- *nChannels = 2;
- *nSampleRate = 48000;
- *samplesPerFrame = 1024;
- } else if (mime.find("flac") != std::string::npos) {
- *nChannels = 2;
- *nSampleRate = 48000;
- *samplesPerFrame = 1152;
- } else if (mime.find("opus") != std::string::npos) {
- *nChannels = 2;
- *nSampleRate = 48000;
- *samplesPerFrame = 960;
- } else if (mime.find("3gpp") != std::string::npos) {
- *nChannels = 1;
- *nSampleRate = 8000;
- *samplesPerFrame = 160;
- } else if (mime.find("amr-wb") != std::string::npos) {
- *nChannels = 1;
- *nSampleRate = 16000;
- *samplesPerFrame = 160;
- } else
- return false;
+bool getConfigParams(const std::shared_ptr<android::Codec2Client::Component>& component,
+ int32_t* nChannels, int32_t* nSampleRate, int32_t* samplesPerFrame) {
+ c2_status_t status = getChannelCount(component, nChannels);
+ if (status != C2_OK) return false;
+
+ status = getSampleRate(component, nSampleRate);
+ if (status != C2_OK) return false;
+
+ status = getSamplesPerFrame(component, *nChannels, samplesPerFrame);
+ if (status != C2_OK) return false;
return true;
}
// LookUpTable of clips and metadata for component testing
-void Codec2AudioEncHidlTestBase::GetURLForComponent(char* mURL) {
- struct CompToURL {
- std::string mime;
- const char* mURL;
- };
- static const CompToURL kCompToURL[] = {
- {"mp4a-latm", "bbb_raw_2ch_48khz_s16le.raw"}, {"3gpp", "bbb_raw_1ch_8khz_s16le.raw"},
- {"amr-wb", "bbb_raw_1ch_16khz_s16le.raw"}, {"flac", "bbb_raw_2ch_48khz_s16le.raw"},
- {"opus", "bbb_raw_2ch_48khz_s16le.raw"},
- };
-
- for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
- if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
- strcat(mURL, kCompToURL[i].mURL);
- return;
- }
+void Codec2AudioEncHidlTestBase::GetURLForComponent(char* mURL, int32_t channelCount,
+ int32_t sampleRate) {
+ std::string rawInput = "bbb_raw_1ch_8khz_s16le.raw";
+ if (channelCount == 1 && sampleRate == 16000) {
+ rawInput = "bbb_raw_1ch_16khz_s16le.raw";
+ } else if (channelCount == 2) {
+ rawInput = "bbb_raw_2ch_48khz_s16le.raw";
}
+
+ strcat(mURL, rawInput.c_str());
}
void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
@@ -283,9 +334,17 @@
uint32_t frameID = 0;
uint32_t maxRetry = 0;
- int bytesCount = samplesPerFrame * nChannels * 2;
+ uint32_t bytesCount = samplesPerFrame * nChannels * 2;
int32_t timestampIncr = (int)(((float)samplesPerFrame / nSampleRate) * 1000000);
uint64_t timestamp = 0;
+
+ // get length of file:
+ int32_t currPos = eleStream.tellg();
+ eleStream.seekg(0, eleStream.end);
+ uint32_t remainingBytes = (uint32_t)eleStream.tellg() - currPos;
+ eleStream.seekg(currPos, eleStream.beg);
+
+ nFrames = std::min(nFrames, remainingBytes / bytesCount);
while (1) {
if (nFrames == 0) break;
uint32_t flags = 0;
@@ -319,7 +378,12 @@
char* data = (char*)malloc(bytesCount);
ASSERT_NE(data, nullptr);
eleStream.read(data, bytesCount);
- ASSERT_EQ(eleStream.gcount(), bytesCount);
+ // if we have reached at the end of input stream, signal eos
+ if (eleStream.gcount() < bytesCount) {
+ bytesCount = eleStream.gcount();
+ if (signalEOS) flags |= C2FrameData::FLAG_END_OF_STREAM;
+ }
+
std::shared_ptr<C2LinearBlock> block;
ASSERT_EQ(C2_OK,
linearPool->fetchLinearBlock(
@@ -373,9 +437,6 @@
TEST_P(Codec2AudioEncEncodeTest, EncodeTest) {
ALOGV("EncodeTest");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- char mURL[512];
- strcpy(mURL, sResourceDir.c_str());
- GetURLForComponent(mURL);
bool signalEOS = std::get<2>(GetParam());
// Ratio w.r.t to mInputMaxBufSize
int32_t inputMaxBufRatio = std::get<3>(GetParam());
@@ -384,7 +445,7 @@
int32_t nSampleRate;
int32_t samplesPerFrame;
- if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+ if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
std::cout << "Failed to get the config params for " << mComponentName << "\n";
std::cout << "[ WARN ] Test Skipped \n";
return;
@@ -398,6 +459,10 @@
std::cout << "[ WARN ] Test Skipped \n";
return;
}
+ char mURL[512];
+ strcpy(mURL, sResourceDir.c_str());
+ GetURLForComponent(mURL, nChannels, nSampleRate);
+
ASSERT_EQ(mComponent->start(), C2_OK);
std::ifstream eleStream;
uint32_t numFrames = 16;
@@ -479,16 +544,12 @@
description("Test Request for flush");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- char mURL[512];
- strcpy(mURL, sResourceDir.c_str());
- GetURLForComponent(mURL);
-
mFlushedIndices.clear();
int32_t nChannels;
int32_t nSampleRate;
int32_t samplesPerFrame;
- if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+ if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
std::cout << "Failed to get the config params for " << mComponentName << "\n";
std::cout << "[ WARN ] Test Skipped \n";
return;
@@ -498,6 +559,10 @@
std::cout << "[ WARN ] Test Skipped \n";
return;
}
+ char mURL[512];
+ strcpy(mURL, sResourceDir.c_str());
+ GetURLForComponent(mURL, nChannels, nSampleRate);
+
ASSERT_EQ(mComponent->start(), C2_OK);
std::ifstream eleStream;
@@ -544,26 +609,25 @@
description("Encodes input file for different channel count");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- char mURL[512];
- strcpy(mURL, sResourceDir.c_str());
- GetURLForComponent(mURL);
-
- std::ifstream eleStream;
- eleStream.open(mURL, std::ifstream::binary);
- ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
- ALOGV("mURL : %s", mURL);
-
int32_t nSampleRate;
int32_t samplesPerFrame;
int32_t nChannels;
int32_t numFrames = 16;
int32_t maxChannelCount = 8;
- if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+ if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
std::cout << "Failed to get the config params for " << mComponentName << "\n";
std::cout << "[ WARN ] Test Skipped \n";
return;
}
+ char mURL[512];
+ strcpy(mURL, sResourceDir.c_str());
+ GetURLForComponent(mURL, nChannels, nSampleRate);
+
+ std::ifstream eleStream;
+ eleStream.open(mURL, std::ifstream::binary);
+ ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
+ ALOGV("mURL : %s", mURL);
uint64_t prevOutputSize = 0u;
uint32_t prevChannelCount = 0u;
@@ -591,8 +655,11 @@
}
// To check if the input stream is sufficient to encode for the higher channel count
+ struct stat buf;
+ stat(mURL, &buf);
+ size_t fileSize = buf.st_size;
int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
- if (eleStream.gcount() < bytesCount) {
+ if (fileSize < bytesCount) {
std::cout << "[ WARN ] Test Skipped for ChannelCount " << nChannels
<< " because of insufficient input data\n";
continue;
@@ -616,9 +683,6 @@
// blocking call to ensures application to Wait till all the inputs are consumed
waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
- // Validate output size based on chosen ChannelCount
- EXPECT_GE(mOutputSize, prevOutputSize);
-
prevChannelCount = nChannels;
prevOutputSize = mOutputSize;
@@ -633,7 +697,8 @@
ASSERT_TRUE(mCsd) << "CSD buffer missing";
}
ASSERT_TRUE(mEos);
- ASSERT_EQ(mComponent->stop(), C2_OK);
+ // TODO(b/147348711) Use reset instead of stop when using the same instance of codec.
+ ASSERT_EQ(mComponent->reset(), C2_OK);
mFramesReceived = 0;
mOutputSize = 0;
mEos = false;
@@ -646,25 +711,24 @@
description("Encodes input file for different SampleRate");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- char mURL[512];
- strcpy(mURL, sResourceDir.c_str());
- GetURLForComponent(mURL);
-
- std::ifstream eleStream;
- eleStream.open(mURL, std::ifstream::binary);
- ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
- ALOGV("mURL : %s", mURL);
-
int32_t nSampleRate;
int32_t samplesPerFrame;
int32_t nChannels;
int32_t numFrames = 16;
- if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+ if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
std::cout << "Failed to get the config params for " << mComponentName << "\n";
std::cout << "[ WARN ] Test Skipped \n";
return;
}
+ char mURL[512];
+ strcpy(mURL, sResourceDir.c_str());
+ GetURLForComponent(mURL, nChannels, nSampleRate);
+
+ std::ifstream eleStream;
+ eleStream.open(mURL, std::ifstream::binary);
+ ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
+ ALOGV("mURL : %s", mURL);
int32_t sampleRateValues[] = {1000, 8000, 16000, 24000, 48000, 96000, 192000};
@@ -694,8 +758,11 @@
}
// To check if the input stream is sufficient to encode for the higher SampleRate
+ struct stat buf;
+ stat(mURL, &buf);
+ size_t fileSize = buf.st_size;
int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
- if (eleStream.gcount() < bytesCount) {
+ if (fileSize < bytesCount) {
std::cout << "[ WARN ] Test Skipped for SampleRate " << nSampleRate
<< " because of insufficient input data\n";
continue;
@@ -719,12 +786,6 @@
// blocking call to ensures application to Wait till all the inputs are consumed
waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
- // Validate output size based on chosen samplerate
- if (prevSampleRate >= nSampleRate) {
- EXPECT_LE(mOutputSize, prevOutputSize);
- } else {
- EXPECT_GT(mOutputSize, prevOutputSize);
- }
prevSampleRate = nSampleRate;
prevOutputSize = mOutputSize;
@@ -739,7 +800,8 @@
ASSERT_TRUE(mCsd) << "CSD buffer missing";
}
ASSERT_TRUE(mEos);
- ASSERT_EQ(mComponent->stop(), C2_OK);
+ // TODO(b/147348711) Use reset instead of stop when using the same instance of codec.
+ ASSERT_EQ(mComponent->reset(), C2_OK);
mFramesReceived = 0;
mOutputSize = 0;
mEos = false;
@@ -748,28 +810,28 @@
}
}
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioEncHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioEncHidlTest, testing::ValuesIn(gTestParameters),
PrintInstanceTupleNameToString<>);
// EncodeTest with EOS / No EOS and inputMaxBufRatio
// inputMaxBufRatio is ratio w.r.t. to mInputMaxBufSize
INSTANTIATE_TEST_SUITE_P(EncodeTest, Codec2AudioEncEncodeTest,
- testing::ValuesIn(kEncodeTestParameters),
+ testing::ValuesIn(gEncodeTestParameters),
PrintInstanceTupleNameToString<>);
} // anonymous namespace
int main(int argc, char** argv) {
parseArgs(argc, argv);
- kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_ENCODER);
- for (auto params : kTestParameters) {
- kEncodeTestParameters.push_back(
+ gTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_ENCODER);
+ for (auto params : gTestParameters) {
+ gEncodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), false, 1));
- kEncodeTestParameters.push_back(
+ gEncodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), false, 2));
- kEncodeTestParameters.push_back(
+ gEncodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), true, 1));
- kEncodeTestParameters.push_back(
+ gEncodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), true, 2));
}
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 e74f247..2222aaf 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
@@ -41,7 +41,7 @@
using namespace ::std::chrono;
using TestParameters = std::tuple<std::string, std::string>;
-static std::vector<TestParameters> kTestParameters;
+static std::vector<TestParameters> gTestParameters;
// Resource directory
extern std::string sResourceDir;
diff --git a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
index 29acd33..ffec897 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
@@ -54,7 +54,7 @@
namespace {
using InputTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
-static std::vector<InputTestParameters> kInputTestParameters;
+static std::vector<InputTestParameters> gInputTestParameters;
// google.codec2 Component test setup
class Codec2ComponentHidlTestBase : public ::testing::Test {
@@ -345,28 +345,28 @@
ASSERT_EQ(mComponent->reset(), C2_OK);
}
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2ComponentHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2ComponentHidlTest, testing::ValuesIn(gTestParameters),
PrintInstanceTupleNameToString<>);
INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests,
- testing::ValuesIn(kInputTestParameters), PrintInstanceTupleNameToString<>);
+ testing::ValuesIn(gInputTestParameters), PrintInstanceTupleNameToString<>);
} // anonymous namespace
// TODO: Add test for Invalid work,
// TODO: Add test for Invalid states
int main(int argc, char** argv) {
parseArgs(argc, argv);
- kTestParameters = getTestParameters();
- for (auto params : kTestParameters) {
- kInputTestParameters.push_back(
+ gTestParameters = getTestParameters();
+ for (auto params : gTestParameters) {
+ gInputTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
- kInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
+ gInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
C2FrameData::FLAG_END_OF_STREAM, true));
- kInputTestParameters.push_back(
+ gInputTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
- kInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
+ gInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
C2FrameData::FLAG_CODEC_CONFIG, false));
- kInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
+ gInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
C2FrameData::FLAG_END_OF_STREAM, false));
}
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index d0a1c31..8d917b3 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -24,7 +24,6 @@
#include <openssl/md5.h>
-#include <C2AllocatorIon.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
#include <C2Config.h>
@@ -35,16 +34,14 @@
#include <gui/IProducerListener.h>
#include <system/window.h>
-using android::C2AllocatorIon;
-
#include "media_c2_hidl_test_common.h"
#include "media_c2_video_hidl_test_common.h"
using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
-static std::vector<DecodeTestParameters> kDecodeTestParameters;
+static std::vector<DecodeTestParameters> gDecodeTestParameters;
using CsdFlushTestParameters = std::tuple<std::string, std::string, bool>;
-static std::vector<CsdFlushTestParameters> kCsdFlushTestParameters;
+static std::vector<CsdFlushTestParameters> gCsdFlushTestParameters;
struct CompToURL {
std::string mime;
@@ -52,7 +49,7 @@
std::string info;
std::string chksum;
};
-std::vector<CompToURL> kCompToURL = {
+std::vector<CompToURL> gCompToURL = {
{"avc", "bbb_avc_176x144_300kbps_60fps.h264", "bbb_avc_176x144_300kbps_60fps.info",
"bbb_avc_176x144_300kbps_60fps_chksum.md5"},
{"avc", "bbb_avc_640x360_768kbps_30fps.h264", "bbb_avc_640x360_768kbps_30fps.info",
@@ -365,12 +362,12 @@
void Codec2VideoDecHidlTestBase::GetURLChksmForComponent(char* mURL, char* info, char* chksum,
size_t streamIndex) {
int streamCount = 0;
- for (size_t i = 0; i < kCompToURL.size(); ++i) {
- if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
+ for (size_t i = 0; i < gCompToURL.size(); ++i) {
+ if (mMime.find(gCompToURL[i].mime) != std::string::npos) {
if (streamCount == streamIndex) {
- strcat(mURL, kCompToURL[i].mURL.c_str());
- strcat(info, kCompToURL[i].info.c_str());
- strcat(chksum, kCompToURL[i].chksum.c_str());
+ strcat(mURL, gCompToURL[i].mURL.c_str());
+ strcat(info, gCompToURL[i].info.c_str());
+ strcat(chksum, gCompToURL[i].chksum.c_str());
return;
}
streamCount++;
@@ -1074,16 +1071,16 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoDecHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoDecHidlTest, testing::ValuesIn(gTestParameters),
PrintInstanceTupleNameToString<>);
// DecodeTest with StreamIndex and EOS / No EOS
INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2VideoDecDecodeTest,
- testing::ValuesIn(kDecodeTestParameters),
+ testing::ValuesIn(gDecodeTestParameters),
PrintInstanceTupleNameToString<>);
INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2VideoDecCsdInputTests,
- testing::ValuesIn(kCsdFlushTestParameters),
+ testing::ValuesIn(gCsdFlushTestParameters),
PrintInstanceTupleNameToString<>);
} // anonymous namespace
@@ -1091,24 +1088,24 @@
// TODO : Video specific configuration Test
int main(int argc, char** argv) {
parseArgs(argc, argv);
- kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
- for (auto params : kTestParameters) {
- kDecodeTestParameters.push_back(
+ gTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
+ for (auto params : gTestParameters) {
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 2, false));
- kDecodeTestParameters.push_back(
+ gDecodeTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 2, true));
- kCsdFlushTestParameters.push_back(
+ gCsdFlushTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), true));
- kCsdFlushTestParameters.push_back(
+ gCsdFlushTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), false));
}
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 23ceff4..dfd649d 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -23,15 +23,12 @@
#include <stdio.h>
#include <fstream>
-#include <C2AllocatorIon.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
#include <C2Config.h>
#include <C2Debug.h>
#include <codec2/hidl/client.h>
-using android::C2AllocatorIon;
-
#include "media_c2_hidl_test_common.h"
#include "media_c2_video_hidl_test_common.h"
@@ -42,10 +39,10 @@
};
using EncodeTestParameters = std::tuple<std::string, std::string, bool, bool, bool>;
-static std::vector<EncodeTestParameters> kEncodeTestParameters;
+static std::vector<EncodeTestParameters> gEncodeTestParameters;
using EncodeResolutionTestParameters = std::tuple<std::string, std::string, int32_t, int32_t>;
-static std::vector<EncodeResolutionTestParameters> kEncodeResolutionTestParameters;
+static std::vector<EncodeResolutionTestParameters> gEncodeResolutionTestParameters;
namespace {
@@ -706,16 +703,16 @@
ASSERT_EQ(mComponent->reset(), C2_OK);
}
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoEncHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoEncHidlTest, testing::ValuesIn(gTestParameters),
PrintInstanceTupleNameToString<>);
INSTANTIATE_TEST_SUITE_P(NonStdSizes, Codec2VideoEncResolutionTest,
- ::testing::ValuesIn(kEncodeResolutionTestParameters),
+ ::testing::ValuesIn(gEncodeResolutionTestParameters),
PrintInstanceTupleNameToString<>);
// EncodeTest with EOS / No EOS
INSTANTIATE_TEST_SUITE_P(EncodeTestwithEOS, Codec2VideoEncEncodeTest,
- ::testing::ValuesIn(kEncodeTestParameters),
+ ::testing::ValuesIn(gEncodeTestParameters),
PrintInstanceTupleNameToString<>);
TEST_P(Codec2VideoEncHidlTest, AdaptiveBitrateTest) {
@@ -808,24 +805,24 @@
int main(int argc, char** argv) {
parseArgs(argc, argv);
- kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER);
- for (auto params : kTestParameters) {
+ gTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER);
+ for (auto params : gTestParameters) {
for (size_t i = 0; i < 1 << 3; ++i) {
- kEncodeTestParameters.push_back(std::make_tuple(
+ gEncodeTestParameters.push_back(std::make_tuple(
std::get<0>(params), std::get<1>(params), i & 1, (i >> 1) & 1, (i >> 2) & 1));
}
- kEncodeResolutionTestParameters.push_back(
+ gEncodeResolutionTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 52, 18));
- kEncodeResolutionTestParameters.push_back(
+ gEncodeResolutionTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 365, 365));
- kEncodeResolutionTestParameters.push_back(
+ gEncodeResolutionTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 484, 362));
- kEncodeResolutionTestParameters.push_back(
+ gEncodeResolutionTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 244, 488));
- kEncodeResolutionTestParameters.push_back(
+ gEncodeResolutionTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 852, 608));
- kEncodeResolutionTestParameters.push_back(
+ gEncodeResolutionTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), 1400, 442));
}
diff --git a/media/codec2/hidl/client/output.cpp b/media/codec2/hidl/client/output.cpp
index 283ed8d..8cd4934 100644
--- a/media/codec2/hidl/client/output.cpp
+++ b/media/codec2/hidl/client/output.cpp
@@ -222,7 +222,7 @@
if (generation == mGeneration) {
// case of old BlockPool destruction
C2SyncVariables *var = mSyncMem ? mSyncMem->mem() : nullptr;
- if (var) {
+ if (syncObj && var) {
*syncObj = std::make_shared<V1_2::SurfaceSyncObj>();
(*syncObj)->bqId = bqId;
(*syncObj)->syncMemory = mSyncMem->handle();
diff --git a/media/codec2/hidl/plugin/FilterWrapperStub.cpp b/media/codec2/hidl/plugin/FilterWrapperStub.cpp
index 1b94a1a..01ca596 100644
--- a/media/codec2/hidl/plugin/FilterWrapperStub.cpp
+++ b/media/codec2/hidl/plugin/FilterWrapperStub.cpp
@@ -42,10 +42,10 @@
}
c2_status_t FilterWrapper::createBlockPool(
- C2PlatformAllocatorStore::id_t,
- std::shared_ptr<const C2Component>,
- std::shared_ptr<C2BlockPool> *) {
- return C2_OMITTED;
+ C2PlatformAllocatorStore::id_t allocatorId,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool) {
+ return CreateCodec2BlockPool(allocatorId, component, pool);
}
} // namespace android
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index e33a5ba..c6ff825 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1780,7 +1780,7 @@
{
Mutexed<Output>::Locked output(mOutput);
numOutputSlots = output->numSlots;
- reorderDepth = output->buffers->getReorderDepth();
+ reorderDepth = output->buffers ? output->buffers->getReorderDepth() : 0;
}
{
Mutexed<OutputSurface>::Locked output(mOutputSurface);
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 1390642..00bf84f 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -311,6 +311,8 @@
{ C2Config::PCM_8, kAudioEncodingPcm8bit },
{ C2Config::PCM_16, kAudioEncodingPcm16bit },
{ C2Config::PCM_FLOAT, kAudioEncodingPcmFloat },
+ { C2Config::PCM_24, kAudioEncodingPcm24bitPacked },
+ { C2Config::PCM_32, kAudioEncodingPcm32bit },
};
ALookup<C2Config::level_t, int32_t> sVp9Levels = {
diff --git a/media/codec2/vndk/C2Config.cpp b/media/codec2/vndk/C2Config.cpp
index 34680a7..e9223fb 100644
--- a/media/codec2/vndk/C2Config.cpp
+++ b/media/codec2/vndk/C2Config.cpp
@@ -142,6 +142,14 @@
{ "av1-0", C2Config::PROFILE_AV1_0 },
{ "av1-1", C2Config::PROFILE_AV1_1 },
{ "av1-2", C2Config::PROFILE_AV1_2 },
+ { "vp8-0", C2Config::PROFILE_VP8_0 },
+ { "vp8-1", C2Config::PROFILE_VP8_1 },
+ { "vp8-2", C2Config::PROFILE_VP8_2 },
+ { "vp8-3", C2Config::PROFILE_VP8_3 },
+ { "mpegh-main", C2Config::PROFILE_MPEGH_MAIN },
+ { "mpegh-high", C2Config::PROFILE_MPEGH_HIGH },
+ { "mpegh-lc", C2Config::PROFILE_MPEGH_LC },
+ { "mpegh-baseline", C2Config::PROFILE_MPEGH_BASELINE },
}))
DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(C2Config::level_t, ({
@@ -248,6 +256,11 @@
{ "av1-7.1", C2Config::LEVEL_AV1_7_1 },
{ "av1-7.2", C2Config::LEVEL_AV1_7_2 },
{ "av1-7.3", C2Config::LEVEL_AV1_7_3 },
+ { "mpegh-1", C2Config::LEVEL_MPEGH_1 },
+ { "mpegh-2", C2Config::LEVEL_MPEGH_2 },
+ { "mpegh-3", C2Config::LEVEL_MPEGH_3 },
+ { "mpegh-4", C2Config::LEVEL_MPEGH_4 },
+ { "mpegh-5", C2Config::LEVEL_MPEGH_5 },
}))
DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(C2BufferData::type_t, ({
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index b1d72e8..416884e 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -62,6 +62,16 @@
#define ALAC_SPECIFIC_INFO_SIZE (36)
+// TODO : Remove the defines once mainline media is built against NDK >= 31.
+// The mp4 extractor is part of mainline and builds against NDK 29 as of
+// writing. These keys are available only from NDK 31:
+#define AMEDIAFORMAT_KEY_MPEGH_PROFILE_LEVEL_INDICATION \
+ "mpegh-profile-level-indication"
+#define AMEDIAFORMAT_KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT \
+ "mpegh-reference-channel-layout"
+#define AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS \
+ "mpegh-compatible-sets"
+
namespace android {
enum {
@@ -139,6 +149,7 @@
bool mIsHEVC;
bool mIsDolbyVision;
bool mIsAC4;
+ bool mIsMpegH = false;
bool mIsPcm;
size_t mNALLengthSize;
@@ -378,6 +389,10 @@
case FOURCC(".mp3"):
case 0x6D730055: // "ms U" mp3 audio
return MEDIA_MIMETYPE_AUDIO_MPEG;
+ case FOURCC("mha1"):
+ return MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1;
+ case FOURCC("mhm1"):
+ return MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1;
default:
ALOGW("Unknown fourcc: %c%c%c%c",
(fourcc >> 24) & 0xff,
@@ -1778,6 +1793,8 @@
case FOURCC("fLaC"):
case FOURCC(".mp3"):
case 0x6D730055: // "ms U" mp3 audio
+ case FOURCC("mha1"):
+ case FOURCC("mhm1"):
{
if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
@@ -1977,7 +1994,94 @@
}
break;
}
+ case FOURCC("mhaC"):
+ {
+ // See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord
+ constexpr uint32_t mhac_header_size = 4 /* size */ + 4 /* boxtype 'mhaC' */
+ + 1 /* configurationVersion */ + 1 /* mpegh3daProfileLevelIndication */
+ + 1 /* referenceChannelLayout */ + 2 /* mpegh3daConfigLength */;
+ uint8_t mhac_header[mhac_header_size];
+ off64_t data_offset = *offset;
+ if (chunk_size < sizeof(mhac_header)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(data_offset, mhac_header, sizeof(mhac_header))
+ < (ssize_t)sizeof(mhac_header)) {
+ return ERROR_IO;
+ }
+
+ //get mpegh3daProfileLevelIndication
+ const uint32_t mpegh3daProfileLevelIndication = mhac_header[9];
+ AMediaFormat_setInt32(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_MPEGH_PROFILE_LEVEL_INDICATION,
+ mpegh3daProfileLevelIndication);
+
+ //get referenceChannelLayout
+ const uint32_t referenceChannelLayout = mhac_header[10];
+ AMediaFormat_setInt32(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT,
+ referenceChannelLayout);
+
+ // get mpegh3daConfigLength
+ const uint32_t mhac_config_size = U16_AT(&mhac_header[11]);
+ if (chunk_size != sizeof(mhac_header) + mhac_config_size) {
+ return ERROR_MALFORMED;
+ }
+
+ data_offset += sizeof(mhac_header);
+ uint8_t mhac_config[mhac_config_size];
+ if (mDataSource->readAt(data_offset, mhac_config, sizeof(mhac_config))
+ < (ssize_t)sizeof(mhac_config)) {
+ return ERROR_IO;
+ }
+
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CSD_0, mhac_config, sizeof(mhac_config));
+ data_offset += sizeof(mhac_config);
+ *offset = data_offset;
+ break;
+ }
+ case FOURCC("mhaP"):
+ {
+ // FDAmd_2 of ISO_IEC_23008-3;2019 MHAProfileAndLevelCompatibilitySetBox
+ constexpr uint32_t mhap_header_size = 4 /* size */ + 4 /* boxtype 'mhaP' */
+ + 1 /* numCompatibleSets */;
+
+ uint8_t mhap_header[mhap_header_size];
+ off64_t data_offset = *offset;
+
+ if (chunk_size < (ssize_t)mhap_header_size) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(data_offset, mhap_header, sizeof(mhap_header))
+ < (ssize_t)sizeof(mhap_header)) {
+ return ERROR_IO;
+ }
+
+ // mhap_compatible_sets_size = numCompatibleSets * sizeof(uint8_t)
+ const uint32_t mhap_compatible_sets_size = mhap_header[8];
+ if (chunk_size != sizeof(mhap_header) + mhap_compatible_sets_size) {
+ return ERROR_MALFORMED;
+ }
+
+ data_offset += sizeof(mhap_header);
+ uint8_t mhap_compatible_sets[mhap_compatible_sets_size];
+ if (mDataSource->readAt(
+ data_offset, mhap_compatible_sets, sizeof(mhap_compatible_sets))
+ < (ssize_t)sizeof(mhap_compatible_sets)) {
+ return ERROR_IO;
+ }
+
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS,
+ mhap_compatible_sets, sizeof(mhap_compatible_sets));
+ data_offset += sizeof(mhap_compatible_sets);
+ *offset = data_offset;
+ break;
+ }
case FOURCC("mp4v"):
case FOURCC("encv"):
case FOURCC("s263"):
@@ -5001,6 +5105,8 @@
bool success = AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime);
CHECK(success);
+ mIsMpegH = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1) ||
+ !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1);
mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) ||
!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
@@ -6072,10 +6178,11 @@
}
uint32_t syncSampleIndex = sampleIndex;
- // assume every non-USAC audio sample is a sync sample. This works around
+ // assume every non-USAC/non-MPEGH audio sample is a sync sample.
+ // This works around
// seek issues with files that were incorrectly written with an
// empty or single-sample stss block for the audio track
- if (err == OK && (!mIsAudio || mIsUsac)) {
+ if (err == OK && (!mIsAudio || mIsUsac || mIsMpegH)) {
err = mSampleTable->findSyncSampleNear(
sampleIndex, &syncSampleIndex, findFlags);
}
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
index 685b779..eef238f 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
@@ -59,7 +59,8 @@
}
void SharedMemoryParcelable::setup(const unique_fd& fd, int32_t sizeInBytes) {
- mFd.reset(::dup(fd.get())); // store a duplicate fd
+ constexpr int minFd = 3; // skip over stdout, stdin and stderr
+ mFd.reset(fcntl(fd.get(), F_DUPFD_CLOEXEC, minFd)); // store a duplicate FD
ALOGV("setup(fd = %d -> %d, size = %d) this = %p\n", fd.get(), mFd.get(), sizeInBytes, this);
mSizeInBytes = sizeInBytes;
}
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index dc961ad..d8b27c3 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -100,8 +100,9 @@
const int32_t burstMinMicros = AAudioProperty_getHardwareBurstMinMicros();
int32_t burstMicros = 0;
+ const audio_format_t requestedFormat = getFormat();
// We have to do volume scaling. So we prefer FLOAT format.
- if (getFormat() == AUDIO_FORMAT_DEFAULT) {
+ if (requestedFormat == AUDIO_FORMAT_DEFAULT) {
setFormat(AUDIO_FORMAT_PCM_FLOAT);
}
// Request FLOAT for the shared mixer or the device.
@@ -156,6 +157,14 @@
mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM)
+ std::to_string(mServiceStreamHandle);
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
+ AudioGlobal_convertPerformanceModeToText(builder.getPerformanceMode()))
+ .set(AMEDIAMETRICS_PROP_SHARINGMODE,
+ AudioGlobal_convertSharingModeToText(builder.getSharingMode()))
+ .set(AMEDIAMETRICS_PROP_ENCODINGCLIENT,
+ android::toString(requestedFormat).c_str()).record();
+
result = configurationOutput.validate();
if (result != AAUDIO_OK) {
goto error;
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index ef83c8e..1ed240a 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -56,16 +56,6 @@
ALOGE_IF(mHasThread, "%s() callback thread never join()ed", __func__);
- if (!mMetricsId.empty()) {
- android::mediametrics::LogItem(mMetricsId)
- .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
- .set(AMEDIAMETRICS_PROP_ENCODINGREQUESTED,
- android::toString(mDeviceFormat).c_str())
- .set(AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL,
- AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
- .record();
- }
-
// If the stream is deleted when OPEN or in use then audio resources will leak.
// This would indicate an internal error. So we want to find this ASAP.
LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
@@ -121,13 +111,13 @@
return AAUDIO_OK;
}
-void AudioStream::logOpen() {
+void AudioStream::logOpenActual() {
if (mMetricsId.size() > 0) {
android::mediametrics::LogItem item(mMetricsId);
item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN)
- .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
+ .set(AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL,
AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
- .set(AMEDIAMETRICS_PROP_SHARINGMODE,
+ .set(AMEDIAMETRICS_PROP_SHARINGMODEACTUAL,
AudioGlobal_convertSharingModeToText(getSharingMode()))
.set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, getBufferCapacity())
.set(AMEDIAMETRICS_PROP_BURSTFRAMES, getFramesPerBurst())
@@ -359,6 +349,7 @@
.set(AMEDIAMETRICS_PROP_FRAMESTRANSFERRED,
getDirection() == AAUDIO_DIRECTION_INPUT ? getFramesWritten()
: getFramesRead())
+ .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
.record();
}
}
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 3930964..2b45ed3 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -118,7 +118,7 @@
virtual aaudio_result_t open(const AudioStreamBuilder& builder);
// log to MediaMetrics
- virtual void logOpen();
+ virtual void logOpenActual();
void logReleaseBufferState();
/* Note about naming for "release" and "close" related methods.
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 207a8e3..2135c54 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -189,7 +189,7 @@
}
if (result == AAUDIO_OK) {
audioStream->registerPlayerBase();
- audioStream->logOpen();
+ audioStream->logOpenActual();
*streamPtr = startUsingStream(audioStream);
} // else audioStream will go out of scope and be deleted
}
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index e3ac6ff..eca5392 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -26,6 +26,7 @@
#include <media/AudioRecord.h>
#include <utils/String16.h>
+#include "core/AudioGlobal.h"
#include "legacy/AudioStreamLegacy.h"
#include "legacy/AudioStreamRecord.h"
#include "utility/AudioClock.h"
@@ -92,8 +93,9 @@
break;
}
+ const audio_format_t requestedFormat = getFormat();
// Preserve behavior of API 26
- if (getFormat() == AUDIO_FORMAT_DEFAULT) {
+ if (requestedFormat == AUDIO_FORMAT_DEFAULT) {
setFormat(AUDIO_FORMAT_PCM_FLOAT);
}
@@ -217,6 +219,12 @@
mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD)
+ std::to_string(mAudioRecord->getPortId());
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
+ AudioGlobal_convertPerformanceModeToText(builder.getPerformanceMode()))
+ .set(AMEDIAMETRICS_PROP_SHARINGMODE,
+ AudioGlobal_convertSharingModeToText(builder.getSharingMode()))
+ .set(AMEDIAMETRICS_PROP_ENCODINGCLIENT, toString(requestedFormat).c_str()).record();
// Get the actual values from the AudioRecord.
setSamplesPerFrame(mAudioRecord->channelCount());
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index df97658..04a9dec 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -23,9 +23,11 @@
#include <aaudio/AAudio.h>
#include <system/audio.h>
-#include "utility/AudioClock.h"
+
+#include "core/AudioGlobal.h"
#include "legacy/AudioStreamLegacy.h"
#include "legacy/AudioStreamTrack.h"
+#include "utility/AudioClock.h"
#include "utility/FixedBlockReader.h"
using namespace android;
@@ -187,6 +189,12 @@
mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
+ std::to_string(mAudioTrack->getPortId());
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
+ AudioGlobal_convertPerformanceModeToText(builder.getPerformanceMode()))
+ .set(AMEDIAMETRICS_PROP_SHARINGMODE,
+ AudioGlobal_convertSharingModeToText(builder.getSharingMode()))
+ .set(AMEDIAMETRICS_PROP_ENCODINGCLIENT, toString(getFormat()).c_str()).record();
doSetVolume();
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index 20c7ab9..6a36e78 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -98,7 +98,7 @@
bool mIsDynamicChannels = false;
bool mIsDynamicRate = false;
- audio_encapsulation_type_t mEncapsulationType;
+ audio_encapsulation_type_t mEncapsulationType = AUDIO_ENCAPSULATION_TYPE_NONE;
AudioProfile() = default;
AudioProfile& operator=(const AudioProfile& other);
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index d0c375e..34bd5df 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "StreamHalLocal"
//#define LOG_NDEBUG 0
+#include <audio_utils/Metadata.h>
#include <hardware/audio.h>
#include <media/AudioParameter.h>
#include <utils/Log.h>
@@ -353,7 +354,11 @@
if (callback.get() == nullptr) return 0;
switch (event) {
case STREAM_EVENT_CBK_TYPE_CODEC_FORMAT_CHANGED:
- callback->onCodecFormatChanged(std::basic_string<uint8_t>((uint8_t*)param));
+ // void* param is the byte string buffer from byte_string_from_audio_metadata().
+ // As the byte string buffer may have embedded zeroes, we cannot use strlen()
+ callback->onCodecFormatChanged(std::basic_string<uint8_t>(
+ (const uint8_t*)param,
+ audio_utils::metadata::dataByteStringLen((const uint8_t*)param)));
break;
default:
ALOGW("%s unknown event %d", __func__, event);
diff --git a/media/libdatasource/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp
index bb6a08c..f91e3ea 100644
--- a/media/libdatasource/DataSourceFactory.cpp
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -65,6 +65,9 @@
sp<HTTPBase> mediaHTTP = httpSource;
if (mediaHTTP == NULL) {
mediaHTTP = static_cast<HTTPBase *>(CreateMediaHTTP(httpService).get());
+ if (mediaHTTP == NULL) {
+ return NULL;
+ }
}
String8 cacheConfig;
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index b2056ad..e471c7b 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -45,6 +45,12 @@
enabled: false,
},
},
+ header_libs: [
+ "libbinder_headers",
+ ],
+ export_header_lib_headers: [
+ "libbinder_headers",
+ ],
apex_available: [
"//apex_available:platform",
"com.android.media",
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 7ed76d8..eb436d1 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -39,7 +39,8 @@
SETMEDIACAS,
NAME,
GETMETRICS,
- SETENTRYPOINT
+ SETENTRYPOINT,
+ SETLOGSESSIONID
};
class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -150,6 +151,13 @@
data.writeInt32(static_cast<int32_t>(entryPoint));
return remote()->transact(SETENTRYPOINT, data, &reply);
}
+
+ virtual status_t setLogSessionId(const String8& logSessionId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+ data.writeString8(logSessionId);
+ return remote()->transact(SETLOGSESSIONID, data, &reply);
+ }
};
IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -250,6 +258,16 @@
}
return err;
}
+ case SETLOGSESSIONID: {
+ ALOGV("setLogSessionId");
+ CHECK_INTERFACE(IMediaExtractor, data, reply);
+ String8 logSessionId;
+ status_t status = data.readString8(&logSessionId);
+ if (status == OK) {
+ setLogSessionId(logSessionId);
+ }
+ return status;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 1705c97..0c87aee 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -230,7 +230,7 @@
return tag;
}
-/*static*/ MediaProfiles::VideoCodec*
+/*static*/ void
MediaProfiles::createVideoCodec(const char **atts, MediaProfiles *profiles)
{
CHECK(!strcmp("codec", atts[0]) &&
@@ -242,22 +242,21 @@
const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
if (codec == -1) {
- ALOGE("MediaProfiles::createVideoCodec failed to locate codec %s", atts[1]);
- return nullptr;
+ ALOGE("MediaProfiles::createVideoCodec failed to locate codec %s", atts[1]);
+ return;
}
- MediaProfiles::VideoCodec *videoCodec =
- new MediaProfiles::VideoCodec(static_cast<video_encoder>(codec),
- atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
- logVideoCodec(*videoCodec);
+ VideoCodec videoCodec {
+ static_cast<video_encoder>(codec),
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]) };
+ logVideoCodec(videoCodec);
size_t nCamcorderProfiles;
CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
- profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodec = videoCodec;
- return videoCodec;
+ profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodecs.emplace_back(videoCodec);
}
-/*static*/ MediaProfiles::AudioCodec*
+/*static*/ void
MediaProfiles::createAudioCodec(const char **atts, MediaProfiles *profiles)
{
CHECK(!strcmp("codec", atts[0]) &&
@@ -267,20 +266,20 @@
const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
if (codec == -1) {
- ALOGE("MediaProfiles::createAudioCodec failed to locate codec %s", atts[1]);
- return nullptr;
+ ALOGE("MediaProfiles::createAudioCodec failed to locate codec %s", atts[1]);
+ return;
}
- MediaProfiles::AudioCodec *audioCodec =
- new MediaProfiles::AudioCodec(static_cast<audio_encoder>(codec),
- atoi(atts[3]), atoi(atts[5]), atoi(atts[7]));
- logAudioCodec(*audioCodec);
+ AudioCodec audioCodec {
+ static_cast<audio_encoder>(codec),
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]) };
+ logAudioCodec(audioCodec);
size_t nCamcorderProfiles;
CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
- profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodec = audioCodec;
- return audioCodec;
+ profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodecs.emplace_back(audioCodec);
}
+
/*static*/ MediaProfiles::AudioDecoderCap*
MediaProfiles::createAudioDecoderCap(const char **atts)
{
@@ -575,8 +574,20 @@
initRequiredProfileRefs(mCameraIds);
for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
- int product = mCamcorderProfiles[i]->mVideoCodec->mFrameWidth *
- mCamcorderProfiles[i]->mVideoCodec->mFrameHeight;
+ // ensure at least one video and audio profile is added
+ if (mCamcorderProfiles[i]->mVideoCodecs.size() == 0) {
+ mCamcorderProfiles[i]->mVideoCodecs.emplace_back(
+ VIDEO_ENCODER_H263, 192000 /* bitrate */,
+ 176 /* width */, 144 /* height */, 20 /* frameRate */);
+ }
+ if (mCamcorderProfiles[i]->mAudioCodecs.size() == 0) {
+ mCamcorderProfiles[i]->mAudioCodecs.emplace_back(
+ AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
+ 8000 /* sampleRate */, 1 /* channels */);
+ }
+
+ int product = mCamcorderProfiles[i]->mVideoCodecs[0].mFrameWidth *
+ mCamcorderProfiles[i]->mVideoCodecs[0].mFrameHeight;
camcorder_quality quality = mCamcorderProfiles[i]->mQuality;
int cameraId = mCamcorderProfiles[i]->mCameraId;
@@ -745,34 +756,35 @@
/*static*/ MediaProfiles::CamcorderProfile*
MediaProfiles::createDefaultCamcorderTimeLapseQcifProfile(camcorder_quality quality)
{
- MediaProfiles::VideoCodec *videoCodec =
- new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 1000000, 176, 144, 20);
-
- AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
profile->mCameraId = 0;
profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
profile->mQuality = quality;
profile->mDuration = 60;
- profile->mVideoCodec = videoCodec;
- profile->mAudioCodec = audioCodec;
+ profile->mVideoCodecs.emplace_back(
+ VIDEO_ENCODER_H263, 1000000 /* bitrate */,
+ 176 /* width */, 144 /* height */, 20 /* frameRate */);
+ profile->mAudioCodecs.emplace_back(
+ AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
+ 8000 /* sampleRate */, 1 /* channels */);
+
return profile;
}
/*static*/ MediaProfiles::CamcorderProfile*
MediaProfiles::createDefaultCamcorderTimeLapse480pProfile(camcorder_quality quality)
{
- MediaProfiles::VideoCodec *videoCodec =
- new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 20000000, 720, 480, 20);
-
- AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
profile->mCameraId = 0;
profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
profile->mQuality = quality;
profile->mDuration = 60;
- profile->mVideoCodec = videoCodec;
- profile->mAudioCodec = audioCodec;
+ profile->mVideoCodecs.emplace_back(
+ VIDEO_ENCODER_H263, 20000000 /* bitrate */,
+ 720 /* width */, 480 /* height */, 20 /* frameRate */);
+ profile->mAudioCodecs.emplace_back(
+ AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
+ 8000 /* sampleRate */, 1 /* channels */);
return profile;
}
@@ -799,36 +811,34 @@
/*static*/ MediaProfiles::CamcorderProfile*
MediaProfiles::createDefaultCamcorderQcifProfile(camcorder_quality quality)
{
- MediaProfiles::VideoCodec *videoCodec =
- new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 192000, 176, 144, 20);
-
- MediaProfiles::AudioCodec *audioCodec =
- new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
-
- MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
profile->mCameraId = 0;
profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
profile->mQuality = quality;
profile->mDuration = 30;
- profile->mVideoCodec = videoCodec;
- profile->mAudioCodec = audioCodec;
+ profile->mVideoCodecs.emplace_back(
+ VIDEO_ENCODER_H263, 192000 /* bitrate */,
+ 176 /* width */, 144 /* height */, 20 /* frameRate */);
+ profile->mAudioCodecs.emplace_back(
+ AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
+ 8000 /* sampleRate */, 1 /* channels */);
return profile;
}
/*static*/ MediaProfiles::CamcorderProfile*
MediaProfiles::createDefaultCamcorderCifProfile(camcorder_quality quality)
{
- MediaProfiles::VideoCodec *videoCodec =
- new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20);
-
- AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
profile->mCameraId = 0;
profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
profile->mQuality = quality;
profile->mDuration = 60;
- profile->mVideoCodec = videoCodec;
- profile->mAudioCodec = audioCodec;
+ profile->mVideoCodecs.emplace_back(
+ VIDEO_ENCODER_H263, 360000 /* bitrate */,
+ 352 /* width */, 288 /* height */, 20 /* frameRate */);
+ profile->mAudioCodecs.emplace_back(
+ AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
+ 8000 /* sampleRate */, 1 /* channels */);
return profile;
}
@@ -1112,6 +1122,36 @@
return index;
}
+const MediaProfiles::CamcorderProfile *MediaProfiles::getCamcorderProfile(
+ int cameraId, camcorder_quality quality) const {
+ int index = getCamcorderProfileIndex(cameraId, quality);
+ if (index == -1) {
+ ALOGE("The given camcorder profile camera %d quality %d is not found",
+ cameraId, quality);
+ return nullptr;
+ }
+
+ return mCamcorderProfiles[index];
+}
+
+std::vector<const MediaProfiles::AudioCodec *>
+MediaProfiles::CamcorderProfile::getAudioCodecs() const {
+ std::vector<const MediaProfiles::AudioCodec *> res;
+ for (const MediaProfiles::AudioCodec &ac : mAudioCodecs) {
+ res.push_back(&ac);
+ }
+ return res;
+}
+
+std::vector<const MediaProfiles::VideoCodec *>
+MediaProfiles::CamcorderProfile::getVideoCodecs() const {
+ std::vector<const MediaProfiles::VideoCodec *> res;
+ for (const MediaProfiles::VideoCodec &vc : mVideoCodecs) {
+ res.push_back(&vc);
+ }
+ return res;
+}
+
int MediaProfiles::getCamcorderProfileParamByName(const char *name,
int cameraId,
camcorder_quality quality) const
@@ -1128,15 +1168,15 @@
if (!strcmp("duration", name)) return mCamcorderProfiles[index]->mDuration;
if (!strcmp("file.format", name)) return mCamcorderProfiles[index]->mFileFormat;
- if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodec->mCodec;
- if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameWidth;
- if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameHeight;
- if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodec->mBitRate;
- if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameRate;
- if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodec->mCodec;
- if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodec->mBitRate;
- if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels;
- if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate;
+ if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mCodec;
+ if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mFrameWidth;
+ if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mFrameHeight;
+ if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mBitRate;
+ if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mFrameRate;
+ if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mCodec;
+ if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mBitRate;
+ if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mChannels;
+ if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mSampleRate;
ALOGE("The given camcorder profile param id %d name %s is not found", cameraId, name);
return -1;
diff --git a/media/libmedia/include/android/IMediaExtractor.h b/media/libmedia/include/android/IMediaExtractor.h
index f9cafde..bb1eb99 100644
--- a/media/libmedia/include/android/IMediaExtractor.h
+++ b/media/libmedia/include/android/IMediaExtractor.h
@@ -72,6 +72,8 @@
};
virtual status_t setEntryPoint(EntryPoint entryPoint) = 0;
+
+ virtual status_t setLogSessionId(const String8& logSessionId) = 0;
};
diff --git a/media/libmedia/include/media/MediaProfiles.h b/media/libmedia/include/media/MediaProfiles.h
index 7f0b99d..75e16fb 100644
--- a/media/libmedia/include/media/MediaProfiles.h
+++ b/media/libmedia/include/media/MediaProfiles.h
@@ -21,6 +21,8 @@
#include <utils/threads.h>
#include <media/mediarecorder.h>
+#include <vector>
+
namespace android {
enum camcorder_quality {
@@ -100,6 +102,176 @@
static MediaProfiles* getInstance();
/**
+ * Configuration for a video encoder.
+ */
+ struct VideoCodec {
+ public:
+ /**
+ * Constructs a video encoder configuration.
+ *
+ * @param codec codec type
+ * @param bitrate bitrate in bps
+ * @param frameWidth frame width in pixels
+ * @param frameHeight frame height in pixels
+ * @param frameRate frame rate in fps
+ */
+ VideoCodec(video_encoder codec, int bitrate, int frameWidth, int frameHeight, int frameRate)
+ : mCodec(codec),
+ mBitRate(bitrate),
+ mFrameWidth(frameWidth),
+ mFrameHeight(frameHeight),
+ mFrameRate(frameRate) {
+ }
+
+ VideoCodec(const VideoCodec&) = default;
+
+ ~VideoCodec() {}
+
+ /** Returns the codec type. */
+ video_encoder getCodec() const {
+ return mCodec;
+ }
+
+ /** Returns the bitrate in bps. */
+ int getBitrate() const {
+ return mBitRate;
+ }
+
+ /** Returns the frame width in pixels. */
+ int getFrameWidth() const {
+ return mFrameWidth;
+ }
+
+ /** Returns the frame height in pixels. */
+ int getFrameHeight() const {
+ return mFrameHeight;
+ }
+
+ /** Returns the frame rate in fps. */
+ int getFrameRate() const {
+ return mFrameRate;
+ }
+
+ private:
+ video_encoder mCodec;
+ int mBitRate;
+ int mFrameWidth;
+ int mFrameHeight;
+ int mFrameRate;
+ friend class MediaProfiles;
+ };
+
+ /**
+ * Configuration for an audio encoder.
+ */
+ struct AudioCodec {
+ public:
+ /**
+ * Constructs an audio encoder configuration.
+ *
+ * @param codec codec type
+ * @param bitrate bitrate in bps
+ * @param sampleRate sample rate in Hz
+ * @param channels number of channels
+ */
+ AudioCodec(audio_encoder codec, int bitrate, int sampleRate, int channels)
+ : mCodec(codec),
+ mBitRate(bitrate),
+ mSampleRate(sampleRate),
+ mChannels(channels) {
+ }
+
+ AudioCodec(const AudioCodec&) = default;
+
+ ~AudioCodec() {}
+
+ /** Returns the codec type. */
+ audio_encoder getCodec() const {
+ return mCodec;
+ }
+
+ /** Returns the bitrate in bps. */
+ int getBitrate() const {
+ return mBitRate;
+ }
+
+ /** Returns the sample rate in Hz. */
+ int getSampleRate() const {
+ return mSampleRate;
+ }
+
+ /** Returns the number of channels. */
+ int getChannels() const {
+ return mChannels;
+ }
+
+ private:
+ audio_encoder mCodec;
+ int mBitRate;
+ int mSampleRate;
+ int mChannels;
+ friend class MediaProfiles;
+ };
+
+ /**
+ * Configuration for a camcorder profile/encoder profiles object.
+ */
+ struct CamcorderProfile {
+ /**
+ * Returns on ordered list of the video codec configurations in
+ * decreasing preference. The returned object is only valid
+ * during the lifetime of this object.
+ */
+ std::vector<const VideoCodec *> getVideoCodecs() const;
+
+ /**
+ * Returns on ordered list of the audio codec configurations in
+ * decreasing preference. The returned object is only valid
+ * during the lifetime of this object.
+ */
+ std::vector<const AudioCodec *> getAudioCodecs() const;
+
+ /** Returns the default duration in seconds. */
+ int getDuration() const {
+ return mDuration;
+ }
+
+ /** Returns the preferred file format. */
+ int getFileFormat() const {
+ return mFileFormat;
+ }
+
+ CamcorderProfile(const CamcorderProfile& copy) = default;
+
+ ~CamcorderProfile() = default;
+
+ private:
+ /**
+ * Constructs an empty object with no audio/video profiles.
+ */
+ CamcorderProfile()
+ : mCameraId(0),
+ mFileFormat(OUTPUT_FORMAT_THREE_GPP),
+ mQuality(CAMCORDER_QUALITY_HIGH),
+ mDuration(0) {}
+
+ int mCameraId;
+ output_format mFileFormat;
+ camcorder_quality mQuality;
+ int mDuration;
+ std::vector<VideoCodec> mVideoCodecs;
+ std::vector<AudioCodec> mAudioCodecs;
+ friend class MediaProfiles;
+ };
+
+ /**
+ * Returns the CamcorderProfile object for the given camera at
+ * the given quality level, or null if it does not exist.
+ */
+ const CamcorderProfile *getCamcorderProfile(
+ int cameraId, camcorder_quality quality) const;
+
+ /**
* Returns the value for the given param name for the given camera at
* the given quality level, or -1 if error.
*
@@ -202,84 +374,6 @@
MediaProfiles() {} // Dummy default constructor
~MediaProfiles(); // Don't delete me
- struct VideoCodec {
- VideoCodec(video_encoder codec, int bitRate, int frameWidth, int frameHeight, int frameRate)
- : mCodec(codec),
- mBitRate(bitRate),
- mFrameWidth(frameWidth),
- mFrameHeight(frameHeight),
- mFrameRate(frameRate) {}
-
- VideoCodec(const VideoCodec& copy) {
- mCodec = copy.mCodec;
- mBitRate = copy.mBitRate;
- mFrameWidth = copy.mFrameWidth;
- mFrameHeight = copy.mFrameHeight;
- mFrameRate = copy.mFrameRate;
- }
-
- ~VideoCodec() {}
-
- video_encoder mCodec;
- int mBitRate;
- int mFrameWidth;
- int mFrameHeight;
- int mFrameRate;
- };
-
- struct AudioCodec {
- AudioCodec(audio_encoder codec, int bitRate, int sampleRate, int channels)
- : mCodec(codec),
- mBitRate(bitRate),
- mSampleRate(sampleRate),
- mChannels(channels) {}
-
- AudioCodec(const AudioCodec& copy) {
- mCodec = copy.mCodec;
- mBitRate = copy.mBitRate;
- mSampleRate = copy.mSampleRate;
- mChannels = copy.mChannels;
- }
-
- ~AudioCodec() {}
-
- audio_encoder mCodec;
- int mBitRate;
- int mSampleRate;
- int mChannels;
- };
-
- struct CamcorderProfile {
- CamcorderProfile()
- : mCameraId(0),
- mFileFormat(OUTPUT_FORMAT_THREE_GPP),
- mQuality(CAMCORDER_QUALITY_HIGH),
- mDuration(0),
- mVideoCodec(0),
- mAudioCodec(0) {}
-
- CamcorderProfile(const CamcorderProfile& copy) {
- mCameraId = copy.mCameraId;
- mFileFormat = copy.mFileFormat;
- mQuality = copy.mQuality;
- mDuration = copy.mDuration;
- mVideoCodec = new VideoCodec(*copy.mVideoCodec);
- mAudioCodec = new AudioCodec(*copy.mAudioCodec);
- }
-
- ~CamcorderProfile() {
- delete mVideoCodec;
- delete mAudioCodec;
- }
-
- int mCameraId;
- output_format mFileFormat;
- camcorder_quality mQuality;
- int mDuration;
- VideoCodec *mVideoCodec;
- AudioCodec *mAudioCodec;
- };
-
struct VideoEncoderCap {
// Ugly constructor
VideoEncoderCap(video_encoder codec,
@@ -365,8 +459,8 @@
// from the xml
static MediaProfiles* createInstanceFromXmlFile(const char *xml);
static output_format createEncoderOutputFileFormat(const char **atts);
- static VideoCodec* createVideoCodec(const char **atts, MediaProfiles *profiles);
- static AudioCodec* createAudioCodec(const char **atts, MediaProfiles *profiles);
+ static void createVideoCodec(const char **atts, MediaProfiles *profiles);
+ static void createAudioCodec(const char **atts, MediaProfiles *profiles);
static AudioDecoderCap* createAudioDecoderCap(const char **atts);
static VideoDecoderCap* createVideoDecoderCap(const char **atts);
static VideoEncoderCap* createVideoEncoderCap(const char **atts);
diff --git a/media/libmediaformatshaper/CodecProperties.cpp b/media/libmediaformatshaper/CodecProperties.cpp
index 315b3ec..c57b693 100644
--- a/media/libmediaformatshaper/CodecProperties.cpp
+++ b/media/libmediaformatshaper/CodecProperties.cpp
@@ -53,11 +53,11 @@
mMinimumQuality = vmaf;
}
-int CodecProperties::targetQpMax() {
- return mTargetQpMax;
+void CodecProperties::setMissingQpBoost(double boost) {
+ mMissingQpBoost = boost;
}
-void CodecProperties::setTargetQpMax(int qpMax) {
- mTargetQpMax = qpMax;
+void CodecProperties::setPhaseOut(double phaseout) {
+ mPhaseOut = phaseout;
}
// what API is this codec set up for (e.g. API of the associated partition)
@@ -111,6 +111,11 @@
setTargetQpMax(iValue);
legal = true;
}
+ } else if (!strncmp(key.c_str(), "vq-target-qpmax-", strlen("vq-target-qpmax-"))) {
+ std::string resolution = key.substr(strlen("vq-target-qpmax-"));
+ if (qpMaxPoint(resolution, value)) {
+ legal = true;
+ }
} else if (!strcmp(key.c_str(), "vq-target-bpp")) {
const char *p = value.c_str();
char *q;
@@ -134,6 +139,22 @@
setBpp(bpp);
legal = true;
}
+ } else if (!strcmp(key.c_str(), "vq-bitrate-phaseout")) {
+ const char *p = value.c_str();
+ char *q;
+ double phaseout = strtod(p, &q);
+ if (q != p) {
+ setPhaseOut(phaseout);
+ legal = true;
+ }
+ } else if (!strcmp(key.c_str(), "vq-boost-missing-qp")) {
+ const char *p = value.c_str();
+ char *q;
+ double boost = strtod(p, &q);
+ if (q != p) {
+ setMissingQpBoost(boost);
+ legal = true;
+ }
} else {
legal = true;
}
@@ -269,6 +290,131 @@
return mBpp;
}
+bool CodecProperties::qpMaxPoint(std::string resolution, std::string value) {
+
+ int32_t width = 0;
+ int32_t height = 0;
+ int qpMax = INT32_MAX;
+
+ // resolution is "WxH", "W*H" or a standard name like "720p"
+ if (resolution == "1080p") {
+ width = 1080; height = 1920;
+ } else if (resolution == "720p") {
+ width = 720; height = 1280;
+ } else if (resolution == "540p") {
+ width = 540; height = 960;
+ } else if (resolution == "480p") {
+ width = 480; height = 854;
+ } else {
+ size_t sep = resolution.find('x');
+ if (sep == std::string::npos) {
+ sep = resolution.find('*');
+ }
+ if (sep == std::string::npos) {
+ ALOGW("unable to parse resolution: '%s'", resolution.c_str());
+ return false;
+ }
+ std::string w = resolution.substr(0, sep);
+ std::string h = resolution.substr(sep+1);
+
+ char *q;
+ const char *p = w.c_str();
+ width = strtol(p, &q, 0);
+ if (q == p) {
+ width = -1;
+ }
+ p = h.c_str();
+ height = strtol(p, &q, 0);
+ if (q == p) {
+ height = -1;
+ }
+ if (width <= 0 || height <= 0 || width > DIMENSION_LIMIT || height > DIMENSION_LIMIT) {
+ ALOGW("unparseable: width, height '%s'", resolution.c_str());
+ return false;
+ }
+ }
+
+ const char *p = value.c_str();
+ char *q;
+ qpMax = strtol(p, &q, 0);
+ if (q == p) {
+ ALOGW("unparseable qpmax '%s'", value.c_str());
+ return false;
+ }
+
+ // convert to our internal 'unspecified' notation
+ if (qpMax == -1)
+ qpMax = INT32_MAX;
+
+ struct qpmax_point *point = (struct qpmax_point*) malloc(sizeof(*point));
+ if (point == nullptr) {
+ ALOGW("unable to allocate memory for qpmax point");
+ return false;
+ }
+
+ point->pixels = width * height;
+ point->width = width;
+ point->height = height;
+ point->qpMax = qpMax;
+
+ if (mQpMaxPoints == nullptr) {
+ point->next = nullptr;
+ mQpMaxPoints = point;
+ } else if (point->pixels < mQpMaxPoints->pixels) {
+ // at the front
+ point->next = mQpMaxPoints;
+ mQpMaxPoints = point;
+ } else {
+ struct qpmax_point *after = mQpMaxPoints;
+ while (after->next) {
+ if (point->pixels > after->next->pixels) {
+ after = after->next;
+ continue;
+ }
+
+ // insert before after->next
+ point->next = after->next;
+ after->next = point;
+ break;
+ }
+ if (after->next == nullptr) {
+ // hasn't gone in yet
+ point->next = nullptr;
+ after->next = point;
+ }
+ }
+
+ return true;
+}
+
+int CodecProperties::targetQpMax(int32_t width, int32_t height) {
+ // look in the per-resolution list
+
+ int32_t pixels = width * height;
+
+ if (mQpMaxPoints) {
+ struct qpmax_point *point = mQpMaxPoints;
+ while (point && point->pixels < pixels) {
+ point = point->next;
+ }
+ if (point) {
+ ALOGV("targetQpMax(w=%d,h=%d) returns %d from qpmax_point w=%d h=%d",
+ width, height, point->qpMax, point->width, point->height);
+ return point->qpMax;
+ }
+ }
+
+ ALOGV("defaulting to %d qpmax", mTargetQpMax);
+ return mTargetQpMax;
+}
+
+void CodecProperties::setTargetQpMax(int qpMax) {
+ // convert to our internal 'unspecified' notation
+ if (qpMax == -1)
+ qpMax = INT32_MAX;
+ mTargetQpMax = qpMax;
+}
+
std::string CodecProperties::getMapping(std::string key, std::string kind) {
ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str());
//play with mMappings
diff --git a/media/libmediaformatshaper/CodecProperties.h b/media/libmediaformatshaper/CodecProperties.h
index ff7051f..196a40f 100644
--- a/media/libmediaformatshaper/CodecProperties.h
+++ b/media/libmediaformatshaper/CodecProperties.h
@@ -69,7 +69,7 @@
// qp max bound used to compensate when SupportedMinimumQuality == 0
// 0 == let a system default handle it
void setTargetQpMax(int qpmax);
- int targetQpMax();
+ int targetQpMax(int32_t width, int32_t height);
// target bits-per-pixel (per second) for encoding operations.
// This is used to calculate a minimum bitrate for any particular resolution.
@@ -82,6 +82,14 @@
void setSupportsQp(bool supported) { mSupportsQp = supported;}
bool supportsQp() { return mSupportsQp;}
+ // defines our range of operation -- multiplier on the floor bitrate
+ double getPhaseOut() { return mPhaseOut; }
+ void setPhaseOut(double overageMultiplier);
+
+ // how much (0.20 = +20%) do we add if Qp is requested but unsupported
+ double getMissingQpBoost() {return mMissingQpBoost; }
+ void setMissingQpBoost(double boost);
+
int supportedApi();
// a codec is not usable until it has been registered with its
@@ -98,6 +106,11 @@
bool mSupportsQp = false;
double mBpp = 0.0;
+ // target bitrates above floor * mPhaseOut are left untouched
+ double mPhaseOut = 1.75;
+ // 20% bump if QP is configured but it is unavailable
+ double mMissingQpBoost = 0.20;
+
// allow different target bits-per-pixel based on resolution
// similar to codec 'performance points'
// uses 'next largest' (by pixel count) point as minimum bpp
@@ -110,6 +123,19 @@
struct bpp_point *mBppPoints = nullptr;
bool bppPoint(std::string resolution, std::string value);
+ // same thing for qpmax -- allow different ones based on resolution
+ // allow different target bits-per-pixel based on resolution
+ // similar to codec 'performance points'
+ // uses 'next largest' (by pixel count) point as minimum bpp
+ struct qpmax_point {
+ struct qpmax_point *next;
+ int32_t pixels;
+ int32_t width, height;
+ int qpMax;
+ };
+ struct qpmax_point *mQpMaxPoints = nullptr;
+ bool qpMaxPoint(std::string resolution, std::string value);
+
std::mutex mMappingLock;
// XXX figure out why I'm having problems getting compiler to like GUARDED_BY
std::map<std::string, std::string> mMappings /*GUARDED_BY(mMappingLock)*/ ;
diff --git a/media/libmediaformatshaper/CodecSeeding.cpp b/media/libmediaformatshaper/CodecSeeding.cpp
index 7fe1075..2f2e29d 100644
--- a/media/libmediaformatshaper/CodecSeeding.cpp
+++ b/media/libmediaformatshaper/CodecSeeding.cpp
@@ -49,25 +49,39 @@
*/
static preloadTuning_t featuresAvc[] = {
- // {true, "vq-target-bpp", "2.45"},
- {true, "vq-target-bpp-1080p", "2.40"},
- {true, "vq-target-bpp-540p", "2.60"},
+ {true, "vq-target-bpp", "0"},
+ {true, "vq-target-bpp-1080p", "1.90"},
+ {true, "vq-target-bpp-720p", "2.25"},
+ {true, "vq-target-bpp-540p", "2.65"},
{true, "vq-target-bpp-480p", "3.00"},
- {true, "vq-target-qpmax", "40"},
+ {true, "vq-target-qpmax", "-1"},
+ {true, "vq-target-qpmax-1080p", "45"},
+ {true, "vq-target-qpmax-720p", "43"},
+ {true, "vq-target-qpmax-540p", "42"},
+ {true, "vq-target-qpmax-480p", "38"},
+ {true, "vq-bitrate-phaseout", "1.75"},
+ {true, "vq-boost-missing-qp", "0.20"},
{true, nullptr, 0}
};
static preloadTuning_t featuresHevc[] = {
- // {true, "vq-target-bpp", "1.80"},
+ {true, "vq-target-bpp", "0"},
{true, "vq-target-bpp-1080p", "1.50"},
{true, "vq-target-bpp-720p", "1.80"},
{true, "vq-target-bpp-540p", "2.10"},
- // no qp for hevc, at least for now
+ {true, "vq-target-qpmax", "-1"},
+ {true, "vq-target-qpmax-1080p", "45"},
+ {true, "vq-target-qpmax-720p", "43"},
+ {true, "vq-target-qpmax-540p", "42"},
+ {true, "vq-target-qpmax-480p", "39"},
+ {true, "vq-bitrate-phaseout", "1.75"},
+ {true, "vq-boost-missing-qp", "0.20"},
{true, nullptr, 0}
};
static preloadTuning_t featuresGenericVideo[] = {
- {true, "vq-target-bpp", "2.40"},
+ // 0 == off
+ {true, "vq-target-bpp", "0"},
{true, nullptr, 0}
};
diff --git a/media/libmediaformatshaper/VQApply.cpp b/media/libmediaformatshaper/VQApply.cpp
index 4f6a6c3..585ec6c 100644
--- a/media/libmediaformatshaper/VQApply.cpp
+++ b/media/libmediaformatshaper/VQApply.cpp
@@ -49,14 +49,6 @@
static const int BITRATE_MODE_VBR = 1;
-// constants we use within the calculations
-//
-constexpr double BITRATE_LEAVE_UNTOUCHED = 1.75;
-
-// 20% bump if QP is configured but it is unavailable
-constexpr double BITRATE_QP_UNAVAILABLE_BOOST = 0.20;
-
-
//
// Caller retains ownership of and responsibility for inFormat
//
@@ -100,7 +92,7 @@
double minimumBpp = codec->getBpp(width, height);
int64_t bitrateFloor = pixels * minimumBpp;
- int64_t bitrateCeiling = bitrateFloor * BITRATE_LEAVE_UNTOUCHED;
+ int64_t bitrateCeiling = bitrateFloor * codec->getPhaseOut();
if (bitrateFloor > INT32_MAX) bitrateFloor = INT32_MAX;
if (bitrateCeiling > INT32_MAX) bitrateCeiling = INT32_MAX;
@@ -123,7 +115,7 @@
bool qpPresent = hasQpMax(inFormat);
// calculate a target QP value
- int32_t qpmax = codec->targetQpMax();
+ int32_t qpmax = codec->targetQpMax(width, height);
if (!qpPresent) {
// user didn't, so shaper wins
if (qpmax != INT32_MAX) {
@@ -144,8 +136,7 @@
// if QP is desired but not supported, compensate with additional bits
if (!codec->supportsQp()) {
if (qpChosen != INT32_MAX) {
- int64_t boost = 0;
- boost = bitrateChosen * BITRATE_QP_UNAVAILABLE_BOOST;
+ int64_t boost = bitrateChosen * codec->getMissingQpBoost();
ALOGD("minquality: requested QP unsupported, boost bitrate %" PRId64 " by %" PRId64,
bitrateChosen, boost);
bitrateChosen = bitrateChosen + boost;
@@ -165,7 +156,7 @@
if (bitrateChosen != bitrateConfigured) {
if (bitrateChosen > bitrateCeiling) {
- ALOGD("minquality: bitrate clamped at ceiling %" PRId64, bitrateCeiling);
+ ALOGD("minquality: bitrate increase clamped at ceiling %" PRId64, bitrateCeiling);
bitrateChosen = bitrateCeiling;
}
ALOGD("minquality/target bitrate raised from %" PRId64 " to %" PRId64 " bps",
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 383bae8..a09a673 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -160,12 +160,14 @@
#define AMEDIAMETRICS_PROP_VOLUME_LEFT "volume.left" // double (AudioTrack)
#define AMEDIAMETRICS_PROP_VOLUME_RIGHT "volume.right" // double (AudioTrack)
#define AMEDIAMETRICS_PROP_WHERE "where" // string value
-// EncodingRequested is the encoding format requested by the app
-#define AMEDIAMETRICS_PROP_ENCODINGREQUESTED "encodingRequested" // string
-// PerformanceModeActual is the actual selected performance mode, could be "none', "loeLatency" or
+// EncodingClient is the encoding format requested by the client
+#define AMEDIAMETRICS_PROP_ENCODINGCLIENT "encodingClient" // string
+// PerformanceModeActual is the actual selected performance mode, could be "none', "lowLatency" or
// "powerSaving"
#define AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL "performanceModeActual" // string
#define AMEDIAMETRICS_PROP_FRAMESTRANSFERRED "framesTransferred" // int64_t, transferred frames
+// string value, "exclusive", "shared". the actual selected sharing mode by the server
+#define AMEDIAMETRICS_PROP_SHARINGMODEACTUAL "sharingModeActual"
// Timing values: millisecond values are suffixed with MS and the type is double
// nanosecond values are suffixed with NS and the type is int64.
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index b485b1e..ce642f3 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -79,6 +79,7 @@
// NB: these are matched with public Java API constants defined
// in frameworks/base/media/java/android/media/MediaRecorder.java
// These must be kept synchronized with the constants there.
+static const char *kRecorderLogSessionId = "android.media.mediarecorder.log-session-id";
static const char *kRecorderAudioBitrate = "android.media.mediarecorder.audio-bitrate";
static const char *kRecorderAudioChannels = "android.media.mediarecorder.audio-channels";
static const char *kRecorderAudioSampleRate = "android.media.mediarecorder.audio-samplerate";
@@ -160,6 +161,8 @@
// know is the app which requested the recording.
mMetricsItem->setUid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mClient.uid)));
+ mMetricsItem->setCString(kRecorderLogSessionId, mLogSessionId.c_str());
+
// populate the values from the raw fields.
// TBD mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
@@ -914,6 +917,14 @@
return ret;
}
+status_t StagefrightRecorder::setLogSessionId(const String8 &log_session_id) {
+ ALOGV("setLogSessionId: %s", log_session_id.string());
+
+ // TODO: validity check that log_session_id is a 32-byte hex digit.
+ mLogSessionId.setTo(log_session_id.string());
+ return OK;
+}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -1082,6 +1093,8 @@
if (safe_strtoi64(value.string(), &networkHandle)) {
return setSocketNetwork(networkHandle);
}
+ } else if (key == "log-session-id") {
+ return setLogSessionId(value);
} else {
ALOGE("setParameter: failed to find key %s", key.string());
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 278f348..59a080e 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -48,6 +48,7 @@
explicit StagefrightRecorder(const Identity& clientIdentity);
virtual ~StagefrightRecorder();
virtual status_t init();
+ virtual status_t setLogSessionId(const String8 &id);
virtual status_t setAudioSource(audio_source_t as);
status_t setPrivacySensitive(bool privacySensitive) override;
status_t isPrivacySensitive(bool *privacySensitive) const override;
@@ -110,6 +111,7 @@
void flushAndResetMetrics(bool reinitialize);
void updateMetrics();
+ AString mLogSessionId;
audio_source_t mAudioSource;
privacy_sensitive_t mPrivacySensitive;
video_source mVideoSource;
diff --git a/media/libmediatranscoding/TranscoderWrapper.cpp b/media/libmediatranscoding/TranscoderWrapper.cpp
index 5e4c671..60b780f 100644
--- a/media/libmediatranscoding/TranscoderWrapper.cpp
+++ b/media/libmediatranscoding/TranscoderWrapper.cpp
@@ -478,7 +478,7 @@
media_status_t err =
setupTranscoder(clientId, sessionId, request, callingUid, clientCb, &reason);
if (err != AMEDIA_OK) {
- ALOGI("%s: failed to setup transcoder", __FUNCTION__);
+ ALOGE("%s: failed to setup transcoder", __FUNCTION__);
logSessionEnded(reason, err);
return err;
}
@@ -613,7 +613,7 @@
Event event = *mQueue.begin();
mQueue.pop_front();
- ALOGD("%s: %s", __FUNCTION__, toString(event).c_str());
+ ALOGV("%s: %s", __FUNCTION__, toString(event).c_str());
if (event.type == Event::Abandon) {
break;
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index ac3b2c0..8f8ad4e 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -113,6 +113,16 @@
// Asset directory
static const std::string kAssetDirectory = "/data/local/tmp/TranscodingBenchmark/";
+ // Transcoding configuration params to be logged
+ int64_t trackDurationUs = 0;
+ int32_t width = 0;
+ int32_t height = 0;
+ std::string sourceMime = "NA";
+ std::string targetMime = "NA";
+ bool includeAudio = false;
+ bool transcodeVideo = false;
+ int32_t targetBitrate = 0;
+
int srcFd = 0;
int dstFd = 0;
@@ -163,10 +173,30 @@
state.counters[PARAM_VIDEO_FRAME_RATE] = benchmark::Counter(
frameCount, benchmark::Counter::kIsIterationInvariantRate);
}
+ if (!AMediaFormat_getInt32(srcFormat, AMEDIAFORMAT_KEY_WIDTH, &width)) {
+ state.SkipWithError("Video source track format does not have width");
+ goto exit;
+ }
+ if (!AMediaFormat_getInt32(srcFormat, AMEDIAFORMAT_KEY_HEIGHT, &height)) {
+ state.SkipWithError("Video source track format does not have height");
+ goto exit;
+ }
+ AMediaFormat_getInt64(srcFormat, AMEDIAFORMAT_KEY_DURATION, &trackDurationUs);
+ sourceMime = mime;
}
if (trackSelectionCallback(mime, &dstFormat)) {
status = transcoder->configureTrackFormat(i, dstFormat);
+ if (strncmp(mime, "video/", 6) == 0 && dstFormat != nullptr) {
+ const char* mime = nullptr;
+ if (AMediaFormat_getString(dstFormat, AMEDIAFORMAT_KEY_MIME, &mime)) {
+ targetMime = mime;
+ }
+ AMediaFormat_getInt32(dstFormat, AMEDIAFORMAT_KEY_BIT_RATE, &targetBitrate);
+ transcodeVideo = true;
+ } else if (strncmp(mime, "audio/", 6) == 0) {
+ includeAudio = true;
+ }
}
if (dstFormat != nullptr) {
@@ -195,6 +225,17 @@
}
}
+ // Set transcoding configuration params in benchmark label
+ state.SetLabel(srcFileName + "," +
+ std::to_string(width) + "x" + std::to_string(height) + "," +
+ sourceMime + "," +
+ std::to_string(trackDurationUs/1000) + "," +
+ (includeAudio ? "Yes" : "No") + "," +
+ (transcodeVideo ? "Yes" : "No") + "," +
+ targetMime + "," +
+ std::to_string(targetBitrate)
+ );
+
exit:
if (srcFd > 0) close(srcFd);
if (dstFd > 0) close(dstFd);
@@ -543,7 +584,11 @@
void PrintRunData(const Run& report);
bool mPrintedHeader;
- std::vector<std::string> mHeaders = {"name", "real_time", "cpu_time", PARAM_VIDEO_FRAME_RATE};
+ std::vector<std::string> mHeaders = {
+ "File", "Resolution", "SourceMime", "VideoTrackDuration(ms)",
+ "IncludeAudio", "TranscodeVideo", "TargetMime", "TargetBirate(bps)",
+ "real_time(ms)", "cpu_time(ms)", PARAM_VIDEO_FRAME_RATE
+ };
};
bool CustomCsvReporter::ReportContext(const Context& context __unused) {
@@ -574,7 +619,8 @@
return;
}
std::ostream& Out = GetOutputStream();
- Out << run.benchmark_name() << ",";
+ // Log the transcoding params reported through label
+ Out << run.report_label << ",";
Out << run.GetAdjustedRealTime() << ",";
Out << run.GetAdjustedCPUTime() << ",";
auto frameRate = run.counters.find(PARAM_VIDEO_FRAME_RATE);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 944e007..6b2e7be 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -102,6 +102,17 @@
static const char *kCodecWidth = "android.media.mediacodec.width"; /* 0..n */
static const char *kCodecHeight = "android.media.mediacodec.height"; /* 0..n */
static const char *kCodecRotation = "android.media.mediacodec.rotation-degrees"; /* 0/90/180/270 */
+static const char *kCodecColorFormat = "android.media.mediacodec.color-format";
+static const char *kCodecFrameRate = "android.media.mediacodec.frame-rate";
+static const char *kCodecCaptureRate = "android.media.mediacodec.capture-rate";
+static const char *kCodecOperatingRate = "android.media.mediacodec.operating-rate";
+static const char *kCodecPriority = "android.media.mediacodec.priority";
+static const char *kCodecRequestedVideoQPIMin = "android.media.mediacodec.video-qp-i-min";
+static const char *kCodecRequestedVideoQPIMax = "android.media.mediacodec.video-qp-i-max";
+static const char *kCodecRequestedVideoQPPMin = "android.media.mediacodec.video-qp-p-min";
+static const char *kCodecRequestedVideoQPPMax = "android.media.mediacodec.video-qp-p-max";
+static const char *kCodecRequestedVideoQPBMin = "android.media.mediacodec.video-qp-b-min";
+static const char *kCodecRequestedVideoQPBMax = "android.media.mediacodec.video-qp-b-max";
// NB: These are not yet exposed as public Java API constants.
static const char *kCodecCrypto = "android.media.mediacodec.crypto"; /* 0,1 */
@@ -131,6 +142,8 @@
static const char *kCodecSampleRate = "android.media.mediacodec.sampleRate";
static const char *kCodecVideoEncodedBytes = "android.media.mediacodec.vencode.bytes";
static const char *kCodecVideoEncodedFrames = "android.media.mediacodec.vencode.frames";
+static const char *kCodecVideoInputBytes = "android.media.mediacodec.video.input.bytes";
+static const char *kCodecVideoInputFrames = "android.media.mediacodec.video.input.frames";
static const char *kCodecVideoEncodedDurationUs = "android.media.mediacodec.vencode.durationUs";
// the kCodecRecent* fields appear only in getMetrics() results
@@ -841,6 +854,8 @@
}
mediametrics_setInt64(mMetricsHandle, kCodecVideoEncodedDurationUs, duration);
mediametrics_setInt64(mMetricsHandle, kCodecVideoEncodedFrames, mFramesEncoded);
+ mediametrics_setInt64(mMetricsHandle, kCodecVideoInputFrames, mFramesInput);
+ mediametrics_setInt64(mMetricsHandle, kCodecVideoInputBytes, mBytesInput);
}
{
@@ -1053,7 +1068,7 @@
}
// when we send a buffer to the codec;
-void MediaCodec::statsBufferSent(int64_t presentationUs) {
+void MediaCodec::statsBufferSent(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer) {
// only enqueue if we have a legitimate time
if (presentationUs <= 0) {
@@ -1067,6 +1082,11 @@
});
}
+ if (mIsVideo && (mFlags & kFlagIsEncoder)) {
+ mBytesInput += buffer->size();
+ mFramesInput++;
+ }
+
const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
BufferFlightTiming_t startdata = { presentationUs, nowNs };
@@ -1450,6 +1470,50 @@
if (format->findInt32("max-height", &maxHeight)) {
mediametrics_setInt32(mMetricsHandle, kCodecMaxHeight, maxHeight);
}
+ int32_t colorFormat = -1;
+ if (format->findInt32("color-format", &colorFormat)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecColorFormat, colorFormat);
+ }
+ float frameRate = -1.0;
+ if (format->findFloat("frame-rate", &frameRate)) {
+ mediametrics_setDouble(mMetricsHandle, kCodecFrameRate, frameRate);
+ }
+ float captureRate = -1.0;
+ if (format->findFloat("capture-rate", &captureRate)) {
+ mediametrics_setDouble(mMetricsHandle, kCodecCaptureRate, captureRate);
+ }
+ float operatingRate = -1.0;
+ if (format->findFloat("operating-rate", &operatingRate)) {
+ mediametrics_setDouble(mMetricsHandle, kCodecOperatingRate, operatingRate);
+ }
+ int32_t priority = -1;
+ if (format->findInt32("priority", &priority)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecPriority, priority);
+ }
+ int32_t qpIMin = -1;
+ if (format->findInt32("video-qp-i-min", &qpIMin)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMin, qpIMin);
+ }
+ int32_t qpIMax = -1;
+ if (format->findInt32("video-qp-i-max", &qpIMax)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMax, qpIMax);
+ }
+ int32_t qpPMin = -1;
+ if (format->findInt32("video-qp-p-min", &qpPMin)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMin, qpPMin);
+ }
+ int32_t qpPMax = -1;
+ if (format->findInt32("video-qp-p-max", &qpPMax)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMax, qpPMax);
+ }
+ int32_t qpBMin = -1;
+ if (format->findInt32("video-qp-b-min", &qpBMin)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMin, qpBMin);
+ }
+ int32_t qpBMax = -1;
+ if (format->findInt32("video-qp-b-max", &qpBMax)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMax, qpBMax);
+ }
}
// Prevent possible integer overflow in downstream code.
@@ -4664,7 +4728,7 @@
info->mOwnedByClient = false;
info->mData.clear();
- statsBufferSent(timeUs);
+ statsBufferSent(timeUs, buffer);
}
return err;
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index f0383b5..a5c3ba6 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -885,4 +885,15 @@
return ERROR_UNSUPPORTED;
}
+status_t NuMediaExtractor::setLogSessionId(const String8& logSessionId) {
+ if (mImpl == nullptr) {
+ return ERROR_UNSUPPORTED;
+ }
+ status_t status = mImpl->setLogSessionId(logSessionId);
+ if (status != OK) {
+ ALOGW("Failed to set log session id: %d.", status);
+ }
+ return status;
+}
+
} // namespace android
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 381eb1a..baa2ca1 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -39,7 +39,11 @@
static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
static const char *kExtractorMime = "android.media.mediaextractor.mime";
static const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
+
+// The following are not available in frameworks/base/media/java/android/media/MediaExtractor.java
+// because they are not applicable or useful to that API.
static const char *kExtractorEntryPoint = "android.media.mediaextractor.entry";
+static const char *kExtractorLogSessionId = "android.media.mediaextractor.logSessionId";
static const char *kEntryPointSdk = "sdk";
static const char *kEntryPointWithJvm = "ndk-with-jvm";
@@ -174,6 +178,11 @@
return OK;
}
+status_t RemoteMediaExtractor::setLogSessionId(const String8& logSessionId) {
+ mMetricsItem->setCString(kExtractorLogSessionId, logSessionId.c_str());
+ return OK;
+}
+
////////////////////////////////////////////////////////////////////////////////
// static
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index fda9f4c..4c18f87 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -47,6 +47,16 @@
#include <media/AudioParameter.h>
#include <system/audio.h>
+// TODO : Remove the defines once mainline media is built against NDK >= 31.
+// The mp4 extractor is part of mainline and builds against NDK 29 as of
+// writing. These keys are available only from NDK 31:
+#define AMEDIAFORMAT_KEY_MPEGH_PROFILE_LEVEL_INDICATION \
+ "mpegh-profile-level-indication"
+#define AMEDIAFORMAT_KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT \
+ "mpegh-reference-channel-layout"
+#define AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS \
+ "mpegh-compatible-sets"
+
namespace android {
static status_t copyNALUToABuffer(sp<ABuffer> *buffer, const uint8_t *ptr, size_t length) {
@@ -1085,6 +1095,25 @@
msg->setInt32("is-adts", isADTS);
}
+ int32_t mpeghProfileLevelIndication;
+ if (meta->findInt32(kKeyMpeghProfileLevelIndication, &mpeghProfileLevelIndication)) {
+ msg->setInt32(AMEDIAFORMAT_KEY_MPEGH_PROFILE_LEVEL_INDICATION,
+ mpeghProfileLevelIndication);
+ }
+ int32_t mpeghReferenceChannelLayout;
+ if (meta->findInt32(kKeyMpeghReferenceChannelLayout, &mpeghReferenceChannelLayout)) {
+ msg->setInt32(AMEDIAFORMAT_KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT,
+ mpeghReferenceChannelLayout);
+ }
+ if (meta->findData(kKeyMpeghCompatibleSets, &type, &data, &size)) {
+ sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
+ msg->setBuffer(AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS, buffer);
+ memcpy(buffer->data(), data, size);
+ }
+
int32_t aacProfile = -1;
if (meta->findInt32(kKeyAACAOT, &aacProfile)) {
msg->setInt32("aac-profile", aacProfile);
@@ -1850,6 +1879,23 @@
meta->setInt32(kKeyIsADTS, isADTS);
}
+ int32_t mpeghProfileLevelIndication = -1;
+ if (msg->findInt32(AMEDIAFORMAT_KEY_MPEGH_PROFILE_LEVEL_INDICATION,
+ &mpeghProfileLevelIndication)) {
+ meta->setInt32(kKeyMpeghProfileLevelIndication, mpeghProfileLevelIndication);
+ }
+ int32_t mpeghReferenceChannelLayout = -1;
+ if (msg->findInt32(AMEDIAFORMAT_KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT,
+ &mpeghReferenceChannelLayout)) {
+ meta->setInt32(kKeyMpeghReferenceChannelLayout, mpeghReferenceChannelLayout);
+ }
+ sp<ABuffer> mpeghCompatibleSets;
+ if (msg->findBuffer(AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS,
+ &mpeghCompatibleSets)) {
+ meta->setData(kKeyMpeghCompatibleSets, kTypeHCOS,
+ mpeghCompatibleSets->data(), mpeghCompatibleSets->size());
+ }
+
int32_t aacProfile = -1;
if (msg->findInt32("aac-profile", &aacProfile)) {
meta->setInt32(kKeyAACAOT, aacProfile);
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 7655d90..4bfc673 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -45,6 +45,9 @@
],
header_libs: [
+ // this is only needed for the vendor variant that removes libbinder, but vendor
+ // target below does not allow adding header_libs.
+ "libbinder_headers",
"libstagefright_foundation_headers",
"media_ndk_headers",
"media_plugin_headers",
@@ -98,6 +101,7 @@
target: {
vendor: {
+ // TODO: add libbinder_headers here instead of above when it becomes supported
exclude_shared_libs: [
"libbinder",
],
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index c216bc5..ada5d81 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -58,6 +58,8 @@
const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3";
const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC = "audio/eac3-joc";
const char *MEDIA_MIMETYPE_AUDIO_AC4 = "audio/ac4";
+const char *MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1 = "audio/mha1";
+const char *MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1 = "audio/mhm1";
const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac";
const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index e96243e..f5cecef 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -60,6 +60,8 @@
extern const char *MEDIA_MIMETYPE_AUDIO_EAC3;
extern const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC;
extern const char *MEDIA_MIMETYPE_AUDIO_AC4;
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1;
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1;
extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED;
extern const char *MEDIA_MIMETYPE_AUDIO_ALAC;
extern const char *MEDIA_MIMETYPE_AUDIO_WMA;
@@ -90,6 +92,8 @@
kAudioEncodingPcm16bit = 2,
kAudioEncodingPcm8bit = 3,
kAudioEncodingPcmFloat = 4,
+ kAudioEncodingPcm24bitPacked = 21,
+ kAudioEncodingPcm32bit = 22,
};
} // namespace android
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index e97f6eb..b7c9062 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -234,9 +234,11 @@
}
// first handle global unsynchronization
+ bool hasGlobalUnsync = false;
if (header.flags & 0x80) {
ALOGV("removing unsynchronization");
+ hasGlobalUnsync = true;
removeUnsynchronization();
}
@@ -341,12 +343,12 @@
memcpy(copy, mData, size);
- bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
+ bool success = removeUnsynchronizationV2_4(false /* iTunesHack */, hasGlobalUnsync);
if (!success) {
memcpy(mData, copy, size);
mSize = size;
- success = removeUnsynchronizationV2_4(true /* iTunesHack */);
+ success = removeUnsynchronizationV2_4(true /* iTunesHack */, hasGlobalUnsync);
if (success) {
ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
@@ -407,7 +409,7 @@
}
}
-bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
+bool ID3::removeUnsynchronizationV2_4(bool iTunesHack, bool hasGlobalUnsync) {
size_t oldSize = mSize;
size_t offset = mFirstFrameOffset;
@@ -443,7 +445,7 @@
flags &= ~1;
}
- if ((flags & 2) && (dataSize >= 2)) {
+ if (!hasGlobalUnsync && (flags & 2) && (dataSize >= 2)) {
// This frame has "unsynchronization", so we have to replace occurrences
// of 0xff 0x00 with just 0xff in order to get the real data.
diff --git a/media/libstagefright/id3/test/AndroidTest.xml b/media/libstagefright/id3/test/AndroidTest.xml
index d6ea470..50f9253 100644
--- a/media/libstagefright/id3/test/AndroidTest.xml
+++ b/media/libstagefright/id3/test/AndroidTest.xml
@@ -19,7 +19,7 @@
<option name="cleanup" value="true" />
<option name="push" value="ID3Test->/data/local/tmp/ID3Test" />
<option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.1.zip?unzip=true"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true"
value="/data/local/tmp/ID3TestRes/" />
</target_preparer>
diff --git a/media/libstagefright/id3/test/ID3Test.cpp b/media/libstagefright/id3/test/ID3Test.cpp
index 8db83cb..1ceeb6a 100644
--- a/media/libstagefright/id3/test/ID3Test.cpp
+++ b/media/libstagefright/id3/test/ID3Test.cpp
@@ -135,6 +135,7 @@
} else {
ASSERT_EQ(data, nullptr) << "Found album art when expected none!";
}
+
#if (LOG_NDEBUG == 0)
hexdump(data, dataSize > 128 ? 128 : dataSize);
#endif
@@ -186,7 +187,8 @@
"bbb_1sec_v23_3tags.mp3",
"bbb_1sec_v1_5tags.mp3",
"bbb_2sec_v24_unsynchronizedOneFrame.mp3",
- "bbb_2sec_v24_unsynchronizedAllFrames.mp3"));
+ "bbb_2sec_v24_unsynchronizedAllFrames.mp3",
+ "idv24_unsynchronized.mp3"));
INSTANTIATE_TEST_SUITE_P(
id3TestAll, ID3versionTest,
@@ -201,7 +203,8 @@
make_pair("bbb_1sec_v1_5tags.mp3", ID3::ID3_V1_1),
make_pair("bbb_1sec_v1_3tags.mp3", ID3::ID3_V1_1),
make_pair("bbb_2sec_v24_unsynchronizedOneFrame.mp3", ID3::ID3_V2_4),
- make_pair("bbb_2sec_v24_unsynchronizedAllFrames.mp3", ID3::ID3_V2_4)));
+ make_pair("bbb_2sec_v24_unsynchronizedAllFrames.mp3", ID3::ID3_V2_4),
+ make_pair("idv24_unsynchronized.mp3", ID3::ID3_V2_4)));
INSTANTIATE_TEST_SUITE_P(
id3TestAll, ID3textTagTest,
@@ -227,7 +230,9 @@
make_pair("bbb_2sec_1_image.mp3", true),
make_pair("bbb_2sec_2_image.mp3", true),
make_pair("bbb_2sec_largeSize.mp3", true),
- make_pair("bbb_1sec_v1_5tags.mp3", false)));
+ make_pair("bbb_1sec_v1_5tags.mp3", false),
+ make_pair("idv24_unsynchronized.mp3", true)
+ ));
INSTANTIATE_TEST_SUITE_P(id3TestAll, ID3multiAlbumArtTest,
::testing::Values(make_pair("bbb_1sec_v23.mp3", 0),
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 0be5896..bd0d27c 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -91,7 +91,7 @@
bool parseV1(DataSourceBase *source);
bool parseV2(DataSourceBase *source, off64_t offset);
void removeUnsynchronization();
- bool removeUnsynchronizationV2_4(bool iTunesHack);
+ bool removeUnsynchronizationV2_4(bool iTunesHack, bool hasGlobalUnsync);
static bool ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 3f93e6d..0584054 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -572,8 +572,9 @@
int64_t mBytesEncoded = 0;
int64_t mEarliestEncodedPtsUs = INT64_MAX;
int64_t mLatestEncodedPtsUs = INT64_MIN;
- int32_t mFramesEncoded = 0;
-
+ int64_t mFramesEncoded = 0;
+ int64_t mBytesInput = 0;
+ int64_t mFramesInput = 0;
int64_t mNumLowLatencyEnables; // how many times low latency mode is enabled
int64_t mNumLowLatencyDisables; // how many times low latency mode is disabled
@@ -590,7 +591,7 @@
sp<BatteryChecker> mBatteryChecker;
- void statsBufferSent(int64_t presentationUs);
+ void statsBufferSent(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer);
void statsBufferReceived(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer);
enum {
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 08925b5..c80012e 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -155,6 +155,10 @@
kKeyIsADTS = 'adts', // bool (int32_t)
kKeyAACAOT = 'aaot', // int32_t
+ kKeyMpeghProfileLevelIndication = 'hpli', // int32_t
+ kKeyMpeghReferenceChannelLayout = 'hrcl', // int32_t
+ kKeyMpeghCompatibleSets = 'hcos', // raw data
+
// If a MediaBuffer's data represents (at least partially) encrypted
// data, the following fields aid in decryption.
// The data can be thought of as pairs of plain and encrypted data
@@ -280,6 +284,7 @@
kTypeAV1C = 'av1c',
kTypeDVCC = 'dvcc',
kTypeD263 = 'd263',
+ kTypeHCOS = 'hcos',
};
enum {
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 6aa7c0f..d17a480 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -100,7 +100,7 @@
status_t getAudioPresentations(size_t trackIdx, AudioPresentationCollection *presentations);
- status_t setPlaybackId(const String8& playbackId);
+ status_t setLogSessionId(const String8& logSessionId);
const char* getName() const;
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 25125f2..9ad90d7 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -43,6 +43,7 @@
virtual status_t setMediaCas(const HInterfaceToken &casToken);
virtual String8 name();
virtual status_t setEntryPoint(EntryPoint entryPoint);
+ virtual status_t setLogSessionId(const String8& logSessionId);
private:
MediaExtractor *mExtractor;
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
index c82e532..05373c9 100644
--- a/media/mediaserver/mediaserver.rc
+++ b/media/mediaserver/mediaserver.rc
@@ -7,9 +7,3 @@
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
-
-# media.transcoding service is defined on com.android.media apex which goes back
-# to API29, but we only want it started on API31+ devices. So we declare it as
-# "disabled" and start it explicitly on boot.
-on boot
- start media.transcoding
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 3007574..8d527e9 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -85,7 +85,9 @@
cc_library_shared {
name: "libmediandk",
- llndk_stubs: "libmediandk.llndk",
+ llndk: {
+ symbol_file: "libmediandk.map.txt",
+ },
srcs: [
"NdkJavaVMHelper.cpp",
@@ -168,14 +170,6 @@
},
}
-llndk_library {
- name: "libmediandk.llndk",
- symbol_file: "libmediandk.map.txt",
- export_include_dirs: [
- "include",
- ],
-}
-
cc_library {
name: "libmediandk_utils",
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index e5eeba3..e3931b1 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -73,6 +73,8 @@
return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
case AUDIO_SOURCE_REMOTE_SUBMIX:
return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
+ case AUDIO_SOURCE_VOICE_DOWNLINK:
+ return AppOpsManager::OP_RECORD_INCOMING_PHONE_AUDIO;
case AUDIO_SOURCE_DEFAULT:
default:
return AppOpsManager::OP_RECORD_AUDIO;
@@ -211,10 +213,7 @@
if (ok) {
static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
- //TODO: b/185972521: see if permission cache can be used with shell identity for CTS
- PermissionController permissionController;
- ok = permissionController.checkPermission(sCaptureHotwordAllowed,
- pid, uid);
+ ok = PermissionCache::checkPermission(sCaptureHotwordAllowed, pid, uid);
}
if (!ok) ALOGV("android.permission.CAPTURE_AUDIO_HOTWORD");
return ok;
@@ -300,6 +299,10 @@
return identity;
}
+void purgePermissionCache() {
+ PermissionCache::purgeCache();
+}
+
status_t checkIMemory(const sp<IMemory>& iMemory)
{
if (iMemory == 0) {
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 9a3c6fb..6e75746 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -97,6 +97,7 @@
bool dumpAllowed();
bool modifyPhoneStateAllowed(const media::permission::Identity& identity);
bool bypassInterruptionPolicyAllowed(const media::permission::Identity& identity);
+void purgePermissionCache();
media::permission::Identity getCallingIdentity();
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index b953c0b..451c198 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -70,7 +70,7 @@
audio_input_flags_t flags,
track_type type,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
- int64_t startTimeMs = -1);
+ int32_t startFrames = -1);
virtual ~RecordTrack();
virtual status_t initCheck() const;
@@ -110,7 +110,7 @@
status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t shareAudioHistory(const std::string& sharedAudioPackageName,
int64_t sharedAudioStartMs);
- int64_t startTimeMs() { return mStartTimeMs; }
+ int32_t startFrames() { return mStartFrames; }
static bool checkServerLatencySupported(
audio_format_t format, audio_input_flags_t flags) {
@@ -152,7 +152,7 @@
// used to enforce OP_RECORD_AUDIO
sp<OpRecordAudioMonitor> mOpRecordAudioMonitor;
std::string mSharedAudioPackageName = {};
- int64_t mStartTimeMs = -1;
+ int32_t mStartFrames = -1;
};
// playback track, used by PatchPanel
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6da4543..51f3032 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -124,12 +124,26 @@
// 50 * ~20msecs = 1 second
static const int8_t kMaxTrackRetries = 50;
static const int8_t kMaxTrackStartupRetries = 50;
+
// allow less retry attempts on direct output thread.
// direct outputs can be a scarce resource in audio hardware and should
// be released as quickly as possible.
-static const int8_t kMaxTrackRetriesDirect = 2;
-
-
+// Notes:
+// 1) The retry duration kMaxTrackRetriesDirectMs may be increased
+// in case the data write is bursty for the AudioTrack. The application
+// should endeavor to write at least once every kMaxTrackRetriesDirectMs
+// to prevent an underrun situation. If the data is bursty, then
+// the application can also throttle the data sent to be even.
+// 2) For compressed audio data, any data present in the AudioTrack buffer
+// will be sent and reset the retry count. This delivers data as
+// it arrives, with approximately kDirectMinSleepTimeUs = 10ms checking interval.
+// 3) For linear PCM or proportional PCM, we wait one period for a period's worth
+// of data to be available, then any remaining data is delivered.
+// This is required to ensure the last bit of data is delivered before underrun.
+//
+// Sleep time per cycle is kDirectMinSleepTimeUs for compressed tracks
+// or the size of the HAL period for proportional / linear PCM tracks.
+static const int32_t kMaxTrackRetriesDirectMs = 200;
// don't warn about blocked writes or record buffer overflows more often than this
static const nsecs_t kWarningThrottleNs = seconds(5);
@@ -5931,11 +5945,19 @@
// Allow draining the buffer in case the client
// app does not call stop() and relies on underrun to stop:
// hence the test on (track->mRetryCount > 1).
- // If retryCount<=1 then track is about to underrun and be removed.
+ // If track->mRetryCount <= 1 then track is about to be disabled, paused, removed,
+ // so we accept any nonzero amount of data delivered by the AudioTrack (which will
+ // reset the retry counter).
// Do not use a high threshold for compressed audio.
+
+ // target retry count that we will use is based on the time we wait for retries.
+ const int32_t targetRetryCount = kMaxTrackRetriesDirectMs * 1000 / mActiveSleepTimeUs;
+ // the retry threshold is when we accept any size for PCM data. This is slightly
+ // smaller than the retry count so we can push small bits of data without a glitch.
+ const int32_t retryThreshold = targetRetryCount > 2 ? targetRetryCount - 1 : 1;
uint32_t minFrames;
if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()
- && (track->mRetryCount > 1) && audio_has_proportional_frames(mFormat)) {
+ && (track->mRetryCount > retryThreshold) && audio_has_proportional_frames(mFormat)) {
minFrames = mNormalFrameCount;
} else {
minFrames = 1;
@@ -5979,7 +6001,7 @@
mPreviousTrack = track;
// reset retry count
- track->mRetryCount = kMaxTrackRetriesDirect;
+ track->mRetryCount = targetRetryCount;
mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
if (mHwPaused) {
@@ -6033,15 +6055,17 @@
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
track->disable();
- } else if (last) {
+ // only do hw pause when track is going to be removed due to BUFFER TIMEOUT.
+ // unlike mixerthread, HAL can be paused for direct output
ALOGW("pause because of UNDERRUN, framesReady = %zu,"
"minFrames = %u, mFormat = %#x",
framesReady, minFrames, mFormat);
- mixerStatus = MIXER_TRACKS_ENABLED;
- if (mHwSupportsPause && !mHwPaused && !mStandby) {
+ if (last && mHwSupportsPause && !mHwPaused && !mStandby) {
doHwPause = true;
mHwPaused = true;
}
+ } else if (last) {
+ mixerStatus = MIXER_TRACKS_ENABLED;
}
}
}
@@ -6113,16 +6137,13 @@
mSleepTimeUs = mIdleSleepTimeUs;
return;
}
- if (mSleepTimeUs == 0) {
- if (mMixerStatus == MIXER_TRACKS_ENABLED) {
- mSleepTimeUs = mActiveSleepTimeUs;
- } else {
- mSleepTimeUs = mIdleSleepTimeUs;
- }
- } else if (mBytesWritten != 0 && audio_has_proportional_frames(mFormat)) {
- memset(mSinkBuffer, 0, mFrameCount * mFrameSize);
- mSleepTimeUs = 0;
+ if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+ mSleepTimeUs = mActiveSleepTimeUs;
+ } else {
+ mSleepTimeUs = mIdleSleepTimeUs;
}
+ // Note: In S or later, we do not write zeroes for
+ // linear or proportional PCM direct tracks in underrun.
}
void AudioFlinger::DirectOutputThread::threadLoop_exit()
@@ -7932,18 +7953,18 @@
{ // scope for mLock
Mutex::Autolock _l(mLock);
- long startTimeMs = -1;
+ int32_t startFrames = -1;
if (!mSharedAudioPackageName.empty()
&& mSharedAudioPackageName == checkedIdentity.packageName
&& mSharedAudioSessionId == sessionId
&& captureHotwordAllowed(checkedIdentity)) {
- startTimeMs = mSharedAudioStartMs;
+ startFrames = mSharedAudioStartFrames;
}
track = new RecordTrack(this, client, attr, sampleRate,
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
- checkedIdentity, *flags, TrackBase::TYPE_DEFAULT, portId, startTimeMs);
+ checkedIdentity, *flags, TrackBase::TYPE_DEFAULT, portId, startFrames);
lStatus = track->initCheck();
if (lStatus != NO_ERROR) {
@@ -8200,17 +8221,32 @@
if ((hasAudioSession_l(sharedSessionId) & ThreadBase::TRACK_SESSION) == 0) {
return BAD_VALUE;
}
- if (sharedAudioStartMs < 0 || sharedAudioStartMs * mSampleRate / 1000 > mRsmpInRear) {
+
+ if (sharedAudioStartMs < 0
+ || sharedAudioStartMs > INT64_MAX / mSampleRate) {
return BAD_VALUE;
}
+ // Current implementation of the input resampling buffer wraps around indexes at 32 bit.
+ // As we cannot detect more than one wraparound, only accept values up current write position
+ // after one wraparound
+ // We assume recent wraparounds on mRsmpInRear only given it is unlikely that the requesting
+ // app waits several hours after the start time was computed.
+ const int64_t sharedAudioStartFrames = sharedAudioStartMs * mSampleRate / 1000;
+ const int32_t sharedOffset = audio_utils::safe_sub_overflow(mRsmpInRear,
+ (int32_t)sharedAudioStartFrames);
+ if (sharedOffset < 0
+ || sharedOffset > mRsmpInFrames) {
+ return BAD_VALUE;
+ }
+
mSharedAudioPackageName = sharedAudioPackageName;
if (mSharedAudioPackageName.empty()) {
mSharedAudioSessionId = AUDIO_SESSION_NONE;
- mSharedAudioStartMs = -1;
+ mSharedAudioStartFrames = -1;
} else {
mSharedAudioSessionId = sharedSessionId;
- mSharedAudioStartMs = sharedAudioStartMs;
+ mSharedAudioStartFrames = (int32_t)sharedAudioStartFrames;
}
return NO_ERROR;
}
@@ -8357,14 +8393,14 @@
mRsmpInUnrel = 0;
const int32_t rear = recordThread->mRsmpInRear;
ssize_t deltaFrames = 0;
- if (mRecordTrack->startTimeMs() >= 0) {
- int32_t startFrames = mRecordTrack->startTimeMs() * recordThread->sampleRate() / 1000;
- // start frame has to be in the past
- //TODO: b/185972521 fix in case rear or startFrames wrap around
- if (startFrames > rear) {
- startFrames = rear;
+ if (mRecordTrack->startFrames() >= 0) {
+ int32_t startFrames = mRecordTrack->startFrames();
+ // Accept a recent wraparound of mRsmpInRear
+ if (startFrames <= rear) {
+ deltaFrames = rear - startFrames;
+ } else {
+ deltaFrames = (int32_t)((int64_t)rear + UINT32_MAX + 1 - startFrames);
}
- deltaFrames = rear - startFrames;
// start frame cannot be further in the past than start of resampling buffer
if ((size_t) deltaFrames > recordThread->mRsmpInFrames) {
deltaFrames = recordThread->mRsmpInFrames;
@@ -8826,17 +8862,22 @@
if (mTracks.size() == 0) {
return 0;
}
- //TODO: b/185972521 fix in case of wrap around on one track:
- // want the max(rear - front) for all tracks.
- int32_t front = INT_MAX;
+ int32_t oldestFront = mRsmpInRear;
+ int32_t maxFilled = 0;
for (size_t i = 0; i < mTracks.size(); i++) {
- front = std::min(front, mTracks[i]->mResamplerBufferProvider->getFront());
+ int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
+ int32_t filled;
+ if (front <= mRsmpInRear) {
+ filled = mRsmpInRear - front;
+ } else {
+ filled = (int32_t)((int64_t)mRsmpInRear + UINT32_MAX + 1 - front);
+ }
+ if (filled > maxFilled) {
+ oldestFront = front;
+ maxFilled = filled;
+ }
}
- // discard any audio past the buffer size
- if (audio_utils::safe_add_overflow(front, (int32_t)mRsmpInFrames) < mRsmpInRear) {
- front = audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
- }
- return front;
+ return oldestFront;
}
void AudioFlinger::RecordThread::updateFronts_l(int32_t offset)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 03ed6fd..b6f7f24 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1863,7 +1863,7 @@
DeviceDescriptorBaseVector mOutDevices;
std::string mSharedAudioPackageName = {};
- long mSharedAudioStartMs = 0;
+ int32_t mSharedAudioStartFrames = -1;
audio_session_t mSharedAudioSessionId = AUDIO_SESSION_NONE;
};
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6549236..3e04804 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2378,7 +2378,7 @@
audio_input_flags_t flags,
track_type type,
audio_port_handle_t portId,
- int64_t startTimeMs)
+ int32_t startFrames)
: TrackBase(thread, client, attr, sampleRate, format,
channelMask, frameCount, buffer, bufferSize, sessionId,
creatorPid,
@@ -2396,7 +2396,7 @@
mFlags(flags),
mSilenced(false),
mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(identity, attr)),
- mStartTimeMs(startTimeMs)
+ mStartFrames(startFrames)
{
if (mCblk == NULL) {
return;
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index b5eb98f..fb38e3d 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1019,6 +1019,9 @@
return handleResetUidState(args, err);
} else if (args.size() >= 2 && args[0] == String16("get-uid-state")) {
return handleGetUidState(args, out, err);
+ } else if (args.size() >= 1 && args[0] == String16("purge_permission-cache")) {
+ purgePermissionCache();
+ return NO_ERROR;
} else if (args.size() == 1 && args[0] == String16("help")) {
printHelp(out);
return NO_ERROR;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index edee734..3e6a7c7 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -91,6 +91,8 @@
using hardware::ICameraServiceListener;
using hardware::camera::common::V1_0::CameraDeviceStatus;
using hardware::camera::common::V1_0::TorchModeStatus;
+using hardware::camera2::ICameraInjectionCallback;
+using hardware::camera2::ICameraInjectionSession;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
using hardware::camera2::utils::ConcurrentCameraIdCombination;
@@ -127,6 +129,8 @@
sCameraSendSystemEventsPermission("android.permission.CAMERA_SEND_SYSTEM_EVENTS");
static const String16 sCameraOpenCloseListenerPermission(
"android.permission.CAMERA_OPEN_CLOSE_LISTENER");
+static const String16
+ sCameraInjectExternalCameraPermission("android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");
static constexpr int32_t kVendorClientScore = resource_policy::PERCEPTIBLE_APP_ADJ;
static constexpr int32_t kVendorClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI;
@@ -166,6 +170,7 @@
mUidPolicy->registerSelf();
mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
mSensorPrivacyPolicy->registerSelf();
+ mInjectionStatusListener = new InjectionStatusListener(this);
mAppOps.setCameraAudioRestriction(mAudioRestriction);
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
@@ -243,6 +248,7 @@
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
mUidPolicy->unregisterSelf();
mSensorPrivacyPolicy->unregisterSelf();
+ mInjectionStatusListener->removeListener();
}
void CameraService::onNewProviderRegistered() {
@@ -2386,6 +2392,42 @@
return Status::ok();
}
+Status CameraService::injectCamera(
+ const String16& packageName, const String16& internalCamId,
+ const String16& externalCamId,
+ const sp<ICameraInjectionCallback>& callback,
+ /*out*/
+ sp<hardware::camera2::ICameraInjectionSession>* cameraInjectionSession) {
+ ATRACE_CALL();
+
+ if (!checkCallingPermission(sCameraInjectExternalCameraPermission)) {
+ const int pid = CameraThreadState::getCallingPid();
+ const int uid = CameraThreadState::getCallingUid();
+ ALOGE("Permission Denial: can't inject camera pid=%d, uid=%d", pid, uid);
+ return STATUS_ERROR(ERROR_PERMISSION_DENIED,
+ "Permission Denial: no permission to inject camera");
+ }
+
+ ALOGV(
+ "%s: Package name = %s, Internal camera ID = %s, External camera ID = "
+ "%s",
+ __FUNCTION__, String8(packageName).string(),
+ String8(internalCamId).string(), String8(externalCamId).string());
+
+ binder::Status ret = binder::Status::ok();
+ // TODO: Implement the injection camera function.
+ // ret = internalInjectCamera(...);
+ // if(!ret.isOk()) {
+ // mInjectionStatusListener->notifyInjectionError(...);
+ // return ret;
+ // }
+
+ mInjectionStatusListener->addListener(callback);
+ *cameraInjectionSession = new CameraInjectionSession(this);
+
+ return ret;
+}
+
void CameraService::removeByClient(const BasicClient* client) {
Mutex::Autolock lock(mServiceLock);
for (auto& i : mActiveClientManager.getAll()) {
@@ -2724,6 +2766,11 @@
ATRACE_CALL();
LOG1("playSound(%d)", kind);
+ if (kind < 0 || kind >= NUM_SOUNDS) {
+ ALOGE("%s: Invalid sound id requested: %d", __FUNCTION__, kind);
+ return;
+ }
+
Mutex::Autolock lock(mSoundLock);
loadSoundLocked(kind);
sp<MediaPlayer> player = mSoundPlayer[kind];
@@ -3609,6 +3656,66 @@
}
// ----------------------------------------------------------------------------
+// InjectionStatusListener
+// ----------------------------------------------------------------------------
+
+void CameraService::InjectionStatusListener::addListener(
+ const sp<ICameraInjectionCallback>& callback) {
+ Mutex::Autolock lock(mListenerLock);
+ if (mCameraInjectionCallback) return;
+ status_t res = IInterface::asBinder(callback)->linkToDeath(this);
+ if (res == OK) {
+ mCameraInjectionCallback = callback;
+ }
+}
+
+void CameraService::InjectionStatusListener::removeListener() {
+ Mutex::Autolock lock(mListenerLock);
+ if (mCameraInjectionCallback == nullptr) {
+ ALOGW("InjectionStatusListener: mCameraInjectionCallback == nullptr");
+ return;
+ }
+ IInterface::asBinder(mCameraInjectionCallback)->unlinkToDeath(this);
+ mCameraInjectionCallback = nullptr;
+}
+
+void CameraService::InjectionStatusListener::notifyInjectionError(
+ int errorCode) {
+ Mutex::Autolock lock(mListenerLock);
+ if (mCameraInjectionCallback == nullptr) {
+ ALOGW("InjectionStatusListener: mCameraInjectionCallback == nullptr");
+ return;
+ }
+ mCameraInjectionCallback->onInjectionError(errorCode);
+}
+
+void CameraService::InjectionStatusListener::binderDied(
+ const wp<IBinder>& /*who*/) {
+ Mutex::Autolock lock(mListenerLock);
+ ALOGV("InjectionStatusListener: ICameraInjectionCallback has died");
+ auto parent = mParent.promote();
+ if (parent != nullptr) {
+ parent->stopInjectionImpl();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CameraInjectionSession
+// ----------------------------------------------------------------------------
+
+binder::Status CameraService::CameraInjectionSession::stopInjection() {
+ Mutex::Autolock lock(mInjectionSessionLock);
+ auto parent = mParent.promote();
+ if (parent == nullptr) {
+ ALOGE("CameraInjectionSession: Parent is gone");
+ return STATUS_ERROR(ICameraInjectionCallback::ERROR_INJECTION_SERVICE,
+ "Camera service encountered error");
+ }
+ parent->stopInjectionImpl();
+ return binder::Status::ok();
+}
+
+// ----------------------------------------------------------------------------
static const int kDumpLockRetries = 50;
static const int kDumpLockSleep = 60000;
@@ -4268,4 +4375,10 @@
return mode;
}
+void CameraService::stopInjectionImpl() {
+ mInjectionStatusListener->removeListener();
+
+ // TODO: Implement the stop injection function.
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index b436cec..10e1748 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -20,6 +20,8 @@
#include <android/hardware/BnCameraService.h>
#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/hardware/ICameraServiceListener.h>
+#include <android/hardware/camera2/BnCameraInjectionSession.h>
+#include <android/hardware/camera2/ICameraInjectionCallback.h>
#include <cutils/multiuser.h>
#include <utils/Vector.h>
@@ -180,6 +182,13 @@
/*out*/
bool *isSupported);
+ virtual binder::Status injectCamera(
+ const String16& packageName, const String16& internalCamId,
+ const String16& externalCamId,
+ const sp<hardware::camera2::ICameraInjectionCallback>& callback,
+ /*out*/
+ sp<hardware::camera2::ICameraInjectionSession>* cameraInjectionSession);
+
// Extra permissions checks
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
@@ -1147,6 +1156,46 @@
// Current camera mute mode
bool mOverrideCameraMuteMode = false;
+
+ /**
+ * A listener class that implements the IBinder::DeathRecipient interface
+ * for use to call back the error state injected by the external camera, and
+ * camera service can kill the injection when binder signals process death.
+ */
+ class InjectionStatusListener : public virtual IBinder::DeathRecipient {
+ public:
+ InjectionStatusListener(sp<CameraService> parent) : mParent(parent) {}
+
+ void addListener(const sp<hardware::camera2::ICameraInjectionCallback>& callback);
+ void removeListener();
+ void notifyInjectionError(int errorCode);
+
+ // IBinder::DeathRecipient implementation
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ Mutex mListenerLock;
+ wp<CameraService> mParent;
+ sp<hardware::camera2::ICameraInjectionCallback> mCameraInjectionCallback;
+ };
+
+ sp<InjectionStatusListener> mInjectionStatusListener;
+
+ /**
+ * A class that implements the hardware::camera2::BnCameraInjectionSession interface
+ */
+ class CameraInjectionSession : public hardware::camera2::BnCameraInjectionSession {
+ public:
+ CameraInjectionSession(sp<CameraService> parent) : mParent(parent) {}
+ virtual ~CameraInjectionSession() {}
+ binder::Status stopInjection() override;
+
+ private:
+ Mutex mInjectionSessionLock;
+ wp<CameraService> mParent;
+ };
+
+ void stopInjectionImpl();
};
} // namespace android
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index dbc68b2..11ec993 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -157,6 +157,7 @@
"log_session_id",
"sample_rate",
"content_type",
+ "sharing_requested",
};
/**
@@ -973,10 +974,11 @@
const auto perfModeActual =
types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeActualStr);
- std::string sharingModeStr;
+ std::string sharingModeActualStr;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
- key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeStr);
- const auto sharingMode = types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeStr);
+ key, AMEDIAMETRICS_PROP_SHARINGMODEACTUAL, &sharingModeActualStr);
+ const auto sharingModeActual =
+ types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeActualStr);
int32_t xrunCount = -1;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
@@ -987,7 +989,7 @@
std::string formatAppStr;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
- key, AMEDIAMETRICS_PROP_ENCODINGREQUESTED, &formatAppStr);
+ key, AMEDIAMETRICS_PROP_ENCODINGCLIENT, &formatAppStr);
const auto formatApp = types::lookup<types::ENCODING, int32_t>(formatAppStr);
std::string formatDeviceStr;
@@ -1008,6 +1010,12 @@
key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr);
const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);
+ std::string sharingModeRequestedStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeRequestedStr);
+ const auto sharingModeRequested =
+ types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeRequestedStr);
+
LOG(LOG_LEVEL) << "key:" << key
<< " path:" << path
<< " direction:" << direction << "(" << directionStr << ")"
@@ -1018,14 +1026,16 @@
<< " total_frames_transferred:" << totalFramesTransferred
<< " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
<< " perf_mode_actual:" << perfModeActual << "(" << perfModeActualStr << ")"
- << " sharing:" << sharingMode << "(" << sharingModeStr << ")"
+ << " sharing:" << sharingModeActual << "(" << sharingModeActualStr << ")"
<< " xrun_count:" << xrunCount
<< " device_type:" << serializedDeviceTypes
<< " format_app:" << formatApp << "(" << formatAppStr << ")"
<< " format_device: " << formatDevice << "(" << formatDeviceStr << ")"
<< " log_session_id: " << logSessionId
<< " sample_rate: " << sampleRate
- << " content_type: " << contentType << "(" << contentTypeStr << ")";
+ << " content_type: " << contentType << "(" << contentTypeStr << ")"
+ << " sharing_requested:" << sharingModeRequested
+ << "(" << sharingModeRequestedStr << ")";
if (mAudioAnalytics.mDeliverStatistics) {
android::util::BytesField bf_serialized(
@@ -1041,7 +1051,7 @@
, totalFramesTransferred
, perfModeRequested
, perfModeActual
- , sharingMode
+ , sharingModeActual
, xrunCount
, bf_serialized
, formatApp
@@ -1049,6 +1059,7 @@
, logSessionId.c_str()
, sampleRate
, contentType
+ , sharingModeRequested
);
std::stringstream ss;
ss << "result:" << result;
@@ -1063,7 +1074,7 @@
, totalFramesTransferred
, perfModeRequested
, perfModeActual
- , sharingMode
+ , sharingModeActual
, xrunCount
, serializedDeviceTypes.c_str()
, formatApp
@@ -1071,6 +1082,7 @@
, logSessionId.c_str()
, sampleRate
, contentType
+ , sharingModeRequested
);
ss << " " << fieldsStr;
std::string str = ss.str();
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index 381f441..2cfdf24 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -95,7 +95,7 @@
if ( item->getInt32("android.media.mediacodec.rotation-degrees", &rotation)) {
metrics_proto.set_rotation(rotation);
}
- // android.media.mediacodec.crypto int32 (although missing if not needed
+ // android.media.mediacodec.crypto int32 (although missing if not needed)
int32_t crypto = -1;
if ( item->getInt32("android.media.mediacodec.crypto", &crypto)) {
metrics_proto.set_crypto(crypto);
@@ -185,15 +185,120 @@
metrics_proto.set_lifetime_millis(lifetime_millis);
}
- // new for S; need to plumb through to westworld
- // android.media.mediacodec.channelCount int32
- // android.media.mediacodec.sampleRate int32
+ // android.media.mediacodec.channelCount
+ int32_t channelCount = -1;
+ if ( item->getInt32("android.media.mediacodec.channelCount", &channelCount)) {
+ metrics_proto.set_channel_count(channelCount);
+ }
- // new for S; need to plumb through to westworld
+ // android.media.mediacodec.sampleRate
+ int32_t sampleRate = -1;
+ if ( item->getInt32("android.media.mediacodec.sampleRate", &sampleRate)) {
+ metrics_proto.set_sample_rate(sampleRate);
+ }
+
// TODO PWG may want these fuzzed up a bit to obscure some precision
- // android.media.mediacodec.vencode.bytes int64
- // android.media.mediacodec.vencode.frames int64
- // android.media.mediacodec.vencode.durationUs int64
+ // android.media.mediacodec.vencode.bytes
+ int64_t bytes = -1;
+ if ( item->getInt64("android.media.mediacodec.vencode.bytes", &bytes)) {
+ metrics_proto.set_video_encode_bytes(bytes);
+ }
+
+ // android.media.mediacodec.vencode.frames
+ int64_t frames = -1;
+ if ( item->getInt64("android.media.mediacodec.vencode.frames", &frames)) {
+ metrics_proto.set_video_encode_frames(frames);
+ }
+
+ // android.media.mediacodec.vencode.durationUs
+ int64_t durationUs = -1;
+ if ( item->getInt64("android.media.mediacodec.vencode.durationUs", &durationUs)) {
+ metrics_proto.set_video_encode_duration_us(durationUs);
+ }
+
+ // android.media.mediacodec.color-format
+ int32_t colorFormat = -1;
+ if ( item->getInt32("android.media.mediacodec.color-format", &colorFormat)) {
+ metrics_proto.set_color_format(colorFormat);
+ }
+
+ // android.media.mediacodec.frame-rate
+ double frameRate = -1.0;
+ if ( item->getDouble("android.media.mediacodec.frame-rate", &frameRate)) {
+ metrics_proto.set_frame_rate(frameRate);
+ }
+
+ // android.media.mediacodec.capture-rate
+ double captureRate = -1.0;
+ if ( item->getDouble("android.media.mediacodec.capture-rate", &captureRate)) {
+ metrics_proto.set_capture_rate(captureRate);
+ }
+
+ // android.media.mediacodec.operating-rate
+ double operatingRate = -1.0;
+ if ( item->getDouble("android.media.mediacodec.operating-rate", &operatingRate)) {
+ metrics_proto.set_operating_rate(operatingRate);
+ }
+
+ // android.media.mediacodec.priority
+ int32_t priority = -1;
+ if ( item->getInt32("android.media.mediacodec.priority", &priority)) {
+ metrics_proto.set_priority(priority);
+ }
+
+ // android.media.mediacodec.video-qp-i-min
+ int32_t qpIMin = -1;
+ if ( item->getInt32("android.media.mediacodec.video-qp-i-min", &qpIMin)) {
+ metrics_proto.set_video_qp_i_min(qpIMin);
+ }
+
+ // android.media.mediacodec.video-qp-i-max
+ int32_t qpIMax = -1;
+ if ( item->getInt32("android.media.mediacodec.video-qp-i-max", &qpIMax)) {
+ metrics_proto.set_video_qp_i_max(qpIMax);
+ }
+
+ // android.media.mediacodec.video-qp-p-min
+ int32_t qpPMin = -1;
+ if ( item->getInt32("android.media.mediacodec.video-qp-p-min", &qpPMin)) {
+ metrics_proto.set_video_qp_p_min(qpPMin);
+ }
+
+ // android.media.mediacodec.video-qp-p-max
+ int32_t qpPMax = -1;
+ if ( item->getInt32("android.media.mediacodec.video-qp-p-max", &qpPMax)) {
+ metrics_proto.set_video_qp_p_max(qpPMax);
+ }
+
+ // android.media.mediacodec.video-qp-b-min
+ int32_t qpBMin = -1;
+ if ( item->getInt32("android.media.mediacodec.video-qp-b-min", &qpBMin)) {
+ metrics_proto.set_video_qp_b_min(qpIMin);
+ }
+
+ // android.media.mediacodec.video-qp-b-max
+ int32_t qpBMax = -1;
+ if ( item->getInt32("android.media.mediacodec.video-qp-b-max", &qpBMax)) {
+ metrics_proto.set_video_qp_b_max(qpBMax);
+ }
+
+ // android.media.mediacodec.video.input.bytes
+ int64_t inputBytes = -1;
+ if ( item->getInt64("android.media.mediacodec.video.input.bytes", &inputBytes)) {
+ metrics_proto.set_video_input_bytes(inputBytes);
+ }
+
+ // android.media.mediacodec.video.input.frames
+ int64_t inputFrames = -1;
+ if ( item->getInt64("android.media.mediacodec.video.input.frames", &inputFrames)) {
+ metrics_proto.set_video_input_frames(inputFrames);
+ }
+
+ // android.media.mediacodec.original.bitrate
+ int32_t originalBitrate = -1;
+ if ( item->getInt32("android.media.mediacodec.original.bitrate", &originalBitrate)) {
+ metrics_proto.set_original_bitrate(originalBitrate);
+ }
std::string serialized;
if (!metrics_proto.SerializeToString(&serialized)) {
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index 73b8872..287fb8d 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -59,9 +59,16 @@
std::string description;
(void) item->getString("description", &description);
+ std::string serialized_metrics;
+ (void) item->getString("serialized_metrics", &serialized_metrics);
+ if (serialized_metrics.empty()) {
+ ALOGD("statsd_mediadrm skipping empty entry");
+ return false;
+ }
+
// This field is left here for backward compatibility.
// This field is not used anymore.
- const std::string kUnusedField("unused");
+ const std::string kUnusedField("");
android::util::BytesField bf_serialized(kUnusedField.c_str(), kUnusedField.size());
int result = android::util::stats_write(android::util::MEDIAMETRICS_MEDIADRM_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index e228f07..281a4ce 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -86,6 +86,12 @@
metrics_proto.set_entry_point(entry_point);
}
+ // android.media.mediaextractor.logSessionId string
+ std::string log_session_id;
+ if (item->getString("android.media.mediaextractor.logSessionId", &log_session_id)) {
+ metrics_proto.set_log_session_id(log_session_id);
+ }
+
std::string serialized;
if (!metrics_proto.SerializeToString(&serialized)) {
ALOGE("Failed to serialize extractor metrics");
@@ -110,10 +116,7 @@
<< " mime:" << mime
<< " tracks:" << tracks
<< " entry_point:" << entry_point_string << "(" << entry_point << ")"
-
- // TODO: Add MediaExtractor log_session_id
- // << " log_session_id:" << log_session_id
-
+ << " log_session_id:" << log_session_id
<< " }";
statsdLog->log(android::util::MEDIAMETRICS_EXTRACTOR_REPORTED, log.str());
return true;
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
index f543425..6cceb06 100644
--- a/services/mediametrics/statsd_mediaparser.cpp
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -79,6 +79,9 @@
int32_t videoHeight = -1;
item->getInt32("android.media.mediaparser.videoHeight", &videoHeight);
+ std::string logSessionId;
+ item->getString("android.media.mediaparser.logSessionId", &logSessionId);
+
if (enabled_statsd) {
(void) android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
timestamp_nanos,
@@ -94,11 +97,11 @@
trackCodecs.c_str(),
alteredParameters.c_str(),
videoWidth,
- videoHeight);
+ videoHeight,
+ logSessionId.c_str());
} else {
ALOGV("NOT sending MediaParser media metrics.");
}
- // TODO: Cleanup after playback_id is merged.
std::stringstream log;
log << "result:" << "(result)" << " {"
<< " mediametrics_mediaparser_reported:"
@@ -117,8 +120,7 @@
<< " altered_parameters:" << alteredParameters
<< " video_width:" << videoWidth
<< " video_height:" << videoHeight
- // TODO: Add MediaParser playback_id
- // << " playback_id:" << playbackId
+ << " log_session_id:" << logSessionId
<< " }";
statsdLog->log(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED, log.str());
return true;
diff --git a/services/mediametrics/statsd_recorder.cpp b/services/mediametrics/statsd_recorder.cpp
index 23b884f..6edad7c 100644
--- a/services/mediametrics/statsd_recorder.cpp
+++ b/services/mediametrics/statsd_recorder.cpp
@@ -32,7 +32,7 @@
#include <statslog.h>
#include "MediaMetricsService.h"
-#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
#include "iface_statsd.h"
namespace android {
@@ -50,11 +50,16 @@
// the rest into our own proto
//
- ::android::stats::mediametrics::RecorderData metrics_proto;
+ ::android::stats::mediametrics_message::RecorderData metrics_proto;
// flesh out the protobuf we'll hand off with our data
//
+ // string kRecorderLogSessionId = "android.media.mediarecorder.log-session-id";
+ std::string log_session_id;
+ if (item->getString("android.media.mediarecorder.log_session_id", &log_session_id)) {
+ metrics_proto.set_log_session_id(std::move(log_session_id));
+ }
// string kRecorderAudioMime = "android.media.mediarecorder.audio.mime";
std::string audio_mime;
if (item->getString("android.media.mediarecorder.audio.mime", &audio_mime)) {
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index 8b64134..b80fe57 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -131,10 +131,10 @@
void MediaTranscodingService::instantiate() {
std::shared_ptr<MediaTranscodingService> service =
::ndk::SharedRefBase::make<MediaTranscodingService>();
- binder_status_t status =
- AServiceManager_addService(service->asBinder().get(), getServiceName());
- if (status != STATUS_OK) {
- return;
+ if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
+ // Once service is started, we want it to stay even is client side perished.
+ AServiceManager_forceLazyServicesPersist(true /*persist*/);
+ (void)AServiceManager_registerLazyService(service->asBinder().get(), getServiceName());
}
}
diff --git a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
index 20e4bfb..0cb2fad 100644
--- a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
+++ b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
@@ -481,7 +481,7 @@
// Need thread pool to receive callbacks, otherwise oneway callbacks are
// silently ignored.
ABinderProcess_startThreadPool();
- ::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.transcoding"));
mService = IMediaTranscodingService::fromBinder(binder);
if (mService == nullptr) {
ALOGE("Failed to connect to the media.trascoding service.");
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
index 74c8ebd..bd82315 100755
--- a/tools/mainline_hook_partial.sh
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
index e432000..cb5fc44 100755
--- a/tools/mainline_hook_project.sh
+++ b/tools/mainline_hook_project.sh
@@ -17,7 +17,7 @@
# tunables
DEV_BRANCH=master
-MAINLINE_BRANCH=mainline-prod
+MAINLINE_BRANCH=sc-mainline-prod
###
RED=$(tput setaf 1)