Merge "AudioPolicy: Add unit tests for the MSD use cases"
diff --git a/apex/Android.bp b/apex/Android.bp
index 05cc2c5..604b268 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -31,8 +31,25 @@
key: "com.android.media.key",
}
+apex {
+ name: "com.android.media.swcodec",
+ compile_multilib: "32",
+ manifest: "manifest_codec.json",
+ native_shared_libs: [
+ "libmedia_codecserviceregistrant",
+ ],
+ use_vendor: true,
+ key: "com.android.media.swcodec.key",
+}
+
apex_key {
name: "com.android.media.key",
public_key: "com.android.media.avbpubkey",
private_key: "com.android.media.pem",
}
+
+apex_key {
+ name: "com.android.media.swcodec.key",
+ public_key: "com.android.media.swcodec.avbpubkey",
+ private_key: "com.android.media.swcodec.pem",
+}
diff --git a/apex/com.android.media.swcodec.avbpubkey b/apex/com.android.media.swcodec.avbpubkey
new file mode 100644
index 0000000..0459723
--- /dev/null
+++ b/apex/com.android.media.swcodec.avbpubkey
Binary files differ
diff --git a/apex/com.android.media.swcodec.pem b/apex/com.android.media.swcodec.pem
new file mode 100644
index 0000000..e379cd3
--- /dev/null
+++ b/apex/com.android.media.swcodec.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEAvB6lOEEOR58KMcFlayEZjsXuPgcfHi/OPxcvfpiGLCpOcK3l
+OPChWUvDRcIHMB7BO+Csfxs0HgsHvvZfNyoNIm99WcjFbboiO7WrBBArIszPr14X
+cfY2NxzT9LBj+EqAnbdL+4OQW1/npLHNE0qtDcxL71ipbjSuKNb58E9qGL0KwvkS
+fwwueWj++bg/iz7dq0mz7iKpnxYscNm4RhJjqcG2Usmg4Ejhr8h5UmOUmTJbObC/
+vzClXQqeeuzS8NTtGVgQ/CI9gC2WN9upq2p/2T7P4U3o3CWvBytUoLKR0UyC83ey
+S8XJgOa42uWR3T/eJOI1ZS4H6Srg1o2XC8Yb8EprFI/NM6/+/5DX/FgDimsslAP6
+Qq4+pSte9v/FjWGqy7QBQaefFRGRuS63xHcSZhXC9J2CFdnxo8+65QT8r4yfQEei
+Ax/0Q94yB7VIL1pIJxHEonKjtd3iKdFEKQzADJ3edsmtHybERdJKCxcm9QIrDCsC
+4YVT9nX0OoC9RD5d5EVD7W5I6eEnRu6igrKIKgUVppeYFQNZD+o+eiNJa4yoggRl
+h8sT0/xLKjMRxAQ7fafi1j+LB2O7UgJmIDDAnidq8Aoz7h3pNi139rNWrjNfwhus
+nMcZvL9dTVv26JWeESHP/zAfAX7j1rfkDwR02ocRLquwEUs1+UHA27Wi1bMCAwEA
+AQKCAgAO3PT83tb7/arWh4s1zaWxTB4otHNW9Tv8bB6KiA6Bys3rxTGJMCnvXjcN
+eekLekKWMoguer3BaemwwtJ/D0l+YQSsZVqD8uLliNL8PTLLSxdVqb98d5GNBTAR
+8yXS5kAHNgZA1wI+1fL9ZjbnwUyu/Gc7f+vTE0J3Y5TX0c52KemBwiAd/Z5mZU9P
+96i9nbfx4p7ev8pbEWttdyZCEw3gybdYDyowzlFWjCZZxhhlij7+7eIYfwVxtncT
+C0cXVBtvly+wXBwz1mY5/5cGPiHfzkCqcndlfWy4ykmjcLhoqvzls51Ys0Xac2BD
+m0PNEVDB5UWGuv5RA9xD12gJvBtU3D7ggMw6C5RcXJT+jSYmSFtD2klWi+It8A/N
+Hv42soKskt6JqYAWE1cvJ3PEqH9ASEJNq2R0Z/PmuM000UJyzU9KId3SNwjXA1Xc
+Kn9hRga4uf9elHTjkTDt79/8+Xv7hjer9sF/S/np7g04rUjIWkuFkC/7NK2tQSh1
+mljV1sD9SF4DPfVK75LwJJaQUlI7TtGd5KJ7FzZwvb+w8ODrpW3hkt6FcI6KwE/a
+QT1T2Z9DknXJSYNdWGrj6vMHsYMiyz8IdAHSCrOB6eXCQxpitbn6W71Raw7f9UaZ
+VDK5AhTU493hkGj1no4cJwecXInMigg/c4ywk2Ibh6IV8O0nkQKCAQEA2+dQQ0IF
+vvVgmQ2WxHBD7M2mbOyf43YBY6Ka6oPBNGPVpZE8X8LoTavQLV+SgCkH8T6gY7XS
+5L4Ze0JFxfua0o1rm6+L2XrOx5F/A2Y40YcPclEik5h1woSwH/J1iHGiEhY8Nqeu
+9GCvjQojkgXx/Rn3Nz+lpvZ329O3H85RWWGF0l60RwLOkig0ZwUb619t8affmGIl
+sxdDv2nfy7OtJX8iGDua7Kf64dvVWQKKtACWkARrlkcWX3uoESxkpSDxue+z7ndH
+o7uHLfM8Tx+Rn+QvYWuRW5TPLbEDMbIYrX65ISt2r/T7v/04XdAC8YpCQRytlqPI
+fpDm15htyHBizQKCAQEA2v+5otRoY56JduISaVGlsJ/IbvKzDAIyWmM14EpRCR5E
+lu+MpTcRAiFQAbHGXr1tMlTFdVFD090WAzIKaKtADFVLXobIHeGspnRCq5OpVp9W
+RvLtVwLxflHAc2yN9/LNtnBqHUgt+S01LBPElybdGHQRTtqAKXhkp31sM21O34Go
+Pri/IxgupWxykMaW44Kig1Cr5DKvc8cwUsGuyDdJm8oBQeNPTMWqSnXtqoTWSaYg
+2kxiMTFokrkSXgufb8wng6OXt/QelywrhG3hAsldPO3GdKidDSxhWZSgpUXXFdAX
+y4GO0IcRJBF/WJtYTYtR+l84nQA2/1Ye4ujFlT0afwKCAQEAmXrXpSm2cvI2CnzW
+hqJIdkWOa6W3bn1VOOIrt5Rfy54GZnl4pumVU2igcpqq2HJKzdDFBvLHj8kyZbn6
+ktUp2NzFhzK9q/uvyNA+0vOMoojeeg4w0MzvG+WaO6Hw8FtHH9KPEiJ01LGKtSin
+bOpjXCC8T75HcsHBJBefTz6jvnt3eD2LG6jU3mPbNy/0rZG8XZaqU2PlJhsNuNI/
+VaBBL9OMy1cGqTgQvYS+YlKI1ls2uqurH4bcEaZvxhSy5iGZNQodDkoIITnofmSu
+6haBgBQ2EYuPN1kkRKKwNQY1fRneQk1gmCynbPdiWO+urkCuP12xtlr3u4aM51rG
+/Meb3QKCAQEA12SxZm9XhLOHLIBJ74A4YLGm50iZxXPbpn7xnHo7naZBe9p8EHtK
+pTeygxggrUnOPrSVyT92YMiQP/BVwIC+a+LwUDZsWMd/ke/DKxH+eY4Zw4pm2S+x
+6bXqfRwFvhr3LTr/g3FcljlalNGUh73Xs5dk9pN9fkxFY16+rw4Rh0709Uur4o6E
+QnuZar+H5Ji10kXj6nvXiR4ebybEC3QlV66k8fLqKe44AShf61jfkmxs34hFA3E/
+EyAn6ouv8rtvGdArBuh5teHho0yXBLCcnbKXgGHepfhCf2LpZeR9GZ0j6iqxFnPh
+7gGvqKyReyNOK9y/x9tQPG6tzit3OcNxbQKCAQEAuDheDOSkXPopXMvLAKOHBIdZ
+rbQ7oFTDHt59gbucM7U8/l2YtaxuKOQFBLnzQa/amIkkrtklYwOsz8E24d7Nm39w
+ykLHwX0XrmjAm6M4XKmDv66a+kSnSV6LEbKZdjvXP02DV+tGeZ5VsnNvJDquxMsD
+fvRTspB8j8CpU96szekxl/tCRhqbdw/4kVTSj5BF++OaRRcJrAyj1B2qf1ynAZE1
+gUvVPkEYa914zcrxg9XIXT4M7yqB7i8KJegOtOtcWjJ7uTiP+638AvygJLMJnSrV
++HjFZWG6P9btZmLHSEBRvwGOAilp0qejXo866l0fmnlGy7ehKz8u3PzvnlPYjQ==
+-----END RSA PRIVATE KEY-----
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
new file mode 100644
index 0000000..e2bceec
--- /dev/null
+++ b/apex/manifest_codec.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.media.swcodec",
+ "version": 1
+}
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 321eb08..4e9b27d 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -167,19 +167,23 @@
}
OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+ const String16& physicalId,
int surfaceSetID, bool isShared) {
mGbps.push_back(gbp);
mRotation = rotation;
mSurfaceSetID = surfaceSetID;
mIsDeferred = false;
mIsShared = isShared;
+ mPhysicalCameraId = physicalId;
}
OutputConfiguration::OutputConfiguration(
const std::vector<sp<IGraphicBufferProducer>>& gbps,
- int rotation, int surfaceSetID, int surfaceType, int width, int height, bool isShared)
+ int rotation, const String16& physicalCameraId, int surfaceSetID, int surfaceType,
+ int width, int height, bool isShared)
: mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType),
- mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared) { }
+ mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
+ mPhysicalCameraId(physicalCameraId) { }
status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 5b117fb..95c4f39 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -65,10 +65,12 @@
OutputConfiguration(const android::Parcel& parcel);
OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+ const String16& physicalCameraId,
int surfaceSetID = INVALID_SET_ID, bool isShared = false);
OutputConfiguration(const std::vector<sp<IGraphicBufferProducer>>& gbps,
- int rotation, int surfaceSetID = INVALID_SET_ID,
+ int rotation, const String16& physicalCameraId,
+ int surfaceSetID = INVALID_SET_ID,
int surfaceType = OutputConfiguration::SURFACE_TYPE_UNKNOWN, int width = 0,
int height = 0, bool isShared = false);
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index fd95296..540d84e 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -28,6 +28,8 @@
#include <camera/NdkCameraCaptureSession.h>
#include "impl/ACameraCaptureSession.h"
+#include "impl/ACameraCaptureSession.inc"
+
using namespace android;
EXPORT
@@ -82,7 +84,31 @@
return ACAMERA_ERROR_SESSION_CLOSED;
}
- return session->capture(cbs, numRequests, requests, captureSequenceId);
+ return session->capture(
+ cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_capture(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->capture(
+ lcbs, numRequests, requests, captureSequenceId);
}
EXPORT
@@ -107,6 +133,28 @@
}
EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->setRepeatingRequest(lcbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session) {
ATRACE_CALL();
if (session == nullptr) {
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index ef05e0b..98608da 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -129,6 +129,20 @@
}
EXPORT
+camera_status_t ACaptureSessionPhysicalOutput_create(
+ ACameraWindowType* window, const char* physicalId,
+ /*out*/ACaptureSessionOutput** out) {
+ ATRACE_CALL();
+ if (window == nullptr || physicalId == nullptr || out == nullptr) {
+ ALOGE("%s: Error: bad argument. window %p, physicalId %p, out %p",
+ __FUNCTION__, window, physicalId, out);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = new ACaptureSessionOutput(window, false, physicalId);
+ return ACAMERA_OK;
+}
+
+EXPORT
camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out,
ACameraWindowType* window) {
ATRACE_CALL();
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 34ec2da..9a39ed8 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -69,3 +69,20 @@
metadata->decStrong((void*) ACameraMetadata_free);
}
}
+
+EXPORT
+bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
+ /*out*/size_t* numPhysicalCameras, /*out*/const char*const** physicalCameraIds) {
+ ATRACE_CALL();
+ if (numPhysicalCameras == nullptr || physicalCameraIds == nullptr) {
+ ALOGE("%s: Invalid input: numPhysicalCameras %p, physicalCameraIds %p",
+ __FUNCTION__, numPhysicalCameras, physicalCameraIds);
+ return false;
+ }
+ if (staticMetadata == nullptr) {
+ ALOGE("%s: Invalid input: staticMetadata is null.", __FUNCTION__);
+ return false;
+ }
+
+ return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds);
+}
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index fb72bdb..d6f1412 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -107,47 +107,6 @@
return ret;
}
-camera_status_t
-ACameraCaptureSession::setRepeatingRequest(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- sp<acam::CameraDevice> dev = getDeviceSp();
- if (dev == nullptr) {
- ALOGE("Error: Device associated with session %p has been closed!", this);
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
-
- camera_status_t ret;
- dev->lockDeviceForSessionOps();
- {
- Mutex::Autolock _l(mSessionLock);
- ret = dev->setRepeatingRequestsLocked(
- this, cbs, numRequests, requests, captureSequenceId);
- }
- dev->unlockDevice();
- return ret;
-}
-
-camera_status_t ACameraCaptureSession::capture(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- sp<acam::CameraDevice> dev = getDeviceSp();
- if (dev == nullptr) {
- ALOGE("Error: Device associated with session %p has been closed!", this);
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
- camera_status_t ret;
- dev->lockDeviceForSessionOps();
- {
- Mutex::Autolock _l(mSessionLock);
- ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
- }
- dev->unlockDevice();
- return ret;
-}
-
camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
sp<acam::CameraDevice> dev = getDeviceSp();
if (dev == nullptr) {
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 133c2c8..08a9226 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -17,6 +17,7 @@
#define _ACAMERA_CAPTURE_SESSION_H
#include <set>
+#include <string>
#include <hardware/camera3.h>
#include <camera/NdkCameraDevice.h>
@@ -29,8 +30,9 @@
using namespace android;
struct ACaptureSessionOutput {
- explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false) :
- mWindow(window), mIsShared(isShared) {};
+ explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false,
+ const char* physicalCameraId = "") :
+ mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
bool operator == (const ACaptureSessionOutput& other) const {
return mWindow == other.mWindow;
@@ -49,6 +51,7 @@
std::set<ACameraWindowType *> mSharedWindows;
bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
+ std::string mPhysicalCameraId;
};
#endif
@@ -88,13 +91,15 @@
camera_status_t abortCaptures();
+ template<class T>
camera_status_t setRepeatingRequest(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t capture(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc
new file mode 100644
index 0000000..86bf8a5
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.inc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include "ACameraCaptureSession.h"
+
+#ifdef __ANDROID_VNDK__
+#include "ndk_vendor/impl/ACameraDeviceVendor.inc"
+#else
+#include "ACameraDevice.inc"
+#endif
+
+using namespace android;
+
+template <class T>
+camera_status_t
+ACameraCaptureSession::setRepeatingRequest(
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp<acam::CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->setRepeatingRequestsLocked(
+ this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
+template <class T>
+camera_status_t ACameraCaptureSession::capture(
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp<acam::CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 657d41f..d8a5765 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -20,13 +20,14 @@
#include <vector>
#include <inttypes.h>
#include <android/hardware/ICameraService.h>
-#include <camera2/SubmitInfo.h>
#include <gui/Surface.h>
#include "ACameraDevice.h"
#include "ACameraMetadata.h"
#include "ACaptureRequest.h"
#include "ACameraCaptureSession.h"
+#include "ACameraCaptureSession.inc"
+
namespace android {
namespace acam {
@@ -39,6 +40,7 @@
const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
const char* CameraDevice::kTimeStampKey = "TimeStamp";
const char* CameraDevice::kCaptureResultKey = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
const char* CameraDevice::kSequenceIdKey = "SequenceId";
const char* CameraDevice::kFrameNumberKey = "FrameNumber";
@@ -190,106 +192,6 @@
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::captureLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
-}
-
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
-}
-
-camera_status_t
-CameraDevice::submitRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId,
- bool isRepeating) {
- camera_status_t ret = checkCameraClosedOrErrorLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
- return ret;
- }
-
- // Form two vectors of capture request, one for internal tracking
- std::vector<hardware::camera2::CaptureRequest> requestList;
- Vector<sp<CaptureRequest> > requestsV;
- requestsV.setCapacity(numRequests);
- for (int i = 0; i < numRequests; i++) {
- sp<CaptureRequest> req;
- ret = allocateCaptureRequest(requests[i], req);
- if (ret != ACAMERA_OK) {
- ALOGE("Convert capture request to internal format failure! ret %d", ret);
- return ret;
- }
- if (req->mSurfaceList.empty()) {
- ALOGE("Capture request without output target cannot be submitted!");
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
- requestList.push_back(*(req.get()));
- requestsV.push_back(req);
- }
-
- if (isRepeating) {
- ret = stopRepeatingLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
- return ret;
- }
- }
-
- binder::Status remoteRet;
- hardware::camera2::utils::SubmitInfo info;
- remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
- int sequenceId = info.mRequestId;
- int64_t lastFrameNumber = info.mLastFrameNumber;
- if (sequenceId < 0) {
- ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
- return ACAMERA_ERROR_UNKNOWN;
- }
-
- CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
- mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
-
- if (isRepeating) {
- // stopRepeating above should have cleanup repeating sequence id
- if (mRepeatingSequenceId != REQUEST_ID_NONE) {
- setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
- return ACAMERA_ERROR_CAMERA_DEVICE;
- }
- mRepeatingSequenceId = sequenceId;
- } else {
- mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
- }
-
- if (mIdle) {
- sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
- msg->setPointer(kContextKey, session->mUserSessionCallback.context);
- msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
- postSessionMsgAndCleanup(msg);
- }
- mIdle = false;
- mBusySession = session;
-
- if (captureSequenceId) {
- *captureSequenceId = sequenceId;
- }
- return ACAMERA_OK;
-}
-
camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
@@ -325,8 +227,9 @@
return ret;
}
- OutputConfiguration outConfig(iGBP, output->mRotation, OutputConfiguration::INVALID_SET_ID,
- true);
+ String16 physicalId16(output->mPhysicalCameraId.c_str());
+ OutputConfiguration outConfig(iGBP, output->mRotation, physicalId16,
+ OutputConfiguration::INVALID_SET_ID, true);
for (auto& anw : output->mSharedWindows) {
ret = getIGBPfromAnw(anw, iGBP);
@@ -640,8 +543,9 @@
if (ret != ACAMERA_OK) {
return ret;
}
+ String16 physicalId16(outConfig.mPhysicalCameraId.c_str());
outputSet.insert(std::make_pair(
- anw, OutputConfiguration(iGBP, outConfig.mRotation,
+ anw, OutputConfiguration(iGBP, outConfig.mRotation, physicalId16,
OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
}
auto addSet = outputSet;
@@ -829,7 +733,7 @@
if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) {
int32_t streamId = resultExtras.errorStreamId;
ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
- cbh.mCallbacks.onCaptureBufferLost;
+ cbh.mOnCaptureBufferLost;
auto outputPairIt = mConfiguredOutputs.find(streamId);
if (outputPairIt == mConfiguredOutputs.end()) {
ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
@@ -846,7 +750,7 @@
getId(), anw, frameNumber);
sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
msg->setObject(kCaptureRequestKey, request);
@@ -858,7 +762,7 @@
}
} else { // Handle other capture failures
// Fire capture failure callback if there is one registered
- ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
failure->frameNumber = frameNumber;
// TODO: refine this when implementing flush
@@ -868,7 +772,7 @@
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT);
sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onError);
msg->setObject(kCaptureRequestKey, request);
@@ -890,6 +794,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -960,6 +865,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -977,6 +883,7 @@
switch (msg->what()) {
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureBufferLost:
found = msg->findObject(kCaptureRequestKey, &obj);
@@ -1048,6 +955,64 @@
freeACaptureRequest(request);
break;
}
+ case kWhatLogicalCaptureResult:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find logicalCamera capture result callback!",
+ __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+
+ found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ static_cast<ACameraPhysicalCaptureResultInfo*>(obj.get()));
+ std::vector<PhysicalCaptureResultInfo>& physicalResultInfo =
+ physicalResult->mPhysicalResultInfo;
+
+ std::vector<std::string> physicalCameraIds;
+ std::vector<sp<ACameraMetadata>> physicalMetadataCopy;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ String8 physicalId8(physicalResultInfo[i].mPhysicalCameraId);
+ physicalCameraIds.push_back(physicalId8.c_str());
+
+ CameraMetadata clone = physicalResultInfo[i].mPhysicalCameraMetadata;
+ clone.update(ANDROID_SYNC_FRAME_NUMBER,
+ &physicalResult->mFrameNumber, /*data_count*/1);
+ sp<ACameraMetadata> metadata =
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+ physicalMetadataCopy.push_back(metadata);
+ }
+
+ std::vector<const char*> physicalCameraIdPtrs;
+ std::vector<const ACameraMetadata*> physicalMetadataCopyPtrs;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+ physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onResult)(context, session.get(), request, result.get(),
+ physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+ physicalMetadataCopyPtrs.data());
+ freeACaptureRequest(request);
+ break;
+ }
case kWhatCaptureFail:
{
ACameraCaptureSession_captureCallback_failed onFail;
@@ -1158,12 +1123,34 @@
}
CameraDevice::CallbackHolder::CallbackHolder(
- sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
- bool isRepeating,
- ACameraCaptureSession_captureCallbacks* cbs) :
- mSession(session), mRequests(requests),
- mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(false) {
+ initCaptureCallbacks(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(true) {
+ initCaptureCallbacks(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ }
+}
void
CameraDevice::checkRepeatingSequenceCompleteLocked(
@@ -1180,9 +1167,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq aborted callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
msg->setInt32(kSequenceIdKey, sequenceId);
postSessionMsgAndCleanup(msg);
} else {
@@ -1230,9 +1217,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq complete callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
msg->setInt32(kSequenceIdKey, sequenceId);
msg->setInt64(kFrameNumberKey, lastFrameNumber);
@@ -1389,7 +1376,7 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+ ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1398,7 +1385,7 @@
}
sp<CaptureRequest> request = cbh.mRequests[burstId];
sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onStart);
msg->setObject(kCaptureRequestKey, request);
@@ -1413,7 +1400,6 @@
const CameraMetadata& metadata,
const CaptureResultExtras& resultExtras,
const std::vector<PhysicalCaptureResultInfo>& physicalResultInfos) {
- (void) physicalResultInfos;
binder::Status ret = binder::Status::ok();
sp<CameraDevice> dev = mDevice.promote();
@@ -1449,9 +1435,6 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
- cbh.mCallbacks.onCaptureProgressed :
- cbh.mCallbacks.onCaptureCompleted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1461,13 +1444,27 @@
sp<CaptureRequest> request = cbh.mRequests[burstId];
sp<ACameraMetadata> result(new ACameraMetadata(
metadataCopy.release(), ACameraMetadata::ACM_RESULT));
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ new ACameraPhysicalCaptureResultInfo(physicalResultInfos, frameNumber));
- sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ sp<AMessage> msg = new AMessage(
+ cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+ dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onResult);
msg->setObject(kCaptureRequestKey, request);
msg->setObject(kCaptureResultKey, result);
+ if (isPartialResult) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureProgressed);
+ } else if (cbh.mIsLogicalCameraCallback) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnLogicalCameraCaptureCompleted);
+ msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+ } else {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureCompleted);
+ }
dev->postSessionMsgAndCleanup(msg);
}
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 8f56d3f..d0f363b 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -21,6 +21,7 @@
#include <set>
#include <atomic>
#include <utility>
+#include <vector>
#include <utils/StrongPointer.h>
#include <utils/Mutex.h>
#include <utils/String8.h>
@@ -46,6 +47,16 @@
// Wrap ACameraCaptureFailure so it can be ref-counted
struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {};
+// Wrap PhysicalCaptureResultInfo so that it can be ref-counted
+struct ACameraPhysicalCaptureResultInfo: public RefBase {
+ ACameraPhysicalCaptureResultInfo(const std::vector<PhysicalCaptureResultInfo>& info,
+ int64_t frameNumber) :
+ mPhysicalResultInfo(info), mFrameNumber(frameNumber) {}
+
+ std::vector<PhysicalCaptureResultInfo> mPhysicalResultInfo;
+ int64_t mFrameNumber;
+};
+
class CameraDevice final : public RefBase {
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
@@ -109,19 +120,22 @@
camera_status_t waitUntilIdleLocked();
+ template<class T>
camera_status_t captureLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t submitRequestsLocked(
sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*out*/int* captureSequenceId,
bool isRepeating);
@@ -192,6 +206,7 @@
// Capture callbacks
kWhatCaptureStart, // onCaptureStarted
kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
kWhatCaptureFail, // onCaptureFailed
kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
kWhatCaptureSeqAbort, // onCaptureSequenceAborted
@@ -207,6 +222,7 @@
static const char* kCaptureRequestKey;
static const char* kTimeStampKey;
static const char* kCaptureResultKey;
+ static const char* kPhysicalCaptureResultKey;
static const char* kCaptureFailureKey;
static const char* kSequenceIdKey;
static const char* kFrameNumberKey;
@@ -245,19 +261,46 @@
const Vector<sp<CaptureRequest> >& requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacks* cbs);
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
- static ACameraCaptureSession_captureCallbacks fillCb(
- ACameraCaptureSession_captureCallbacks* cbs) {
+ template <class T>
+ void initCaptureCallbacks(T* cbs) {
+ mContext = nullptr;
+ mOnCaptureStarted = nullptr;
+ mOnCaptureProgressed = nullptr;
+ mOnCaptureCompleted = nullptr;
+ mOnLogicalCameraCaptureCompleted = nullptr;
+ mOnCaptureFailed = nullptr;
+ mOnCaptureSequenceCompleted = nullptr;
+ mOnCaptureSequenceAborted = nullptr;
+ mOnCaptureBufferLost = nullptr;
if (cbs != nullptr) {
- return *cbs;
+ mContext = cbs->context;
+ mOnCaptureStarted = cbs->onCaptureStarted;
+ mOnCaptureProgressed = cbs->onCaptureProgressed;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+ mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+ mOnCaptureBufferLost = cbs->onCaptureBufferLost;
}
- return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
}
-
sp<ACameraCaptureSession> mSession;
Vector<sp<CaptureRequest> > mRequests;
const bool mIsRepeating;
- ACameraCaptureSession_captureCallbacks mCallbacks;
+ const bool mIsLogicalCameraCallback;
+
+ void* mContext;
+ ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
+ ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
+ ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
+ ACameraCaptureSession_captureCallback_failed mOnCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted;
+ ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost;
};
// sequence id -> callbacks map
std::map<int, CallbackHolder> mSequenceCallbackMap;
diff --git a/camera/ndk/impl/ACameraDevice.inc b/camera/ndk/impl/ACameraDevice.inc
new file mode 100644
index 0000000..1fc5352
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.inc
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <vector>
+#include <inttypes.h>
+#include "ACameraDevice.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "ACameraCaptureSession.h"
+
+namespace android {
+namespace acam {
+
+template<class T>
+camera_status_t
+CameraDevice::captureLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+template<class T>
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+template<class T>
+camera_status_t CameraDevice::submitRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId,
+ bool isRepeating) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Form two vectors of capture request, one for internal tracking
+ std::vector<hardware::camera2::CaptureRequest> requestList;
+ Vector<sp<CaptureRequest> > requestsV;
+ requestsV.setCapacity(numRequests);
+ for (int i = 0; i < numRequests; i++) {
+ sp<CaptureRequest> req;
+ ret = allocateCaptureRequest(requests[i], req);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Convert capture request to internal format failure! ret %d", ret);
+ return ret;
+ }
+ if (req->mSurfaceList.empty()) {
+ ALOGE("Capture request without output target cannot be submitted!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ requestList.push_back(*(req.get()));
+ requestsV.push_back(req);
+ }
+
+ if (isRepeating) {
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ }
+
+ binder::Status remoteRet;
+ hardware::camera2::utils::SubmitInfo info;
+ remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
+ int sequenceId = info.mRequestId;
+ int64_t lastFrameNumber = info.mLastFrameNumber;
+ if (sequenceId < 0) {
+ ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+ mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+
+ if (isRepeating) {
+ // stopRepeating above should have cleanup repeating sequence id
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ mRepeatingSequenceId = sequenceId;
+ } else {
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+ }
+
+ if (mIdle) {
+ sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+ postSessionMsgAndCleanup(msg);
+ }
+ mIdle = false;
+ mBusySession = session;
+
+ if (captureSequenceId) {
+ *captureSequenceId = sequenceId;
+ }
+ return ACAMERA_OK;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 94b5713..c661233 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -50,6 +50,7 @@
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS:
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE:
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA:
return true;
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING:
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING:
@@ -79,11 +80,41 @@
uint8_t capability = entry.data.u8[i];
if (isNdkSupportedCapability(capability)) {
capabilities.push(capability);
+
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+ derivePhysicalCameraIds();
+ }
}
}
mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
}
+void
+ACameraMetadata::derivePhysicalCameraIds() {
+ ACameraMetadata_const_entry entry;
+ auto ret = getConstEntry(ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS, &entry);
+ if (ret != ACAMERA_OK) {
+ ALOGE("%s: Get ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS key failed. ret %d",
+ __FUNCTION__, ret);
+ return;
+ }
+
+ const uint8_t* ids = entry.data.u8;
+ size_t start = 0;
+ for (size_t i = 0; i < entry.count; ++i) {
+ if (ids[i] == '\0') {
+ if (start != i) {
+ mStaticPhysicalCameraIds.push_back((const char*)ids+start);
+ }
+ start = i+1;
+ }
+ }
+
+ if (mStaticPhysicalCameraIds.size() < 2) {
+ ALOGW("%s: Logical multi-camera device only has %zu physical cameras",
+ __FUNCTION__, mStaticPhysicalCameraIds.size());
+ }
+}
void
ACameraMetadata::filterDurations(uint32_t tag) {
@@ -309,6 +340,27 @@
return mData;
}
+bool
+ACameraMetadata::isLogicalMultiCamera(size_t* count, const char*const** physicalCameraIds) const {
+ if (mType != ACM_CHARACTERISTICS) {
+ ALOGE("%s must be called for a static metadata!", __FUNCTION__);
+ return false;
+ }
+ if (count == nullptr || physicalCameraIds == nullptr) {
+ ALOGE("%s: Invalid input count: %p, physicalCameraIds: %p", __FUNCTION__,
+ count, physicalCameraIds);
+ return false;
+ }
+
+ if (mStaticPhysicalCameraIds.size() >= 2) {
+ *count = mStaticPhysicalCameraIds.size();
+ *physicalCameraIds = mStaticPhysicalCameraIds.data();
+ return true;
+ }
+
+ return false;
+}
+
// TODO: some of key below should be hidden from user
// ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
index f21dbaf..7049c4b 100644
--- a/camera/ndk/impl/ACameraMetadata.h
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -17,6 +17,7 @@
#define _ACAMERA_METADATA_H
#include <unordered_set>
+#include <vector>
#include <sys/types.h>
#include <utils/Mutex.h>
@@ -65,6 +66,7 @@
/*out*/const uint32_t** tags) const;
const CameraMetadata& getInternalData() const;
+ bool isLogicalMultiCamera(size_t* count, const char* const** physicalCameraIds) const;
private:
@@ -74,6 +76,7 @@
void filterUnsupportedFeatures(); // Hide features not yet supported by NDK
void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats
void filterDurations(uint32_t tag); // translate hal format to NDK formats
+ void derivePhysicalCameraIds(); // Derive array of physical ids.
template<typename INTERNAL_T, typename NDK_T>
camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) {
@@ -112,6 +115,8 @@
const ACAMERA_METADATA_TYPE mType;
static std::unordered_set<uint32_t> sSystemTags;
+
+ std::vector<const char*> mStaticPhysicalCameraIds;
};
#endif // _ACAMERA_METADATA_H
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index 1244582..d13a818 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -643,6 +643,103 @@
ACaptureSessionOutput* output) __INTRODUCED_IN(28);
#endif /* __ANDROID_API__ >= 28 */
+#if __ANDROID_API__ >= 29
+/**
+ * The definition of final capture result callback with logical multi-camera support.
+ *
+ * This has the same functionality as final ACameraCaptureSession_captureCallback_result, with
+ * added ability to return physical camera result metadata within a logical multi-camera.
+ *
+ * For a logical multi-camera, this function will be called with the Id and result metadata
+ * of the underlying physical cameras, which the corresponding capture request contains targets for.
+ * If the capture request doesn't contain targets specific to any physical camera, or the current
+ * camera device isn't a logical multi-camera, physicalResultCount will be 0.
+ *
+ * @param context The optional application context provided by user in
+ * {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request of interest. Note that this pointer points to a copy of
+ * capture request sent by application, so the address is different to what
+ * application sent but the content will match. This request will be freed by
+ * framework immediately after this callback returns.
+ * @param result The capture result metadata reported by camera device. The memory is managed by
+ * camera framework. Do not access this pointer after this callback returns.
+ * @param physicalResultCount The number of physical camera result metadata
+ * @param physicalCameraIds The array of physical camera IDs on which the
+ * physical result metadata are reported.
+ * @param physicalResults The array of capture result metadata reported by the
+ * physical camera devices.
+ */
+typedef void (*ACameraCaptureSession_logicalCamera_captureCallback_result)(
+ void* context, ACameraCaptureSession* session,
+ ACaptureRequest* request, const ACameraMetadata* result,
+ size_t physicalResultCount, const char** physicalCameraIds,
+ const ACameraMetadata** physicalResults);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_captureCallbacks,
+ * with the exception that an onLogicalCameraCaptureCompleted callback is
+ * used, instead of onCaptureCompleted, to support logical multi-camera.
+ */
+typedef struct ACameraCaptureSession_logicalCamera_captureCallbacks {
+ /**
+ * Same as ACameraCaptureSession_captureCallbacks
+ */
+ void* context;
+ ACameraCaptureSession_captureCallback_start onCaptureStarted;
+ ACameraCaptureSession_captureCallback_result onCaptureProgressed;
+
+ /**
+ * This callback is called when an image capture has fully completed and all the
+ * result metadata is available. For a logical multi-camera, this callback
+ * also returns the result metadata for all physical cameras being
+ * explicitly requested on.
+ *
+ * <p>This callback will always fire after the last {@link onCaptureProgressed};
+ * in other words, no more partial results will be delivered once the completed result
+ * is available.</p>
+ *
+ * <p>For performance-intensive use-cases where latency is a factor, consider
+ * using {@link onCaptureProgressed} instead.</p>
+ *
+ * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+ * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+ */
+ ACameraCaptureSession_logicalCamera_captureCallback_result onLogicalCameraCaptureCompleted;
+
+ /**
+ * Same as ACameraCaptureSession_captureCallbacks
+ */
+ ACameraCaptureSession_captureCallback_failed onCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd onCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
+ ACameraCaptureSession_captureCallback_bufferLost onCaptureBufferLost;
+} ACameraCaptureSession_logicalCamera_captureCallbacks;
+
+/**
+ * This has the same functionality as ACameraCaptureSession_capture, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_capture(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_setRepeatingRequest, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAMERA_CAPTURE_SESSION_H */
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 4fe43d5..26af4f8 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -765,6 +765,36 @@
#endif /* __ANDROID_API__ >= 28 */
+#if __ANDROID_API__ >= 29
+
+/**
+ * Create a ACaptureSessionOutput object used for streaming from a physical
+ * camera as part of a logical camera device.
+ *
+ * <p>The ACaptureSessionOutput is used in {@link ACaptureSessionOutputContainer_add} method to add
+ * an output {@link ANativeWindow} to ACaptureSessionOutputContainer. Use
+ * {@link ACaptureSessionOutput_free} to free the object and its memory after application no longer
+ * needs the {@link ACaptureSessionOutput}.</p>
+ *
+ * @param anw the {@link ANativeWindow} to be associated with the {@link ACaptureSessionOutput}
+ * @param physicalId the Id of the physical camera this output is associated
+ * with.
+ * @param output the output {@link ACaptureSessionOutput} will be stored here if the
+ * method call succeeds.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds. The created container will be
+ * filled in the output argument.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if anw, physicalId or output is NULL.</li></ul>
+ *
+ * @see ACaptureSessionOutputContainer_add
+ */
+camera_status_t ACaptureSessionPhysicalOutput_create(
+ ACameraWindowType* anw, const char* physicalId,
+ /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAMERA_DEVICE_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h
index 611e270..9bbfb83 100644
--- a/camera/ndk/include/camera/NdkCameraMetadata.h
+++ b/camera/ndk/include/camera/NdkCameraMetadata.h
@@ -233,6 +233,28 @@
#endif /* __ANDROID_API__ >= 24 */
+#if __ANDROID_API__ >= 29
+
+/**
+ * Helper function to check if a camera is logical multi-camera.
+ *
+ * <p> Check whether a camera device is a logical multi-camera based on its
+ * static metadata. If it is, also returns its physical sub camera Ids.</p>
+ *
+ * @param staticMetadata the static metadata of the camera being checked.
+ * @param numPhysicalCameras returns the number of physical cameras.
+ * @param physicalCameraIds returns the array of physical camera Ids backing this logical
+ * camera device. Note that this pointer is only valid
+ * during the lifetime of the staticMetadata object.
+ *
+ * @return true if this is a logical multi-camera, false otherwise.
+ */
+bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
+ /*out*/size_t* numPhysicalCameras, /*out*/const char* const** physicalCameraIds)
+ __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAMERA_METADATA_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index cb474f4..4bb74cb 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -5552,6 +5552,25 @@
ACAMERA_DEPTH_END,
/**
+ * <p>String containing the ids of the underlying physical cameras.</p>
+ *
+ * <p>Type: byte[n]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>For a logical camera, this is concatenation of all underlying physical camera ids.
+ * The null terminator for physical camera id must be preserved so that the whole string
+ * can be tokenized using '\0' to generate list of physical camera ids.</p>
+ * <p>For example, if the physical camera ids of the logical camera are "2" and "3", the
+ * value of this tag will be ['2', '\0', '3', '\0'].</p>
+ * <p>The number of physical camera ids must be no less than 2.</p>
+ */
+ ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS = // byte[n]
+ ACAMERA_LOGICAL_MULTI_CAMERA_START,
+ /**
* <p>The accuracy of frame timestamp synchronization between physical cameras</p>
*
* <p>Type: byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)</p>
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index a29e96d..5a00022 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -2,9 +2,11 @@
global:
ACameraCaptureSession_abortCaptures;
ACameraCaptureSession_capture;
+ ACameraCaptureSession_logicalCamera_capture; # introduced=29
ACameraCaptureSession_close;
ACameraCaptureSession_getDevice;
ACameraCaptureSession_setRepeatingRequest;
+ ACameraCaptureSession_logicalCamera_setRepeatingRequest; # introduced=29
ACameraCaptureSession_stopRepeating;
ACameraCaptureSession_updateSharedOutput; # introduced=28
ACameraDevice_close;
@@ -24,6 +26,7 @@
ACameraMetadata_free;
ACameraMetadata_getAllTags;
ACameraMetadata_getConstEntry;
+ ACameraMetadata_isLogicalMultiCamera; # introduced=29
ACameraOutputTarget_create;
ACameraOutputTarget_free;
ACaptureRequest_addTarget;
@@ -48,6 +51,7 @@
ACaptureSessionSharedOutput_create; # introduced=28
ACaptureSessionSharedOutput_add; # introduced=28
ACaptureSessionSharedOutput_remove; # introduced=28
+ ACaptureSessionPhysicalOutput_create; # introduced=29
ACaptureSessionOutput_free;
local:
*;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
index 8d9e90c..e1af8c1 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
@@ -14,11 +14,13 @@
* limitations under the License.
*/
+#include <string>
#include "utils.h"
struct ACaptureSessionOutput {
- explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false) :
- mWindow(window), mIsShared(isShared) {};
+ explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false,
+ const char* physicalCameraId = "") :
+ mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
bool operator == (const ACaptureSessionOutput& other) const {
return (mWindow == other.mWindow);
@@ -40,6 +42,7 @@
std::set<android::acam::utils::native_handle_ptr_wrapper> mSharedWindows;
bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
+ std::string mPhysicalCameraId;
};
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 26e6b3c..f7863a5 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -29,6 +29,8 @@
#include "ACaptureRequest.h"
#include "utils.h"
+#include "ACameraCaptureSession.inc"
+
using namespace android;
namespace android {
@@ -47,6 +49,7 @@
const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
const char* CameraDevice::kTimeStampKey = "TimeStamp";
const char* CameraDevice::kCaptureResultKey = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
const char* CameraDevice::kSequenceIdKey = "SequenceId";
const char* CameraDevice::kFrameNumberKey = "FrameNumber";
@@ -206,28 +209,8 @@
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::captureLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
-}
-
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
-}
-
-void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
- sp<CaptureRequest> &req) {
+void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
+ sp<CaptureRequest> &req) {
CameraMetadata metadataCopy = aCaptureRequest->settings->getInternalData();
const camera_metadata_t *camera_metadata = metadataCopy.getAndLock();
HCameraMetadata hCameraMetadata;
@@ -237,101 +220,6 @@
req->mPhysicalCameraSettings[0].settings.metadata(std::move(hCameraMetadata));
}
-camera_status_t
-CameraDevice::submitRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId,
- bool isRepeating) {
- camera_status_t ret = checkCameraClosedOrErrorLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
- return ret;
- }
-
- // Form two vectors of capture request, one for internal tracking
- std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
- Vector<sp<CaptureRequest>> requestsV;
- requestsV.setCapacity(numRequests);
- for (int i = 0; i < numRequests; i++) {
- sp<CaptureRequest> req;
- ret = allocateCaptureRequest(requests[i], req);
- // We need to call this method since after submitRequestList is called,
- // the request metadata queue might have removed the capture request
- // metadata. Therefore we simply add the metadata to its wrapper class,
- // so that it can be retrived later.
- addRequestSettingsMetadata(requests[i], req);
- if (ret != ACAMERA_OK) {
- ALOGE("Convert capture request to internal format failure! ret %d", ret);
- return ret;
- }
- if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
- ALOGE("Capture request without output target cannot be submitted!");
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
- requestList.push_back(utils::convertToHidl(req.get()));
- requestsV.push_back(req);
- }
- if (isRepeating) {
- ret = stopRepeatingLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
- return ret;
- }
- }
-
- SubmitInfo info;
- Status status;
- auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
- [&status, &info](auto s, auto &submitInfo) {
- status = s;
- info = submitInfo;
- });
- if (!remoteRet.isOk()) {
- ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
- remoteRet.description().c_str());
- }
- if (status != Status::NO_ERROR) {
- return utils::convertFromHidl(status);
- }
- int32_t sequenceId = info.requestId;
- int64_t lastFrameNumber = info.lastFrameNumber;
- if (sequenceId < 0) {
- ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
- return ACAMERA_ERROR_UNKNOWN;
- }
-
- CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
- mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
-
- if (isRepeating) {
- // stopRepeating above should have cleanup repeating sequence id
- if (mRepeatingSequenceId != REQUEST_ID_NONE) {
- setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
- return ACAMERA_ERROR_CAMERA_DEVICE;
- }
- mRepeatingSequenceId = sequenceId;
- } else {
- mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
- }
-
- if (mIdle) {
- sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
- msg->setPointer(kContextKey, session->mUserSessionCallback.context);
- msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
- postSessionMsgAndCleanup(msg);
- }
- mIdle = false;
- mBusySession = session;
-
- if (captureSequenceId) {
- *captureSequenceId = sequenceId;
- }
- return ACAMERA_OK;
-}
-
camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
@@ -365,6 +253,7 @@
outConfig.windowGroupId = -1; // ndk doesn't support inter OutputConfiguration buffer sharing.
outConfig.windowHandles.resize(output->mSharedWindows.size() + 1);
outConfig.windowHandles[0] = output->mWindow;
+ outConfig.physicalCameraId = output->mPhysicalCameraId;
int i = 1;
for (auto& anw : output->mSharedWindows) {
outConfig.windowHandles[i++] = anw;
@@ -668,6 +557,7 @@
outConfigInsert.windowGroupId = -1;
outConfigInsert.windowHandles.resize(outConfig.mSharedWindows.size() + 1);
outConfigInsert.windowHandles[0] = anw;
+ outConfigInsert.physicalCameraId = outConfig.mPhysicalCameraId;
native_handle_ptr_wrapper wrap(anw);
outputSet.insert(std::make_pair(anw, outConfigInsertW));
}
@@ -894,7 +784,7 @@
if (errorCode == ErrorCode::CAMERA_BUFFER) {
int32_t streamId = resultExtras.errorStreamId;
ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
- cbh.mCallbacks.onCaptureBufferLost;
+ cbh.mOnCaptureBufferLost;
auto outputPairIt = mConfiguredOutputs.find(streamId);
if (outputPairIt == mConfiguredOutputs.end()) {
ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
@@ -913,7 +803,7 @@
getId(), anw, frameNumber);
sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
msg->setObject(kCaptureRequestKey, request);
@@ -925,7 +815,7 @@
}
} else { // Handle other capture failures
// Fire capture failure callback if there is one registered
- ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
failure->frameNumber = frameNumber;
// TODO: refine this when implementing flush
@@ -934,7 +824,7 @@
failure->wasImageCaptured = (errorCode == ErrorCode::CAMERA_RESULT);
sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onError);
msg->setObject(kCaptureRequestKey, request);
@@ -956,6 +846,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -1026,6 +917,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -1043,6 +935,7 @@
switch (msg->what()) {
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureBufferLost:
found = msg->findObject(kCaptureRequestKey, &obj);
@@ -1114,6 +1007,62 @@
freeACaptureRequest(request);
break;
}
+ case kWhatLogicalCaptureResult:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result callback!", __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+
+ found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ static_cast<ACameraPhysicalCaptureResultInfo*>(obj.get()));
+ std::vector<PhysicalCaptureResultInfoLocal>& physicalResultInfo =
+ physicalResult->mPhysicalResultInfo;
+
+ std::vector<std::string> physicalCameraIds;
+ std::vector<sp<ACameraMetadata>> physicalMetadataCopy;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIds.push_back(physicalResultInfo[i].physicalCameraId);
+
+ CameraMetadata clone = physicalResultInfo[i].physicalMetadata;
+ clone.update(ANDROID_SYNC_FRAME_NUMBER,
+ &physicalResult->mFrameNumber, /*data_count*/1);
+ sp<ACameraMetadata> metadata =
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+ physicalMetadataCopy.push_back(metadata);
+ }
+ std::vector<const char*> physicalCameraIdPtrs;
+ std::vector<const ACameraMetadata*> physicalMetadataCopyPtrs;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+ physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onResult)(context, session.get(), request, result.get(),
+ physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+ physicalMetadataCopyPtrs.data());
+ freeACaptureRequest(request);
+ break;
+ }
+
case kWhatCaptureFail:
{
ACameraCaptureSession_captureCallback_failed onFail;
@@ -1224,12 +1173,34 @@
}
CameraDevice::CallbackHolder::CallbackHolder(
- sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
- bool isRepeating,
- ACameraCaptureSession_captureCallbacks* cbs) :
- mSession(session), mRequests(requests),
- mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(false) {
+ initCaptureCallbacks(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(true) {
+ initCaptureCallbacks(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ }
+}
void
CameraDevice::checkRepeatingSequenceCompleteLocked(
@@ -1246,9 +1217,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq aborted callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
msg->setInt32(kSequenceIdKey, sequenceId);
postSessionMsgAndCleanup(msg);
} else {
@@ -1295,9 +1266,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq complete callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
msg->setInt32(kSequenceIdKey, sequenceId);
msg->setInt64(kFrameNumberKey, lastFrameNumber);
@@ -1454,7 +1425,7 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+ ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1463,7 +1434,7 @@
}
sp<CaptureRequest> request = cbh.mRequests[burstId];
sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onStart);
msg->setObject(kCaptureRequestKey, request);
@@ -1478,7 +1449,6 @@
const FmqSizeOrMetadata& resultMetadata,
const CaptureResultExtras& resultExtras,
const hidl_vec<PhysicalCaptureResultInfo>& physicalResultInfos) {
- (void) physicalResultInfos;
auto ret = Void();
sp<CameraDevice> dev = mDevice.promote();
@@ -1508,27 +1478,10 @@
}
CameraMetadata metadataCopy;
- HCameraMetadata hCameraMetadata;
- bool converted = false;
- if (resultMetadata.getDiscriminator() ==
- FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
- hCameraMetadata.resize(resultMetadata.fmqMetadataSize());
- bool read = dev->mCaptureResultMetadataQueue->read(hCameraMetadata.data(),
- resultMetadata.fmqMetadataSize());
- if (!read) {
- ALOGE("%s capture request settings could't be read from fmq",
- __FUNCTION__);
- return ret;
- }
- // TODO: Do we actually need to clone here ?
- converted = utils::convertFromHidlCloned(hCameraMetadata, &metadataCopy);
-
- } else {
- converted = utils::convertFromHidlCloned(resultMetadata.metadata(), &metadataCopy);
- }
-
- if (!converted) {
- ALOGE("%s result metadata couldn't be converted", __FUNCTION__);
+ camera_status_t status = readOneResultMetadata(resultMetadata,
+ dev->mCaptureResultMetadataQueue.get(), &metadataCopy);
+ if (status != ACAMERA_OK) {
+ ALOGE("%s: result metadata couldn't be converted", __FUNCTION__);
return ret;
}
@@ -1538,9 +1491,6 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
- cbh.mCallbacks.onCaptureProgressed :
- cbh.mCallbacks.onCaptureCompleted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1551,12 +1501,39 @@
sp<ACameraMetadata> result(new ACameraMetadata(
metadataCopy.release(), ACameraMetadata::ACM_RESULT));
- sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ std::vector<PhysicalCaptureResultInfoLocal> localPhysicalResult;
+ localPhysicalResult.resize(physicalResultInfos.size());
+ for (size_t i = 0; i < physicalResultInfos.size(); i++) {
+ localPhysicalResult[i].physicalCameraId = physicalResultInfos[i].physicalCameraId;
+ status = readOneResultMetadata(physicalResultInfos[i].physicalCameraMetadata,
+ dev->mCaptureResultMetadataQueue.get(),
+ &localPhysicalResult[i].physicalMetadata);
+ if (status != ACAMERA_OK) {
+ ALOGE("%s: physical camera result metadata couldn't be converted", __FUNCTION__);
+ return ret;
+ }
+ }
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ new ACameraPhysicalCaptureResultInfo(localPhysicalResult, frameNumber));
+
+ sp<AMessage> msg = new AMessage(
+ cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+ dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onResult);
msg->setObject(kCaptureRequestKey, request);
msg->setObject(kCaptureResultKey, result);
+ if (isPartialResult) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureProgressed);
+ } else if (cbh.mIsLogicalCameraCallback) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnLogicalCameraCaptureCompleted);
+ msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+ } else {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureCompleted);
+ }
dev->postSessionMsgAndCleanup(msg);
}
@@ -1590,5 +1567,31 @@
return ret;
}
+camera_status_t CameraDevice::ServiceCallback::readOneResultMetadata(
+ const FmqSizeOrMetadata& fmqSizeOrMetadata, ResultMetadataQueue* metadataQueue,
+ CameraMetadata* metadata) {
+ if (metadataQueue == nullptr || metadata == nullptr) {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ bool converted;
+ HCameraMetadata hCameraMetadata;
+ if (fmqSizeOrMetadata.getDiscriminator() ==
+ FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
+ hCameraMetadata.resize(fmqSizeOrMetadata.fmqMetadataSize());
+ bool read = metadataQueue->read(
+ hCameraMetadata.data(), fmqSizeOrMetadata.fmqMetadataSize());
+ if (!read) {
+ ALOGE("%s capture request settings could't be read from fmq", __FUNCTION__);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ // TODO: Do we actually need to clone here ?
+ converted = utils::convertFromHidlCloned(hCameraMetadata, metadata);
+ } else {
+ converted = utils::convertFromHidlCloned(fmqSizeOrMetadata.metadata(), metadata);
+ }
+
+ return converted ? ACAMERA_OK : ACAMERA_ERROR_UNKNOWN;
+}
+
} // namespace acam
} // namespace android
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index 01a219f..c63b97f 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -21,6 +21,7 @@
#include <set>
#include <atomic>
#include <utility>
+#include <vector>
#include <utils/StrongPointer.h>
#include <utils/Mutex.h>
#include <utils/List.h>
@@ -65,6 +66,21 @@
// Wrap ACameraCaptureFailure so it can be ref-counted
struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure { };
+// Wrap PhysicalCaptureResultInfo so that it can be ref-counted
+struct PhysicalCaptureResultInfoLocal {
+ std::string physicalCameraId;
+ CameraMetadata physicalMetadata;
+};
+
+struct ACameraPhysicalCaptureResultInfo: public RefBase {
+ ACameraPhysicalCaptureResultInfo(const std::vector<PhysicalCaptureResultInfoLocal>& info,
+ int64_t frameNumber) :
+ mPhysicalResultInfo(info), mFrameNumber(frameNumber) {}
+
+ std::vector<PhysicalCaptureResultInfoLocal> mPhysicalResultInfo;
+ int64_t mFrameNumber;
+};
+
class CameraDevice final : public RefBase {
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
@@ -99,6 +115,8 @@
android::hardware::Return<void> onRepeatingRequestError(uint64_t lastFrameNumber,
int32_t stoppedSequenceId) override;
private:
+ camera_status_t readOneResultMetadata(const FmqSizeOrMetadata& fmqSizeOrMetadata,
+ ResultMetadataQueue* metadataQueue, CameraMetadata* metadata);
const wp<CameraDevice> mDevice;
};
inline sp<ICameraDeviceCallback> getServiceCallback() {
@@ -127,24 +145,28 @@
camera_status_t waitUntilIdleLocked();
-
+ template<class T>
camera_status_t captureLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t submitRequestsLocked(
sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*out*/int* captureSequenceId,
bool isRepeating);
+ void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, sp<CaptureRequest> &req);
+
camera_status_t updateOutputConfigurationLocked(ACaptureSessionOutput *output);
camera_status_t allocateCaptureRequest(
@@ -206,6 +228,7 @@
// Capture callbacks
kWhatCaptureStart, // onCaptureStarted
kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
kWhatCaptureFail, // onCaptureFailed
kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
kWhatCaptureSeqAbort, // onCaptureSequenceAborted
@@ -221,6 +244,7 @@
static const char* kCaptureRequestKey;
static const char* kTimeStampKey;
static const char* kCaptureResultKey;
+ static const char* kPhysicalCaptureResultKey;
static const char* kCaptureFailureKey;
static const char* kSequenceIdKey;
static const char* kFrameNumberKey;
@@ -259,19 +283,47 @@
const Vector<sp<CaptureRequest>>& requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacks* cbs);
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest>>& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
- static ACameraCaptureSession_captureCallbacks fillCb(
- ACameraCaptureSession_captureCallbacks* cbs) {
+ template <class T>
+ void initCaptureCallbacks(T* cbs) {
+ mContext = nullptr;
+ mOnCaptureStarted = nullptr;
+ mOnCaptureProgressed = nullptr;
+ mOnCaptureCompleted = nullptr;
+ mOnLogicalCameraCaptureCompleted = nullptr;
+ mOnCaptureFailed = nullptr;
+ mOnCaptureSequenceCompleted = nullptr;
+ mOnCaptureSequenceAborted = nullptr;
+ mOnCaptureBufferLost = nullptr;
if (cbs != nullptr) {
- return *cbs;
+ mContext = cbs->context;
+ mOnCaptureStarted = cbs->onCaptureStarted;
+ mOnCaptureProgressed = cbs->onCaptureProgressed;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+ mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+ mOnCaptureBufferLost = cbs->onCaptureBufferLost;
}
- return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
}
sp<ACameraCaptureSession> mSession;
- Vector<sp<CaptureRequest>> mRequests;
+ Vector<sp<CaptureRequest>> mRequests;
const bool mIsRepeating;
- ACameraCaptureSession_captureCallbacks mCallbacks;
+ const bool mIsLogicalCameraCallback;
+
+ void* mContext;
+ ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
+ ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
+ ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
+ ACameraCaptureSession_captureCallback_failed mOnCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted;
+ ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost;
};
// sequence id -> callbacks map
std::map<int, CallbackHolder> mSequenceCallbackMap;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
new file mode 100644
index 0000000..7d2304e
--- /dev/null
+++ b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <vector>
+#include <inttypes.h>
+#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
+#include <android/frameworks/cameraservice/device/2.0/types.h>
+#include <CameraMetadata.h>
+
+#include "ndk_vendor/impl/ACameraDevice.h"
+#include "ACameraCaptureSession.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "utils.h"
+
+using namespace android;
+
+namespace android {
+namespace acam {
+
+template<class T>
+camera_status_t
+CameraDevice::captureLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+template<class T>
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+template<class T>
+camera_status_t CameraDevice::submitRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*out*/int* captureSequenceId,
+ bool isRepeating)
+{
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Form two vectors of capture request, one for internal tracking
+ std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
+ Vector<sp<CaptureRequest>> requestsV;
+ requestsV.setCapacity(numRequests);
+ for (int i = 0; i < numRequests; i++) {
+ sp<CaptureRequest> req;
+ ret = allocateCaptureRequest(requests[i], req);
+ // We need to call this method since after submitRequestList is called,
+ // the request metadata queue might have removed the capture request
+ // metadata. Therefore we simply add the metadata to its wrapper class,
+ // so that it can be retrieved later.
+ addRequestSettingsMetadata(requests[i], req);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Convert capture request to internal format failure! ret %d", ret);
+ return ret;
+ }
+ if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
+ ALOGE("Capture request without output target cannot be submitted!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ requestList.push_back(utils::convertToHidl(req.get()));
+ requestsV.push_back(req);
+ }
+ if (isRepeating) {
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ }
+
+ SubmitInfo info;
+ Status status;
+ auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
+ [&status, &info](auto s, auto &submitInfo) {
+ status = s;
+ info = submitInfo;
+ });
+ if (!remoteRet.isOk()) {
+ ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
+ remoteRet.description().c_str());
+ }
+ if (status != Status::NO_ERROR) {
+ return utils::convertFromHidl(status);
+ }
+ int32_t sequenceId = info.requestId;
+ int64_t lastFrameNumber = info.lastFrameNumber;
+ if (sequenceId < 0) {
+ ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+ mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+ if (isRepeating) {
+ // stopRepeating above should have cleanup repeating sequence id
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ mRepeatingSequenceId = sequenceId;
+ } else {
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+ }
+
+ if (mIdle) {
+ sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+ postSessionMsgAndCleanup(msg);
+ }
+ mIdle = false;
+ mBusySession = session;
+
+ if (captureSequenceId) {
+ *captureSequenceId = sequenceId;
+ }
+ return ACAMERA_OK;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 579412e..f9bb3ac 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -55,38 +55,27 @@
class CameraHelper {
public:
- CameraHelper(native_handle_t* imgReaderAnw) : mImgReaderAnw(imgReaderAnw) {}
+ CameraHelper(const char* id, ACameraManager *manager) :
+ mImgReaderAnw(nullptr), mCameraId(id), mCameraManager(manager) {}
~CameraHelper() { closeCamera(); }
- int initCamera() {
- if (mImgReaderAnw == nullptr) {
+ struct PhysicalImgReaderInfo {
+ const char* physicalCameraId;
+ native_handle_t* anw;
+ };
+ int initCamera(native_handle_t* imgReaderAnw,
+ const std::vector<PhysicalImgReaderInfo>& physicalImgReaders) {
+ if (imgReaderAnw == nullptr) {
ALOGE("Cannot initialize camera before image reader get initialized.");
return -1;
}
+ if (mIsCameraReady) {
+ ALOGE("initCamera should only be called once.");
+ return -1;
+ }
+
int ret;
-
- mCameraManager = ACameraManager_create();
- if (mCameraManager == nullptr) {
- ALOGE("Failed to create ACameraManager.");
- return -1;
- }
-
- ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
- if (ret != AMEDIA_OK) {
- ALOGE("Failed to get cameraIdList: ret=%d", ret);
- return ret;
- }
- if (mCameraIdList->numCameras < 1) {
- ALOGW("Device has no camera on board.");
- return 0;
- }
-
- // We always use the first camera.
- mCameraId = mCameraIdList->cameraIds[0];
- if (mCameraId == nullptr) {
- ALOGE("Failed to get cameraId.");
- return -1;
- }
+ mImgReaderAnw = imgReaderAnw;
ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
if (ret != AMEDIA_OK || mDevice == nullptr) {
@@ -94,18 +83,6 @@
return -1;
}
- ret = ACameraManager_getCameraCharacteristics(mCameraManager, mCameraId, &mCameraMetadata);
- if (ret != ACAMERA_OK || mCameraMetadata == nullptr) {
- ALOGE("Get camera %s characteristics failure. ret %d, metadata %p", mCameraId, ret,
- mCameraMetadata);
- return -1;
- }
-
- if (!isCapabilitySupported(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE)) {
- ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
- return 0;
- }
-
// Create capture session
ret = ACaptureSessionOutputContainer_create(&mOutputs);
if (ret != AMEDIA_OK) {
@@ -122,6 +99,25 @@
ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
return ret;
}
+
+ for (auto& physicalStream : physicalImgReaders) {
+ ACaptureSessionOutput* sessionOutput = nullptr;
+ ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
+ physicalStream.physicalCameraId, &sessionOutput);
+ if (ret != ACAMERA_OK) {
+ ALOGE("ACaptureSessionPhysicalOutput_create failed, ret=%d", ret);
+ return ret;
+ }
+ ret = ACaptureSessionOutputContainer_add(mOutputs, sessionOutput);
+ if (ret != AMEDIA_OK) {
+ ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
+ return ret;
+ }
+ mExtraOutputs.push_back(sessionOutput);
+ // Assume that at most one physical stream per physical camera.
+ mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
+ }
+
ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
if (ret != AMEDIA_OK) {
ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
@@ -145,21 +141,25 @@
return ret;
}
+ for (auto& physicalStream : physicalImgReaders) {
+ ACameraOutputTarget* outputTarget = nullptr;
+ ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
+ if (ret != AMEDIA_OK) {
+ ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
+ return ret;
+ }
+ ret = ACaptureRequest_addTarget(mStillRequest, outputTarget);
+ if (ret != AMEDIA_OK) {
+ ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
+ return ret;
+ }
+ mReqExtraOutputs.push_back(outputTarget);
+ }
+
mIsCameraReady = true;
return 0;
}
- bool isCapabilitySupported(acamera_metadata_enum_android_request_available_capabilities_t cap) {
- ACameraMetadata_const_entry entry;
- ACameraMetadata_getConstEntry(
- mCameraMetadata, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
- for (uint32_t i = 0; i < entry.count; i++) {
- if (entry.data.u8[i] == cap) {
- return true;
- }
- }
- return false;
- }
bool isCameraReady() { return mIsCameraReady; }
@@ -169,6 +169,10 @@
ACameraOutputTarget_free(mReqImgReaderOutput);
mReqImgReaderOutput = nullptr;
}
+ for (auto& outputTarget : mReqExtraOutputs) {
+ ACameraOutputTarget_free(outputTarget);
+ }
+ mReqExtraOutputs.clear();
if (mStillRequest) {
ACaptureRequest_free(mStillRequest);
mStillRequest = nullptr;
@@ -182,6 +186,10 @@
ACaptureSessionOutput_free(mImgReaderOutput);
mImgReaderOutput = nullptr;
}
+ for (auto& extraOutput : mExtraOutputs) {
+ ACaptureSessionOutput_free(extraOutput);
+ }
+ mExtraOutputs.clear();
if (mOutputs) {
ACaptureSessionOutputContainer_free(mOutputs);
mOutputs = nullptr;
@@ -191,19 +199,6 @@
ACameraDevice_close(mDevice);
mDevice = nullptr;
}
- if (mCameraMetadata) {
- ACameraMetadata_free(mCameraMetadata);
- mCameraMetadata = nullptr;
- }
- // Destroy camera manager
- if (mCameraIdList) {
- ACameraManager_deleteCameraIdList(mCameraIdList);
- mCameraIdList = nullptr;
- }
- if (mCameraManager) {
- ACameraManager_delete(mCameraManager);
- mCameraManager = nullptr;
- }
mIsCameraReady = false;
}
@@ -213,6 +208,12 @@
&seqId);
}
+ int takeLogicalCameraPicture() {
+ int seqId;
+ return ACameraCaptureSession_logicalCamera_capture(mSession, &mLogicalCaptureCallbacks,
+ 1, &mStillRequest, &seqId);
+ }
+
bool checkCallbacks(int pictureCount) {
std::lock_guard<std::mutex> lock(mMutex);
if (mCompletedCaptureCallbackCount != pictureCount) {
@@ -241,22 +242,22 @@
native_handle_t* mImgReaderAnw = nullptr; // not owned by us.
- // Camera manager
- ACameraManager* mCameraManager = nullptr;
- ACameraIdList* mCameraIdList = nullptr;
// Camera device
- ACameraMetadata* mCameraMetadata = nullptr;
ACameraDevice* mDevice = nullptr;
// Capture session
ACaptureSessionOutputContainer* mOutputs = nullptr;
ACaptureSessionOutput* mImgReaderOutput = nullptr;
+ std::vector<ACaptureSessionOutput*> mExtraOutputs;
+
ACameraCaptureSession* mSession = nullptr;
// Capture request
ACaptureRequest* mStillRequest = nullptr;
ACameraOutputTarget* mReqImgReaderOutput = nullptr;
+ std::vector<ACameraOutputTarget*> mReqExtraOutputs;
bool mIsCameraReady = false;
const char* mCameraId;
+ ACameraManager* mCameraManager;
int mCompletedCaptureCallbackCount = 0;
std::mutex mMutex;
ACameraCaptureSession_captureCallbacks mCaptureCallbacks = {
@@ -264,7 +265,6 @@
this, // context
nullptr, // onCaptureStarted
nullptr, // onCaptureProgressed
- // onCaptureCompleted, called serially, so no lock needed.
[](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
const ACameraMetadata *) {
CameraHelper *ch = static_cast<CameraHelper *>(ctx);
@@ -275,8 +275,44 @@
nullptr, // onCaptureSequenceCompleted
nullptr, // onCaptureSequenceAborted
nullptr, // onCaptureBufferLost
- };
+ };
+ std::vector<std::string> mPhysicalCameraIds;
+ ACameraCaptureSession_logicalCamera_captureCallbacks mLogicalCaptureCallbacks = {
+ // TODO: Add tests for other callbacks
+ this, // context
+ nullptr, // onCaptureStarted
+ nullptr, // onCaptureProgressed
+ [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
+ const ACameraMetadata *, size_t physicalResultCount,
+ const char** physicalCameraIds, const ACameraMetadata** physicalResults) {
+ CameraHelper *ch = static_cast<CameraHelper *>(ctx);
+ std::lock_guard<std::mutex> lock(ch->mMutex);
+ ASSERT_EQ(physicalResultCount, ch->mPhysicalCameraIds.size());
+ for (size_t i = 0; i < physicalResultCount; i++) {
+ ASSERT_TRUE(physicalCameraIds[i] != nullptr);
+ ASSERT_TRUE(physicalResults[i] != nullptr);
+ ASSERT_NE(std::find(ch->mPhysicalCameraIds.begin(),
+ ch->mPhysicalCameraIds.end(), physicalCameraIds[i]),
+ ch->mPhysicalCameraIds.end());
+
+ // Verify frameNumber and sensorTimestamp exist in physical
+ // result metadata
+ ACameraMetadata_const_entry entry;
+ ACameraMetadata_getConstEntry(
+ physicalResults[i], ACAMERA_SYNC_FRAME_NUMBER, &entry);
+ ASSERT_EQ(entry.count, 1);
+ ACameraMetadata_getConstEntry(
+ physicalResults[i], ACAMERA_SENSOR_TIMESTAMP, &entry);
+ ASSERT_EQ(entry.count, 1);
+ }
+ ch->mCompletedCaptureCallbackCount++;
+ },
+ nullptr, // onCaptureFailed
+ nullptr, // onCaptureSequenceCompleted
+ nullptr, // onCaptureSequenceAborted
+ nullptr, // onCaptureBufferLost
+ };
};
class ImageReaderTestCase {
@@ -476,84 +512,276 @@
AImageReader_BufferRemovedListener mReaderDetachedCb{this, onBufferRemoved};
};
-bool takePictures(uint64_t readerUsage, int readerMaxImages, bool readerAsync, int pictureCount) {
- int ret = 0;
- ImageReaderTestCase testCase(
- kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
- readerAsync);
- ret = testCase.initImageReader();
- if (ret < 0) {
- ALOGE("Unable to initialize ImageReader");
+
+class AImageReaderVendorTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ mCameraManager = ACameraManager_create();
+ if (mCameraManager == nullptr) {
+ ALOGE("Failed to create ACameraManager.");
+ return;
+ }
+
+ camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Failed to get cameraIdList: ret=%d", ret);
+ return;
+ }
+ if (mCameraIdList->numCameras < 1) {
+ ALOGW("Device has no camera on board.");
+ return;
+ }
+ }
+ void TearDown() override {
+ // Destroy camera manager
+ if (mCameraIdList) {
+ ACameraManager_deleteCameraIdList(mCameraIdList);
+ mCameraIdList = nullptr;
+ }
+ if (mCameraManager) {
+ ACameraManager_delete(mCameraManager);
+ mCameraManager = nullptr;
+ }
+ }
+
+ bool takePictures(const char* id, uint64_t readerUsage, int readerMaxImages,
+ bool readerAsync, int pictureCount) {
+ int ret = 0;
+
+ ImageReaderTestCase testCase(
+ kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
+ readerAsync);
+ ret = testCase.initImageReader();
+ if (ret < 0) {
+ ALOGE("Unable to initialize ImageReader");
+ return false;
+ }
+
+ CameraHelper cameraHelper(id, mCameraManager);
+ ret = cameraHelper.initCamera(testCase.getNativeWindow(), {});
+ if (ret < 0) {
+ ALOGE("Unable to initialize camera helper");
+ return false;
+ }
+
+ if (!cameraHelper.isCameraReady()) {
+ ALOGW("Camera is not ready after successful initialization. It's either due to camera "
+ "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
+ "camera on board.");
+ return true;
+ }
+
+ for (int i = 0; i < pictureCount; i++) {
+ ret = cameraHelper.takePicture();
+ if (ret < 0) {
+ ALOGE("Unable to take picture");
+ return false;
+ }
+ }
+
+ // Sleep until all capture finished
+ for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
+ usleep(kCaptureWaitUs);
+ if (testCase.getAcquiredImageCount() == pictureCount) {
+ ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
+ pictureCount);
+ break;
+ }
+ }
+ return testCase.getAcquiredImageCount() == pictureCount &&
+ cameraHelper.checkCallbacks(pictureCount);
+ }
+
+ bool testTakePicturesNative(const char* id) {
+ for (auto& readerUsage :
+ {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
+ for (auto& readerMaxImages : {1, 4, 8}) {
+ for (auto& readerAsync : {true, false}) {
+ for (auto& pictureCount : {1, 4, 8}) {
+ if (!takePictures(id, readerUsage, readerMaxImages,
+ readerAsync, pictureCount)) {
+ ALOGE("Test takePictures failed for test case usage=%" PRIu64
+ ", maxImages=%d, async=%d, pictureCount=%d",
+ readerUsage, readerMaxImages, readerAsync, pictureCount);
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ // Camera manager
+ ACameraManager* mCameraManager = nullptr;
+ ACameraIdList* mCameraIdList = nullptr;
+
+ bool isCapabilitySupported(ACameraMetadata* staticInfo,
+ acamera_metadata_enum_android_request_available_capabilities_t cap) {
+ ACameraMetadata_const_entry entry;
+ ACameraMetadata_getConstEntry(
+ staticInfo, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+ for (uint32_t i = 0; i < entry.count; i++) {
+ if (entry.data.u8[i] == cap) {
+ return true;
+ }
+ }
return false;
}
- CameraHelper cameraHelper(testCase.getNativeWindow());
- ret = cameraHelper.initCamera();
- if (ret < 0) {
- ALOGE("Unable to initialize camera helper");
+ bool isSizeSupportedForFormat(ACameraMetadata* staticInfo,
+ int32_t format, int32_t width, int32_t height) {
+ ACameraMetadata_const_entry entry;
+ ACameraMetadata_getConstEntry(staticInfo,
+ ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
+ for (uint32_t i = 0; i < entry.count; i += 4) {
+ if (entry.data.i32[i] == format &&
+ entry.data.i32[i+3] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ entry.data.i32[i+1] == width &&
+ entry.data.i32[i+2] == height) {
+ return true;
+ }
+ }
return false;
}
+ void findCandidateLogicalCamera(const char **cameraId,
+ ACameraMetadata** staticMetadata,
+ std::vector<const char*>* candidatePhysicalIds) {
+ // Find first available logical camera
+ for (int i = 0; i < mCameraIdList->numCameras; i++) {
+ camera_status_t ret;
+ ret = ACameraManager_getCameraCharacteristics(
+ mCameraManager, mCameraIdList->cameraIds[i], staticMetadata);
+ ASSERT_EQ(ret, ACAMERA_OK);
+ ASSERT_NE(*staticMetadata, nullptr);
+
+ if (!isCapabilitySupported(*staticMetadata,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)) {
+ ACameraMetadata_free(*staticMetadata);
+ *staticMetadata = nullptr;
+ continue;
+ }
+
+ // Check returned physical camera Ids are valid
+ size_t physicalCameraIdCnt = 0;
+ const char*const* physicalCameraIds = nullptr;
+ bool isLogicalCamera = ACameraMetadata_isLogicalMultiCamera(*staticMetadata,
+ &physicalCameraIdCnt, &physicalCameraIds);
+ ASSERT_TRUE(isLogicalCamera);
+ ASSERT_GE(physicalCameraIdCnt, 2);
+ ACameraMetadata* physicalCameraMetadata = nullptr;
+ candidatePhysicalIds->clear();
+ for (size_t j = 0; j < physicalCameraIdCnt && candidatePhysicalIds->size() < 2; j++) {
+ ASSERT_GT(strlen(physicalCameraIds[j]), 0);
+ ret = ACameraManager_getCameraCharacteristics(
+ mCameraManager, physicalCameraIds[j], &physicalCameraMetadata);
+ ASSERT_EQ(ret, ACAMERA_OK);
+ ASSERT_NE(physicalCameraMetadata, nullptr);
+
+ if (isSizeSupportedForFormat(physicalCameraMetadata, kTestImageFormat,
+ kTestImageWidth, kTestImageHeight)) {
+ candidatePhysicalIds->push_back(physicalCameraIds[j]);
+ }
+ ACameraMetadata_free(physicalCameraMetadata);
+ }
+ if (candidatePhysicalIds->size() == 2) {
+ *cameraId = mCameraIdList->cameraIds[i];
+ return;
+ } else {
+ ACameraMetadata_free(*staticMetadata);
+ *staticMetadata = nullptr;
+ }
+ }
+ *cameraId = nullptr;
+ return;
+ }
+};
+
+TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) {
+ // We always use the first camera.
+ const char* cameraId = mCameraIdList->cameraIds[0];
+ ASSERT_TRUE(cameraId != nullptr);
+
+ ACameraMetadata* staticMetadata = nullptr;
+ camera_status_t ret = ACameraManager_getCameraCharacteristics(
+ mCameraManager, cameraId, &staticMetadata);
+ ASSERT_EQ(ret, ACAMERA_OK);
+ ASSERT_NE(staticMetadata, nullptr);
+
+ bool isBC = isCapabilitySupported(staticMetadata,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
+
+ ACameraMetadata_free(staticMetadata);
+
+ if (!isBC) {
+ ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
+ return;
+ }
+
+ EXPECT_TRUE(testTakePicturesNative(cameraId));
+}
+
+TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
+ const char* cameraId = nullptr;
+ ACameraMetadata* staticMetadata = nullptr;
+ std::vector<const char*> physicalCameraIds;
+
+ findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds);
+ if (cameraId == nullptr) {
+ // Couldn't find logical camera to test
+ return;
+ }
+
+ // Test streaming the logical multi-camera
+ uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
+ int32_t readerMaxImages = 8;
+ bool readerAsync = false;
+ const int pictureCount = 6;
+ std::vector<ImageReaderTestCase*> testCases;
+ for (size_t i = 0; i < 3; i++) {
+ ImageReaderTestCase* testCase = new ImageReaderTestCase(
+ kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
+ readerAsync);
+ ASSERT_EQ(testCase->initImageReader(), 0);
+ testCases.push_back(testCase);
+ }
+
+ CameraHelper cameraHelper(cameraId, mCameraManager);
+ std::vector<CameraHelper::PhysicalImgReaderInfo> physicalImgReaderInfo;
+ physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
+ physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
+
+ int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo);
+ ASSERT_EQ(ret, 0);
+
if (!cameraHelper.isCameraReady()) {
ALOGW("Camera is not ready after successful initialization. It's either due to camera on "
"board lacks BACKWARDS_COMPATIBLE capability or the device does not have camera on "
"board.");
- return true;
+ return;
}
for (int i = 0; i < pictureCount; i++) {
- ret = cameraHelper.takePicture();
- if (ret < 0) {
- ALOGE("Unable to take picture");
- return false;
- }
+ ret = cameraHelper.takeLogicalCameraPicture();
+ ASSERT_EQ(ret, 0);
}
// Sleep until all capture finished
for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
usleep(kCaptureWaitUs);
- if (testCase.getAcquiredImageCount() == pictureCount) {
+ if (testCases[0]->getAcquiredImageCount() == pictureCount) {
ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
pictureCount);
break;
}
}
- return testCase.getAcquiredImageCount() == pictureCount &&
- cameraHelper.checkCallbacks(pictureCount);
-}
+ ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
+ ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
+ ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
+ ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
-class AImageReaderWindowHandleTest : public ::testing::Test {
- public:
- void SetUp() override {
- }
- void TearDown() override {
-
- }
-
-};
-
-bool testTakePicturesNative() {
- for (auto& readerUsage :
- {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
- for (auto& readerMaxImages : {1, 4, 8}) {
- for (auto& readerAsync : {true, false}) {
- for (auto& pictureCount : {1, 4, 8}) {
- if (!takePictures(readerUsage, readerMaxImages, readerAsync, pictureCount)) {
- ALOGE("Test takePictures failed for test case usage=%" PRIu64 ", maxImages=%d, "
- "async=%d, pictureCount=%d",
- readerUsage, readerMaxImages, readerAsync, pictureCount);
- return false;
- }
- }
- }
- }
- }
- return true;
-}
-
-
-TEST_F(AImageReaderWindowHandleTest, CreateWindowNativeHandle) {
- EXPECT_TRUE(testTakePicturesNative());
+ ACameraMetadata_free(staticMetadata);
}
} // namespace
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index fa8a7a3..8534b28 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -480,7 +480,8 @@
sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
- OutputConfiguration output(gbProducer, /*rotation*/0);
+ String16 noPhysicalId;
+ OutputConfiguration output(gbProducer, /*rotation*/0, noPhysicalId);
// Can we configure?
res = device->beginConfigure();
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 86e9040..34a9a40 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -224,11 +224,15 @@
player->setSource(rawSource);
rawSource.clear();
- player->start(true /* sourceAlreadyStarted */);
+ err = player->start(true /* sourceAlreadyStarted */);
- status_t finalStatus;
- while (!player->reachedEOS(&finalStatus)) {
- usleep(100000ll);
+ if (err == OK) {
+ status_t finalStatus;
+ while (!player->reachedEOS(&finalStatus)) {
+ usleep(100000ll);
+ }
+ } else {
+ fprintf(stderr, "unable to start playback err=%d (0x%08x)\n", err, err);
}
delete player;
@@ -651,7 +655,8 @@
MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9,
MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, MEDIA_MIMETYPE_VIDEO_HEVC,
- MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_AC4
+ MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_AC4,
+ MEDIA_MIMETYPE_VIDEO_AV1
};
const char *codecType = queryDecoders? "decoder" : "encoder";
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index 28a78aa..bb9d7ec 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -29,8 +29,7 @@
srcs: ["src/FwdLockEngine.cpp"],
shared_libs: [
- "libicui18n",
- "libicuuc",
+ "libandroidicu",
"libutils",
"liblog",
"libdl",
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 41d1833..01efb22 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -27,7 +27,6 @@
"libmediadrmmetrics_lite",
"libmediametrics",
"libmediautils",
- "libprotobuf-cpp-lite",
"libstagefright_foundation",
"libutils",
"android.hardware.drm@1.0",
@@ -60,13 +59,11 @@
shared_libs: [
"android.hardware.drm@1.0",
"android.hardware.drm@1.1",
- "libbase",
"libbinder",
"libhidlbase",
"liblog",
"libmediametrics",
"libprotobuf-cpp-lite",
- "libstagefright_foundation",
"libutils",
],
cflags: [
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 14ff493..66c509f 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -553,12 +553,14 @@
const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
- for (size_t i = 0; i < mFactories.size(); i++) {
+ for (size_t i = mFactories.size() - 1; i >= 0; i--) {
if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
- mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
- if (mPlugin != NULL) {
+ auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
+ if (plugin != NULL) {
+ mPlugin = plugin;
mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
+ break;
}
}
}
@@ -567,6 +569,9 @@
mInitCheck = ERROR_UNSUPPORTED;
} else {
if (!mPlugin->setListener(this).isOk()) {
+ mPlugin = NULL;
+ mPluginV1_1 = NULL;
+ mPluginV1_2 = NULL;
mInitCheck = DEAD_OBJECT;
} else {
mInitCheck = OK;
diff --git a/include/media/MediaExtractorPluginApi.h b/include/media/MediaExtractorPluginApi.h
index 854bf83..916472c 100644
--- a/include/media/MediaExtractorPluginApi.h
+++ b/include/media/MediaExtractorPluginApi.h
@@ -135,8 +135,16 @@
const char *extractor_name;
union {
- SnifferFunc v2;
- } sniff;
+ struct {
+ SnifferFunc sniff;
+ } v2;
+ struct {
+ SnifferFunc sniff;
+ // a NULL terminated list of container mime types and/or file extensions
+ // that this extractor supports
+ const char **supported_types;
+ } v3;
+ } u;
};
// the C++ based API which first shipped in P and is no longer supported
@@ -145,7 +153,10 @@
// the first C/NDK based API
const uint32_t EXTRACTORDEF_VERSION_NDK_V1 = 2;
-const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V1;
+// the second C/NDK based API
+const uint32_t EXTRACTORDEF_VERSION_NDK_V2 = 3;
+
+const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V2;
// each plugin library exports one function of this type
typedef ExtractorDef (*GetExtractorDef)();
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index f1e815b..dfb1a3f 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -16,3 +16,6 @@
stop audioserver
on property:vts.native_server.on=0
start audioserver
+
+on init
+ mkdir /dev/socket/audioserver 0775 audioserver audioserver
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index aeefbdb..87730ae 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -468,7 +468,8 @@
if (outargs.numOutBytes > 0) {
mInputSize = 0;
- int consumed = ((capacity / sizeof(int16_t)) - inargs.numInSamples);
+ int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
+ + outargs.numInSamples;
mInputTimeUs = work->input.ordinal.timestamp
+ (consumed * 1000000ll / channelCount / sampleRate);
buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp
new file mode 100644
index 0000000..0fabf5c
--- /dev/null
+++ b/media/codec2/components/aom/Android.bp
@@ -0,0 +1,14 @@
+cc_library_shared {
+ name: "libcodec2_soft_av1dec",
+ defaults: [
+ "libcodec2_soft-defaults",
+ "libcodec2_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["C2SoftAomDec.cpp"],
+ static_libs: ["libaom"],
+
+ include_dirs: [
+ "external/libaom/",
+ ],
+}
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
new file mode 100644
index 0000000..6be1807
--- /dev/null
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -0,0 +1,750 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "C2SoftAomDec"
+#include <log/log.h>
+
+#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+#include <SimpleC2Interface.h>
+
+#include "C2SoftAomDec.h"
+
+namespace android {
+
+constexpr char COMPONENT_NAME[] = "c2.android.av1.decoder";
+
+class C2SoftAomDec::IntfImpl : public SimpleInterface<void>::BaseParams {
+ public:
+ explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
+ : SimpleInterface<void>::BaseParams(
+ helper, COMPONENT_NAME, C2Component::KIND_DECODER,
+ C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
+ noPrivateBuffers(); // TODO: account for our buffers here
+ noInputReferences();
+ noOutputReferences();
+ noInputLatency();
+ noTimeStretch();
+
+ addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
+ .withConstValue(new C2ComponentAttributesSetting(
+ C2Component::ATTRIB_IS_TEMPORAL))
+ .build());
+
+ addParameter(
+ DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
+ .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
+ .withFields({
+ C2F(mSize, width).inRange(2, 2048, 2),
+ C2F(mSize, height).inRange(2, 2048, 2),
+ })
+ .withSetter(SizeSetter)
+ .build());
+
+ addParameter(
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(0u,
+ C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
+ .withFields({
+ C2F(mProfileLevel, profile).oneOf({
+ C2Config::PROFILE_AV1_0,
+ C2Config::PROFILE_AV1_1}),
+ C2F(mProfileLevel, level).oneOf({
+ C2Config::LEVEL_AV1_2,
+ C2Config::LEVEL_AV1_2_1,
+ C2Config::LEVEL_AV1_2_2,
+ C2Config::LEVEL_AV1_3,
+ C2Config::LEVEL_AV1_3_1,
+ C2Config::LEVEL_AV1_3_2,
+ })
+ })
+ .withSetter(ProfileLevelSetter, mSize)
+ .build());
+
+ addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
+ .withDefault(new C2StreamMaxPictureSizeTuning::output(
+ 0u, 320, 240))
+ .withFields({
+ C2F(mSize, width).inRange(2, 2048, 2),
+ C2F(mSize, height).inRange(2, 2048, 2),
+ })
+ .withSetter(MaxPictureSizeSetter, mSize)
+ .build());
+
+ addParameter(
+ DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
+ .withDefault(
+ new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+ .withFields({
+ C2F(mMaxInputSize, value).any(),
+ })
+ .calculatedAs(MaxInputSizeSetter, mMaxSize)
+ .build());
+
+ C2ChromaOffsetStruct locations[1] = {
+ C2ChromaOffsetStruct::ITU_YUV_420_0()};
+ std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
+ C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
+ C2Color::YUV_420);
+ memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
+
+ defaultColorInfo = C2StreamColorInfo::output::AllocShared(
+ {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
+ C2Color::YUV_420);
+ helper->addStructDescriptors<C2ChromaOffsetStruct>();
+
+ addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
+ .withConstValue(defaultColorInfo)
+ .build());
+
+ addParameter(
+ DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsTuning::output(
+ 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mDefaultColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mDefaultColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mDefaultColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mDefaultColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(DefaultColorAspectsSetter)
+ .build());
+
+ // TODO: support more formats?
+ addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
+ .withConstValue(new C2StreamPixelFormatInfo::output(
+ 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
+ .build());
+ }
+
+ static C2R SizeSetter(bool mayBlock,
+ const C2P<C2StreamPictureSizeInfo::output>& oldMe,
+ C2P<C2VideoSizeStreamInfo::output>& me) {
+ (void)mayBlock;
+ C2R res = C2R::Ok();
+ if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
+ res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
+ me.set().width = oldMe.v.width;
+ }
+ if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
+ res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
+ me.set().height = oldMe.v.height;
+ }
+ return res;
+ }
+
+ static C2R MaxPictureSizeSetter(
+ bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output>& me,
+ const C2P<C2StreamPictureSizeInfo::output>& size) {
+ (void)mayBlock;
+ // TODO: get max width/height from the size's field helpers vs.
+ // hardcoding
+ me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
+ me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
+ return C2R::Ok();
+ }
+
+ static C2R MaxInputSizeSetter(
+ bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input>& me,
+ const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
+ (void)mayBlock;
+ // assume compression ratio of 2
+ me.set().value = (((maxSize.v.width + 63) / 64) *
+ ((maxSize.v.height + 63) / 64) * 3072);
+ return C2R::Ok();
+ }
+ static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &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 ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
+ const C2P<C2StreamPictureSizeInfo::output> &size) {
+ (void)mayBlock;
+ (void)size;
+ (void)me; // TODO: validate
+ return C2R::Ok();
+ }
+ std::shared_ptr<C2StreamColorAspectsTuning::output> getDefaultColorAspects_l() {
+ return mDefaultColorAspects;
+ }
+
+ private:
+ std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
+ std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
+ std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
+ std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
+ std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
+ std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
+ std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
+};
+
+C2SoftAomDec::C2SoftAomDec(const char* name, c2_node_id_t id,
+ const std::shared_ptr<IntfImpl>& intfImpl)
+ : SimpleC2Component(
+ std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
+ mIntf(intfImpl),
+ mCodecCtx(nullptr){
+
+ GENERATE_FILE_NAMES();
+ CREATE_DUMP_FILE(mInFile);
+ CREATE_DUMP_FILE(mOutFile);
+
+ gettimeofday(&mTimeStart, nullptr);
+ gettimeofday(&mTimeEnd, nullptr);
+}
+
+C2SoftAomDec::~C2SoftAomDec() {
+ onRelease();
+}
+
+c2_status_t C2SoftAomDec::onInit() {
+ status_t err = initDecoder();
+ return err == OK ? C2_OK : C2_CORRUPTED;
+}
+
+c2_status_t C2SoftAomDec::onStop() {
+ mSignalledError = false;
+ mSignalledOutputEos = false;
+ return C2_OK;
+}
+
+void C2SoftAomDec::onReset() {
+ (void)onStop();
+ c2_status_t err = onFlush_sm();
+ if (err != C2_OK) {
+ ALOGW("Failed to flush decoder. Try to hard reset decoder.");
+ destroyDecoder();
+ (void)initDecoder();
+ }
+}
+
+void C2SoftAomDec::onRelease() {
+ destroyDecoder();
+}
+
+c2_status_t C2SoftAomDec::onFlush_sm() {
+ if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+ ALOGE("Failed to flush av1 decoder.");
+ return C2_CORRUPTED;
+ }
+
+ aom_codec_iter_t iter = nullptr;
+ while (aom_codec_get_frame(mCodecCtx, &iter)) {
+ }
+
+ mSignalledError = false;
+ mSignalledOutputEos = false;
+
+ return C2_OK;
+}
+
+static int GetCPUCoreCount() {
+ int cpuCoreCount = 1;
+#if defined(_SC_NPROCESSORS_ONLN)
+ cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ // _SC_NPROC_ONLN must be defined...
+ cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+ CHECK(cpuCoreCount >= 1);
+ ALOGV("Number of CPU cores: %d", cpuCoreCount);
+ return cpuCoreCount;
+}
+
+status_t C2SoftAomDec::initDecoder() {
+ mSignalledError = false;
+ mSignalledOutputEos = false;
+ if (!mCodecCtx) {
+ mCodecCtx = new aom_codec_ctx_t;
+ }
+
+ if (!mCodecCtx) {
+ ALOGE("mCodecCtx is null");
+ return NO_MEMORY;
+ }
+
+ aom_codec_dec_cfg_t cfg;
+ memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t));
+ cfg.threads = GetCPUCoreCount();
+ cfg.allow_lowbitdepth = 1;
+
+ aom_codec_flags_t flags;
+ memset(&flags, 0, sizeof(aom_codec_flags_t));
+
+ aom_codec_err_t err;
+ if ((err = aom_codec_dec_init(mCodecCtx, aom_codec_av1_dx(), &cfg, 0))) {
+ ALOGE("av1 decoder failed to initialize. (%d)", err);
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+status_t C2SoftAomDec::destroyDecoder() {
+ if (mCodecCtx) {
+ aom_codec_destroy(mCodecCtx);
+ delete mCodecCtx;
+ mCodecCtx = nullptr;
+ }
+ return OK;
+}
+
+void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
+ uint32_t flags = 0;
+ if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
+ ALOGV("signalling eos");
+ }
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.ordinal = work->input.ordinal;
+ work->workletsProcessed = 1u;
+}
+
+void C2SoftAomDec::finishWork(uint64_t index,
+ const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2GraphicBlock>& block) {
+ std::shared_ptr<C2Buffer> buffer =
+ createGraphicBuffer(block, C2Rect(mWidth, mHeight));
+ auto fillWork = [buffer, index](const std::unique_ptr<C2Work>& work) {
+ uint32_t flags = 0;
+ if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
+ (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
+ ALOGV("signalling eos");
+ }
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.buffers.push_back(buffer);
+ work->worklets.front()->output.ordinal = work->input.ordinal;
+ work->workletsProcessed = 1u;
+ };
+ if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
+ fillWork(work);
+ } else {
+ finish(index, fillWork);
+ }
+}
+
+void C2SoftAomDec::process(const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2BlockPool>& pool) {
+ work->result = C2_OK;
+ work->workletsProcessed = 0u;
+ work->worklets.front()->output.configUpdate.clear();
+ work->worklets.front()->output.flags = work->input.flags;
+ if (mSignalledError || mSignalledOutputEos) {
+ work->result = C2_BAD_VALUE;
+ return;
+ }
+
+ size_t inOffset = 0u;
+ size_t inSize = 0u;
+ C2ReadView rView = mDummyReadView;
+ if (!work->input.buffers.empty()) {
+ rView =
+ work->input.buffers[0]->data().linearBlocks().front().map().get();
+ inSize = rView.capacity();
+ if (inSize && rView.error()) {
+ ALOGE("read view map failed %d", rView.error());
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ }
+
+ bool codecConfig =
+ ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
+ bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
+
+ ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
+ inSize, (int)work->input.ordinal.timestamp.peeku(),
+ (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
+
+ if (codecConfig) {
+ fillEmptyWork(work);
+ return;
+ }
+
+ int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
+ if (inSize) {
+ uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
+ int32_t decodeTime = 0;
+ int32_t delay = 0;
+
+ DUMP_TO_FILE(mOutFile, bitstream, inSize);
+ GETTIME(&mTimeStart, nullptr);
+ TIME_DIFF(mTimeEnd, mTimeStart, delay);
+
+ aom_codec_err_t err =
+ aom_codec_decode(mCodecCtx, bitstream, inSize, &frameIndex);
+
+ GETTIME(&mTimeEnd, nullptr);
+ TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
+ ALOGV("decodeTime=%4d delay=%4d\n", decodeTime, delay);
+
+ if (err != AOM_CODEC_OK) {
+ ALOGE("av1 decoder failed to decode frame err: %d", err);
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ mSignalledError = true;
+ return;
+ }
+
+ } else {
+ if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+ ALOGE("Failed to flush av1 decoder.");
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ mSignalledError = true;
+ return;
+ }
+ }
+
+ (void)outputBuffer(pool, work);
+
+ if (eos) {
+ drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
+ mSignalledOutputEos = true;
+ } else if (!inSize) {
+ fillEmptyWork(work);
+ }
+}
+
+static void copyOutputBufferToYV12Frame(uint8_t *dst,
+ const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
+ size_t srcYStride, size_t srcUStride, size_t srcVStride,
+ uint32_t width, uint32_t height) {
+ size_t dstYStride = align(width, 16);
+ size_t dstUVStride = align(dstYStride / 2, 16);
+ uint8_t* dstStart = dst;
+
+
+ for (size_t i = 0; i < height; ++i) {
+ memcpy(dst, srcY, width);
+ srcY += srcYStride;
+ dst += dstYStride;
+ }
+
+ dst = dstStart + dstYStride * height;
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dst, srcV, width / 2);
+ srcV += srcVStride;
+ dst += dstUVStride;
+ }
+
+ dst = dstStart + (dstYStride * height) + (dstUVStride * height / 2);
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dst, srcU, width / 2);
+ srcU += srcUStride;
+ dst += dstUVStride;
+ }
+}
+
+static void convertYUV420Planar16ToY410(uint32_t *dst,
+ const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
+ size_t srcYStride, size_t srcUStride, size_t srcVStride,
+ size_t dstStride, size_t width, size_t height) {
+
+ // Converting two lines at a time, slightly faster
+ for (size_t y = 0; y < height; y += 2) {
+ uint32_t *dstTop = (uint32_t *) dst;
+ uint32_t *dstBot = (uint32_t *) (dst + dstStride);
+ uint16_t *ySrcTop = (uint16_t*) srcY;
+ uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
+ uint16_t *uSrc = (uint16_t*) srcU;
+ uint16_t *vSrc = (uint16_t*) srcV;
+
+ uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
+ size_t x = 0;
+ for (; x < width - 3; x += 4) {
+
+ u01 = *((uint32_t*)uSrc); uSrc += 2;
+ v01 = *((uint32_t*)vSrc); vSrc += 2;
+
+ y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
+ y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
+ y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
+ y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;
+
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
+
+ *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
+ *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
+
+ *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
+ *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
+ }
+
+ // There should be at most 2 more pixels to process. Note that we don't
+ // need to consider odd case as the buffer is always aligned to even.
+ if (x < width) {
+ u01 = *uSrc;
+ v01 = *vSrc;
+ y01 = *((uint32_t*)ySrcTop);
+ y45 = *((uint32_t*)ySrcBot);
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = ((y01 >> 16) << 10) | uv0;
+ *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = ((y45 >> 16) << 10) | uv0;
+ }
+
+ srcY += srcYStride * 2;
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dst += dstStride * 2;
+ }
+
+ return;
+}
+
+static void convertYUV420Planar16ToYUV420Planar(uint8_t *dst,
+ const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
+ size_t srcYStride, size_t srcUStride, size_t srcVStride,
+ size_t dstStride, size_t width, size_t height) {
+
+ uint8_t *dstY = (uint8_t *)dst;
+ size_t dstYSize = dstStride * height;
+ size_t dstUVStride = align(dstStride / 2, 16);
+ size_t dstUVSize = dstUVStride * height / 2;
+ uint8_t *dstV = dstY + dstYSize;
+ uint8_t *dstU = dstV + dstUVSize;
+
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ dstY[x] = (uint8_t)(srcY[x] >> 2);
+ }
+
+ srcY += srcYStride;
+ dstY += dstStride;
+ }
+
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstU[x] = (uint8_t)(srcU[x] >> 2);
+ dstV[x] = (uint8_t)(srcV[x] >> 2);
+ }
+
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dstU += dstUVStride;
+ dstV += dstUVStride;
+ }
+ return;
+}
+bool C2SoftAomDec::outputBuffer(
+ const std::shared_ptr<C2BlockPool> &pool,
+ const std::unique_ptr<C2Work> &work)
+{
+ if (!(work && pool)) return false;
+
+ aom_codec_iter_t iter = nullptr;
+ aom_image_t* img = aom_codec_get_frame(mCodecCtx, &iter);
+
+ if (!img) return false;
+
+ if (img->d_w != mWidth || img->d_h != mHeight) {
+ mWidth = img->d_w;
+ mHeight = img->d_h;
+
+ C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight);
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
+ if (err == C2_OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(size));
+ } else {
+ ALOGE("Config update size failed");
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ return false;
+ }
+ }
+
+ CHECK(img->fmt == AOM_IMG_FMT_I420 || img->fmt == AOM_IMG_FMT_I42016);
+
+ std::shared_ptr<C2GraphicBlock> block;
+ uint32_t format = HAL_PIXEL_FORMAT_YV12;
+ if (img->fmt == AOM_IMG_FMT_I42016) {
+ IntfImpl::Lock lock = mIntf->lock();
+ std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects = mIntf->getDefaultColorAspects_l();
+
+ if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
+ defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
+ defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
+ format = HAL_PIXEL_FORMAT_RGBA_1010102;
+ }
+ }
+ C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
+ c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight,
+ format, usage, &block);
+
+ if (err != C2_OK) {
+ ALOGE("fetchGraphicBlock for Output failed with status %d", err);
+ work->result = err;
+ return false;
+ }
+
+ C2GraphicView wView = block->map().get();
+
+ if (wView.error()) {
+ ALOGE("graphic view map failed %d", wView.error());
+ work->result = C2_CORRUPTED;
+ return false;
+ }
+
+ ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d",
+ block->width(), block->height(), mWidth, mHeight,
+ (int)*(int64_t*)img->user_priv);
+
+ uint8_t* dst = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_Y]);
+ size_t srcYStride = img->stride[AOM_PLANE_Y];
+ size_t srcUStride = img->stride[AOM_PLANE_U];
+ size_t srcVStride = img->stride[AOM_PLANE_V];
+
+ if (img->fmt == AOM_IMG_FMT_I42016) {
+ const uint16_t *srcY = (const uint16_t *)img->planes[AOM_PLANE_Y];
+ const uint16_t *srcU = (const uint16_t *)img->planes[AOM_PLANE_U];
+ const uint16_t *srcV = (const uint16_t *)img->planes[AOM_PLANE_V];
+
+ if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
+ convertYUV420Planar16ToY410((uint32_t *)dst, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2,
+ align(mWidth, 16),
+ mWidth, mHeight);
+ } else {
+ convertYUV420Planar16ToYUV420Planar(dst, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2,
+ align(mWidth, 16),
+ mWidth, mHeight);
+ }
+ } else {
+ const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
+ const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
+ const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
+ copyOutputBufferToYV12Frame(dst, srcY, srcU, srcV,
+ srcYStride, srcUStride, srcVStride, mWidth, mHeight);
+ }
+ finishWork(*(int64_t*)img->user_priv, work, std::move(block));
+ block = nullptr;
+ return true;
+}
+
+c2_status_t C2SoftAomDec::drainInternal(
+ uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool,
+ const std::unique_ptr<C2Work>& work) {
+ if (drainMode == NO_DRAIN) {
+ ALOGW("drain with NO_DRAIN: no-op");
+ return C2_OK;
+ }
+ if (drainMode == DRAIN_CHAIN) {
+ ALOGW("DRAIN_CHAIN not supported");
+ return C2_OMITTED;
+ }
+
+ if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+ ALOGE("Failed to flush av1 decoder.");
+ return C2_CORRUPTED;
+ }
+
+ while ((outputBuffer(pool, work))) {
+ }
+
+ if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
+ work->workletsProcessed == 0u) {
+ fillEmptyWork(work);
+ }
+
+ return C2_OK;
+}
+
+c2_status_t C2SoftAomDec::drain(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool>& pool) {
+ return drainInternal(drainMode, pool, nullptr);
+}
+
+class C2SoftAomFactory : public C2ComponentFactory {
+ public:
+ C2SoftAomFactory()
+ : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
+ GetCodec2PlatformComponentStore()->getParamReflector())) {}
+
+ virtual c2_status_t createComponent(
+ c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(
+ new C2SoftAomDec(COMPONENT_NAME, id,
+ std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
+ deleter);
+ return C2_OK;
+ }
+
+ virtual c2_status_t createInterface(
+ c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = std::shared_ptr<C2ComponentInterface>(
+ new SimpleInterface<C2SoftAomDec::IntfImpl>(
+ COMPONENT_NAME, id,
+ std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
+ deleter);
+ return C2_OK;
+ }
+
+ virtual ~C2SoftAomFactory() override = default;
+
+ private:
+ std::shared_ptr<C2ReflectorHelper> mHelper;
+};
+
+} // namespace android
+
+extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
+ ALOGV("in %s", __func__);
+ return new ::android::C2SoftAomFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
+ ALOGV("in %s", __func__);
+ delete factory;
+}
diff --git a/media/codec2/components/aom/C2SoftAomDec.h b/media/codec2/components/aom/C2SoftAomDec.h
new file mode 100644
index 0000000..4c82647
--- /dev/null
+++ b/media/codec2/components/aom/C2SoftAomDec.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_C2_SOFT_AV1_DEC_H_
+#define ANDROID_C2_SOFT_AV1_DEC_H_
+
+#include <SimpleC2Component.h>
+#include "aom/aom_decoder.h"
+#include "aom/aomdx.h"
+
+#define GETTIME(a, b) gettimeofday(a, b);
+#define TIME_DIFF(start, end, diff) \
+ diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
+ ((end).tv_usec - (start).tv_usec);
+
+namespace android {
+
+struct C2SoftAomDec : public SimpleC2Component {
+ class IntfImpl;
+
+ C2SoftAomDec(const char* name, c2_node_id_t id,
+ const std::shared_ptr<IntfImpl>& intfImpl);
+ virtual ~C2SoftAomDec();
+
+ // From SimpleC2Component
+ c2_status_t onInit() override;
+ c2_status_t onStop() override;
+ void onReset() override;
+ void onRelease() override;
+ c2_status_t onFlush_sm() override;
+ void process(const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2BlockPool>& pool) override;
+ c2_status_t drain(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool>& pool) override;
+
+ private:
+ std::shared_ptr<IntfImpl> mIntf;
+ aom_codec_ctx_t* mCodecCtx;
+
+ uint32_t mWidth;
+ uint32_t mHeight;
+ bool mSignalledOutputEos;
+ bool mSignalledError;
+
+ #ifdef FILE_DUMP_ENABLE
+ char mInFile[200];
+ char mOutFile[200];
+ #endif /* FILE_DUMP_ENABLE */
+
+ struct timeval mTimeStart; // Time at the start of decode()
+ struct timeval mTimeEnd; // Time at the end of decode()
+
+ status_t initDecoder();
+ status_t destroyDecoder();
+ void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2GraphicBlock>& block);
+ bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
+ const std::unique_ptr<C2Work>& work);
+
+ c2_status_t drainInternal(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool>& pool,
+ const std::unique_ptr<C2Work>& work);
+
+ C2_DO_NOT_COPY(C2SoftAomDec);
+};
+
+#ifdef FILE_DUMP_ENABLE
+
+#define INPUT_DUMP_PATH "/data/local/tmp/temp/av1"
+#define INPUT_DUMP_EXT "webm"
+#define OUTPUT_DUMP_PATH "/data/local/tmp/temp/av1"
+#define OUTPUT_DUMP_EXT "av1"
+#define GENERATE_FILE_NAMES() \
+ { \
+ GETTIME(&mTimeStart, NULL); \
+ strcpy(mInFile, ""); \
+ ALOGD("GENERATE_FILE_NAMES"); \
+ sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, mTimeStart.tv_sec, \
+ mTimeStart.tv_usec, INPUT_DUMP_EXT); \
+ strcpy(mOutFile, ""); \
+ sprintf(mOutFile, "%s_%ld.%ld.%s", OUTPUT_DUMP_PATH, \
+ mTimeStart.tv_sec, mTimeStart.tv_usec, OUTPUT_DUMP_EXT); \
+ }
+
+#define CREATE_DUMP_FILE(m_filename) \
+ { \
+ FILE* fp = fopen(m_filename, "wb"); \
+ if (fp != NULL) { \
+ ALOGD("Opened file %s", m_filename); \
+ fclose(fp); \
+ } else { \
+ ALOGD("Could not open file %s", m_filename); \
+ } \
+ }
+#define DUMP_TO_FILE(m_filename, m_buf, m_size) \
+ { \
+ FILE* fp = fopen(m_filename, "ab"); \
+ if (fp != NULL && m_buf != NULL) { \
+ int i; \
+ ALOGD("Dump to file!"); \
+ i = fwrite(m_buf, 1, m_size, fp); \
+ if (i != (int)m_size) { \
+ ALOGD("Error in fwrite, returned %d", i); \
+ perror("Error in write to file"); \
+ } \
+ fclose(fp); \
+ } else { \
+ ALOGD("Could not write to file %s", m_filename); \
+ if (fp != NULL) fclose(fp); \
+ } \
+ }
+#else /* FILE_DUMP_ENABLE */
+#define INPUT_DUMP_PATH
+#define INPUT_DUMP_EXT
+#define OUTPUT_DUMP_PATH
+#define OUTPUT_DUMP_EXT
+#define GENERATE_FILE_NAMES()
+#define CREATE_DUMP_FILE(m_filename)
+#define DUMP_TO_FILE(m_filename, m_buf, m_size)
+#endif /* FILE_DUMP_ENABLE */
+
+} // namespace android
+
+#endif // ANDROID_C2_SOFT_AV1_DEC_H_
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 50b4d20..b8baec8 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -132,6 +132,56 @@
}
}
+class SimpleC2Component::BlockingBlockPool : public C2BlockPool {
+public:
+ BlockingBlockPool(const std::shared_ptr<C2BlockPool>& base): mBase{base} {}
+
+ virtual local_id_t getLocalId() const override {
+ return mBase->getLocalId();
+ }
+
+ virtual C2Allocator::id_t getAllocatorId() const override {
+ return mBase->getAllocatorId();
+ }
+
+ virtual c2_status_t fetchLinearBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock>* block) {
+ c2_status_t status;
+ do {
+ status = mBase->fetchLinearBlock(capacity, usage, block);
+ } while (status == C2_TIMED_OUT);
+ return status;
+ }
+
+ virtual c2_status_t fetchCircularBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2CircularBlock>* block) {
+ c2_status_t status;
+ do {
+ status = mBase->fetchCircularBlock(capacity, usage, block);
+ } while (status == C2_TIMED_OUT);
+ return status;
+ }
+
+ virtual c2_status_t fetchGraphicBlock(
+ uint32_t width, uint32_t height, uint32_t format,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicBlock>* block) {
+ c2_status_t status;
+ do {
+ status = mBase->fetchGraphicBlock(width, height, format, usage,
+ block);
+ } while (status == C2_TIMED_OUT);
+ return status;
+ }
+
+private:
+ std::shared_ptr<C2BlockPool> mBase;
+};
+
////////////////////////////////////////////////////////////////////////////////
namespace {
@@ -446,12 +496,16 @@
}
}
- err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
+ std::shared_ptr<C2BlockPool> blockPool;
+ err = GetCodec2BlockPool(poolId, shared_from_this(), &blockPool);
ALOGD("Using output block pool with poolID %llu => got %llu - %d",
(unsigned long long)poolId,
(unsigned long long)(
- mOutputBlockPool ? mOutputBlockPool->getLocalId() : 111000111),
+ blockPool ? blockPool->getLocalId() : 111000111),
err);
+ if (err == C2_OK) {
+ mOutputBlockPool = std::make_shared<BlockingBlockPool>(blockPool);
+ }
return err;
}();
if (err != C2_OK) {
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index b3a98f4..43029a9 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -234,7 +234,8 @@
typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork;
Mutexed<PendingWork> mPendingWork;
- std::shared_ptr<C2BlockPool> mOutputBlockPool;
+ class BlockingBlockPool;
+ std::shared_ptr<BlockingBlockPool> mOutputBlockPool;
SimpleC2Component() = delete;
};
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index d485964..e5eb51d 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -23,5 +23,8 @@
srcs: ["C2SoftFlacEnc.cpp"],
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libaudioutils",
+ "libFLAC",
+ ],
}
diff --git a/media/codec2/components/flac/C2SoftFlacDec.cpp b/media/codec2/components/flac/C2SoftFlacDec.cpp
index f1e2f51..86b16e8 100644
--- a/media/codec2/components/flac/C2SoftFlacDec.cpp
+++ b/media/codec2/components/flac/C2SoftFlacDec.cpp
@@ -83,8 +83,21 @@
DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
.withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 32768))
.build());
+
+ addParameter(
+ DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+ .withDefault(new C2StreamPcmEncodingInfo::output(0u, C2Config::PCM_16))
+ .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+ C2Config::PCM_16,
+ // C2Config::PCM_8,
+ C2Config::PCM_FLOAT})
+ })
+ .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+ .build());
}
+ int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
+
private:
std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
@@ -94,6 +107,7 @@
std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
std::shared_ptr<C2BitrateTuning::input> mBitrate;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+ std::shared_ptr<C2StreamPcmEncodingInfo::output> mPcmEncodingInfo;
};
C2SoftFlacDec::C2SoftFlacDec(
@@ -263,11 +277,11 @@
return;
}
- size_t outSize;
- if (mHasStreamInfo)
- outSize = mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(short);
- else
- outSize = kMaxBlockSize * FLACDecoder::kMaxChannels * sizeof(short);
+ const bool outputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(short);
+ size_t outSize = mHasStreamInfo ?
+ mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+ : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
std::shared_ptr<C2LinearBlock> block;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
@@ -284,9 +298,8 @@
return;
}
- short *output = reinterpret_cast<short *>(wView.data());
status_t decoderErr = mFLACDecoder->decodeOneFrame(
- input, inSize, output, &outSize);
+ input, inSize, wView.data(), &outSize, outputFloat);
if (decoderErr != OK) {
ALOGE("process: FLACDecoder decodeOneFrame returns error %d", decoderErr);
mSignalledError = true;
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index e4192c7..4ea35c2 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "C2SoftFlacEnc"
#include <log/log.h>
+#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include <C2PlatformSupport.h>
@@ -72,11 +73,23 @@
DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
.withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 4608))
.build());
+
+ addParameter(
+ DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+ .withDefault(new C2StreamPcmEncodingInfo::input(0u, C2Config::PCM_16))
+ .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+ C2Config::PCM_16,
+ // C2Config::PCM_8,
+ C2Config::PCM_FLOAT})
+ })
+ .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+ .build());
}
uint32_t getSampleRate() const { return mSampleRate->value; }
uint32_t getChannelCount() const { return mChannelCount->value; }
uint32_t getBitrate() const { return mBitrate->value; }
+ int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
private:
std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
@@ -87,6 +100,7 @@
std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
std::shared_ptr<C2BitrateTuning::output> mBitrate;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+ std::shared_ptr<C2StreamPcmEncodingInfo::input> mPcmEncodingInfo;
};
constexpr char COMPONENT_NAME[] = "c2.android.flac.encoder";
@@ -224,12 +238,15 @@
mWroteHeader = true;
}
- uint32_t sampleRate = mIntf->getSampleRate();
- uint32_t channelCount = mIntf->getChannelCount();
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
+ const uint32_t sampleRate = mIntf->getSampleRate();
+ const uint32_t channelCount = mIntf->getChannelCount();
+ const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+ const unsigned frameSize = channelCount * sampleSize;
+ const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
size_t outCapacity = inSize;
- outCapacity += mBlockSize * channelCount * sizeof(int16_t);
+ outCapacity += mBlockSize * frameSize;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &mOutputBlock);
@@ -250,14 +267,19 @@
size_t inPos = 0;
while (inPos < inSize) {
const uint8_t *inPtr = rView.data() + inOffset;
- size_t processSize = MIN(kInBlockSize * channelCount * sizeof(int16_t), (inSize - inPos));
- const unsigned nbInputFrames = processSize / (channelCount * sizeof(int16_t));
- const unsigned nbInputSamples = processSize / sizeof(int16_t);
- const int16_t *pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
- ALOGV("about to encode %zu bytes", processSize);
+ const size_t processSize = MIN(kInBlockSize * frameSize, (inSize - inPos));
+ const unsigned nbInputFrames = processSize / frameSize;
+ const unsigned nbInputSamples = processSize / sampleSize;
- for (unsigned i = 0; i < nbInputSamples; i++) {
- mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ ALOGV("about to encode %zu bytes", processSize);
+ if (inputFloat) {
+ const float * const pcmFloat = reinterpret_cast<const float *>(inPtr + inPos);
+ memcpy_to_q8_23_from_float_with_clamp(mInputBufferPcm32, pcmFloat, nbInputSamples);
+ } else {
+ const int16_t * const pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
+ for (unsigned i = 0; i < nbInputSamples; i++) {
+ mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ }
}
FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
@@ -342,10 +364,12 @@
return UNKNOWN_ERROR;
}
+ const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const int bitsPerSample = inputFloat ? 24 : 16;
FLAC__bool ok = true;
ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mIntf->getChannelCount());
ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mIntf->getSampleRate());
- ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+ ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, bitsPerSample);
ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, mCompressionLevel);
ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
if (!ok) {
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 27aa064..cf1f6cf 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -392,6 +392,7 @@
_C2_PL_HEVC_BASE = 0x6000,
_C2_PL_VP9_BASE = 0x7000,
_C2_PL_DV_BASE = 0x8000,
+ _C2_PL_AV1_BASE = 0x9000,
C2_PROFILE_LEVEL_VENDOR_START = 0x70000000,
};
@@ -539,6 +540,11 @@
PROFILE_DV_HE_07 = _C2_PL_DV_BASE + 7, ///< Dolby Vision dvhe.07 profile
PROFILE_DV_HE_08 = _C2_PL_DV_BASE + 8, ///< Dolby Vision dvhe.08 profile
PROFILE_DV_AV_09 = _C2_PL_DV_BASE + 9, ///< Dolby Vision dvav.09 profile
+
+ // AV1 profiles
+ 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)
};
enum C2Config::level_t : uint32_t {
@@ -652,6 +658,31 @@
LEVEL_DV_HIGH_UHD_30, ///< Dolby Vision high tier uhd30
LEVEL_DV_HIGH_UHD_48, ///< Dolby Vision high tier uhd48
LEVEL_DV_HIGH_UHD_60, ///< Dolby Vision high tier uhd60
+
+ LEVEL_AV1_2 = _C2_PL_AV1_BASE , ///< AV1 Level 2
+ LEVEL_AV1_2_1, ///< AV1 Level 2.1
+ LEVEL_AV1_2_2, ///< AV1 Level 2.2
+ LEVEL_AV1_2_3, ///< AV1 Level 2.3
+ LEVEL_AV1_3, ///< AV1 Level 3
+ LEVEL_AV1_3_1, ///< AV1 Level 3.1
+ LEVEL_AV1_3_2, ///< AV1 Level 3.2
+ LEVEL_AV1_3_3, ///< AV1 Level 3.3
+ LEVEL_AV1_4, ///< AV1 Level 4
+ LEVEL_AV1_4_1, ///< AV1 Level 4.1
+ LEVEL_AV1_4_2, ///< AV1 Level 4.2
+ LEVEL_AV1_4_3, ///< AV1 Level 4.3
+ LEVEL_AV1_5, ///< AV1 Level 5
+ LEVEL_AV1_5_1, ///< AV1 Level 5.1
+ LEVEL_AV1_5_2, ///< AV1 Level 5.2
+ LEVEL_AV1_5_3, ///< AV1 Level 5.3
+ LEVEL_AV1_6, ///< AV1 Level 6
+ LEVEL_AV1_6_1, ///< AV1 Level 6.1
+ LEVEL_AV1_6_2, ///< AV1 Level 6.2
+ LEVEL_AV1_6_3, ///< AV1 Level 6.3
+ LEVEL_AV1_7, ///< AV1 Level 7
+ LEVEL_AV1_7_1, ///< AV1 Level 7.1
+ LEVEL_AV1_7_2, ///< AV1 Level 7.2
+ LEVEL_AV1_7_3, ///< AV1 Level 7.3
};
struct C2ProfileLevelStruct {
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index 40be3b3..efc5c89 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -988,7 +988,10 @@
/** specialization for easy enums */
template<typename E>
inline static NamedValuesType namedValuesFor(const C2EasyEnum<E> &) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
return namedValuesFor(*(E*)nullptr);
+#pragma GCC diagnostic pop
}
private:
@@ -1104,7 +1107,10 @@
template<typename B>
struct C2FieldDescriptor::_NamedValuesGetter<B, true> {
inline static C2FieldDescriptor::NamedValuesType getNamedValues() {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
return C2FieldDescriptor::namedValuesFor(*(B*)nullptr);
+#pragma GCC diagnostic pop
}
};
@@ -1599,11 +1605,13 @@
/// \internal
/// \todo: create separate values vs. flags initializer as for flags we want
/// to list both allowed and required flags
- template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
+ template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)nullptr))>
C2FieldSupportedValues(bool flags, const T*)
: type(flags ? FLAGS : VALUES),
range{(T)0, (T)0, (T)0, (T)0, (T)0} {
- C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)0);
+ C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)nullptr);
if (flags) {
values.emplace_back(0); // min-mask defaults to 0
}
@@ -1612,6 +1620,7 @@
}
}
};
+#pragma GCC diagnostic pop
/**
* Supported values for a specific field.
diff --git a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
index 1e87f38..d4b973f 100644
--- a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
@@ -330,57 +330,72 @@
}
}
+// number of elementary streams per component
+#define STREAM_COUNT 2
+
// LookUpTable of clips and metadata for component testing
void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL,
- char* info) {
+ char* info, size_t streamIndex = 0) {
struct CompToURL {
Codec2AudioDecHidlTest::standardComp comp;
- const char* mURL;
- const char* info;
+ const char mURL[STREAM_COUNT][512];
+ const char info[STREAM_COUNT][512];
};
+ ASSERT_TRUE(streamIndex < STREAM_COUNT);
+
static const CompToURL kCompToURL[] = {
{Codec2AudioDecHidlTest::standardComp::xaac,
- "bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz.info"},
+ {"bbb_aac_stereo_128kbps_48000hz.aac",
+ "bbb_aac_stereo_128kbps_48000hz.aac"},
+ {"bbb_aac_stereo_128kbps_48000hz.info",
+ "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::mp3,
- "bbb_mp3_stereo_192kbps_48000hz.mp3",
- "bbb_mp3_stereo_192kbps_48000hz.info"},
+ {"bbb_mp3_stereo_192kbps_48000hz.mp3",
+ "bbb_mp3_stereo_192kbps_48000hz.mp3"},
+ {"bbb_mp3_stereo_192kbps_48000hz.info",
+ "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::aac,
- "bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz.info"},
+ {"bbb_aac_stereo_128kbps_48000hz.aac",
+ "bbb_aac_stereo_128kbps_48000hz.aac"},
+ {"bbb_aac_stereo_128kbps_48000hz.info",
+ "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::amrnb,
- "sine_amrnb_1ch_12kbps_8000hz.amrnb",
- "sine_amrnb_1ch_12kbps_8000hz.info"},
+ {"sine_amrnb_1ch_12kbps_8000hz.amrnb",
+ "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
+ {"sine_amrnb_1ch_12kbps_8000hz.info",
+ "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::amrwb,
- "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
- "bbb_amrwb_1ch_14kbps_16000hz.info"},
+ {"bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+ "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
+ {"bbb_amrwb_1ch_14kbps_16000hz.info",
+ "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::vorbis,
- "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
- "bbb_vorbis_stereo_128kbps_48000hz.info"},
+ {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
+ {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::opus,
- "bbb_opus_stereo_128kbps_48000hz.opus",
- "bbb_opus_stereo_128kbps_48000hz.info"},
+ {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
+ {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::g711alaw,
- "bbb_g711alaw_1ch_8khz.raw",
- "bbb_g711alaw_1ch_8khz.info"},
+ {"bbb_g711alaw_1ch_8khz.raw", ""},
+ {"bbb_g711alaw_1ch_8khz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::g711mlaw,
- "bbb_g711mulaw_1ch_8khz.raw",
- "bbb_g711mulaw_1ch_8khz.info"},
+ {"bbb_g711mulaw_1ch_8khz.raw", ""},
+ {"bbb_g711mulaw_1ch_8khz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::gsm,
- "bbb_gsm_1ch_8khz_13kbps.raw",
- "bbb_gsm_1ch_8khz_13kbps.info"},
+ {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
+ {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
{Codec2AudioDecHidlTest::standardComp::raw,
- "bbb_raw_1ch_8khz_s32le.raw",
- "bbb_raw_1ch_8khz_s32le.info"},
+ {"bbb_raw_1ch_8khz_s32le.raw", ""},
+ {"bbb_raw_1ch_8khz_s32le.info", ""}},
{Codec2AudioDecHidlTest::standardComp::flac,
- "bbb_flac_stereo_680kbps_48000hz.flac",
- "bbb_flac_stereo_680kbps_48000hz.info"},
+ {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
+ {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
};
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
if (kCompToURL[i].comp == comp) {
- strcat(mURL, kCompToURL[i].mURL);
- strcat(info, kCompToURL[i].info);
+ strcat(mURL, kCompToURL[i].mURL[streamIndex]);
+ strcat(info, kCompToURL[i].info[streamIndex]);
return;
}
}
@@ -491,10 +506,15 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioDecHidlTest, DecodeTest) {
+class Codec2AudioDecDecodeTest : public Codec2AudioDecHidlTest,
+ public ::testing::WithParamInterface<int32_t> {
+};
+
+TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
description("Decodes input file");
if (mDisableTest) return;
+ uint32_t streamIndex = GetParam();
ASSERT_EQ(mComponent->start(), C2_OK);
mTimestampDevTest = true;
char mURL[512], info[512];
@@ -502,7 +522,12 @@
strcpy(mURL, gEnv->getRes().c_str());
strcpy(info, gEnv->getRes().c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mCompName, mURL, info, streamIndex);
+ if (!strcmp(mURL, gEnv->getRes().c_str())) {
+ ALOGV("EMPTY INPUT gEnv->getRes().c_str() %s mURL %s ",
+ gEnv->getRes().c_str(), mURL);
+ return;
+ }
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true);
@@ -521,6 +546,9 @@
Info.push_back({bytesCount, flags, timestamp});
}
eleInfo.close();
+ // Reset total no of frames received
+ mFramesReceived = 0;
+ mTimestampUs = 0;
int32_t bitStreamInfo[2] = {0};
if (mCompName == raw) {
bitStreamInfo[0] = 8000;
@@ -577,6 +605,9 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
+INSTANTIATE_TEST_CASE_P(StreamIndexes, Codec2AudioDecDecodeTest,
+ ::testing::Values(0, 1));
+
// thumbnail test
TEST_F(Codec2AudioDecHidlTest, ThumbnailTest) {
description("Test Request for thumbnail");
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
new file mode 100644
index 0000000..182af20
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
@@ -0,0 +1,443 @@
+5 32 0
+5 32 0
+337 1 0
+322 1 21333
+279 1 42666
+563 1 64000
+635 1 106666
+634 1 149333
+629 1 192000
+680 1 234666
+688 1 277333
+1036 1 320000
+1040 1 384000
+1009 1 448000
+1020 1 512000
+1357 1 576000
+1353 1 661333
+1351 1 746666
+1351 1 832000
+343 1 917333
+335 1 938666
+339 1 960000
+342 1 981333
+348 1 1002666
+350 1 1024000
+351 1 1045333
+342 1 1066666
+366 1 1088000
+340 1 1109333
+354 1 1130666
+340 1 1152000
+334 1 1173333
+338 1 1194666
+340 1 1216000
+351 1 1237333
+346 1 1258666
+331 1 1280000
+321 1 1301333
+343 1 1322666
+342 1 1344000
+345 1 1365333
+326 1 1386666
+342 1 1408000
+356 1 1429333
+351 1 1450666
+343 1 1472000
+347 1 1493333
+349 1 1514666
+350 1 1536000
+330 1 1557333
+341 1 1578666
+340 1 1600000
+330 1 1621333
+340 1 1642666
+335 1 1664000
+344 1 1685333
+359 1 1706666
+337 1 1728000
+346 1 1749333
+330 1 1770666
+351 1 1792000
+355 1 1813333
+352 1 1834666
+325 1 1856000
+342 1 1877333
+327 1 1898666
+349 1 1920000
+326 1 1941333
+337 1 1962666
+378 1 1984000
+321 1 2005333
+319 1 2026666
+346 1 2048000
+352 1 2069333
+349 1 2090666
+331 1 2112000
+330 1 2133333
+329 1 2154666
+333 1 2176000
+367 1 2197333
+362 1 2218666
+337 1 2240000
+337 1 2261333
+360 1 2282666
+333 1 2304000
+317 1 2325333
+344 1 2346666
+335 1 2368000
+337 1 2389333
+349 1 2410666
+336 1 2432000
+348 1 2453333
+349 1 2474666
+342 1 2496000
+359 1 2517333
+340 1 2538666
+340 1 2560000
+348 1 2581333
+334 1 2602666
+328 1 2624000
+341 1 2645333
+339 1 2666666
+337 1 2688000
+350 1 2709333
+326 1 2730666
+360 1 2752000
+344 1 2773333
+340 1 2794666
+343 1 2816000
+361 1 2837333
+329 1 2858666
+345 1 2880000
+345 1 2901333
+330 1 2922666
+342 1 2944000
+344 1 2965333
+330 1 2986666
+329 1 3008000
+335 1 3029333
+366 1 3050666
+328 1 3072000
+349 1 3093333
+339 1 3114666
+340 1 3136000
+335 1 3157333
+327 1 3178666
+348 1 3200000
+339 1 3221333
+334 1 3242666
+350 1 3264000
+325 1 3285333
+361 1 3306666
+338 1 3328000
+350 1 3349333
+353 1 3370666
+327 1 3392000
+346 1 3413333
+348 1 3434666
+339 1 3456000
+342 1 3477333
+334 1 3498666
+350 1 3520000
+354 1 3541333
+363 1 3562666
+322 1 3584000
+337 1 3605333
+355 1 3626666
+329 1 3648000
+324 1 3669333
+338 1 3690666
+356 1 3712000
+330 1 3733333
+321 1 3754666
+337 1 3776000
+345 1 3797333
+335 1 3818666
+348 1 3840000
+342 1 3861333
+348 1 3882666
+335 1 3904000
+344 1 3925333
+357 1 3946666
+368 1 3968000
+324 1 3989333
+343 1 4010666
+341 1 4032000
+329 1 4053333
+356 1 4074666
+317 1 4096000
+351 1 4117333
+340 1 4138666
+340 1 4160000
+332 1 4181333
+355 1 4202666
+357 1 4224000
+327 1 4245333
+338 1 4266666
+323 1 4288000
+346 1 4309333
+352 1 4330666
+347 1 4352000
+343 1 4373333
+311 1 4394666
+338 1 4416000
+365 1 4437333
+349 1 4458666
+327 1 4480000
+355 1 4501333
+319 1 4522666
+349 1 4544000
+351 1 4565333
+337 1 4586666
+340 1 4608000
+349 1 4629333
+316 1 4650666
+344 1 4672000
+334 1 4693333
+344 1 4714666
+347 1 4736000
+348 1 4757333
+334 1 4778666
+338 1 4800000
+331 1 4821333
+344 1 4842666
+342 1 4864000
+336 1 4885333
+326 1 4906666
+364 1 4928000
+350 1 4949333
+350 1 4970666
+363 1 4992000
+358 1 5013333
+305 1 5034666
+344 1 5056000
+346 1 5077333
+342 1 5098666
+330 1 5120000
+318 1 5141333
+361 1 5162666
+354 1 5184000
+313 1 5205333
+330 1 5226666
+350 1 5248000
+347 1 5269333
+346 1 5290666
+357 1 5312000
+325 1 5333333
+335 1 5354666
+331 1 5376000
+366 1 5397333
+329 1 5418666
+349 1 5440000
+371 1 5461333
+326 1 5482666
+333 1 5504000
+319 1 5525333
+327 1 5546666
+353 1 5568000
+356 1 5589333
+348 1 5610666
+338 1 5632000
+331 1 5653333
+341 1 5674666
+362 1 5696000
+326 1 5717333
+359 1 5738666
+315 1 5760000
+376 1 5781333
+343 1 5802666
+354 1 5824000
+353 1 5845333
+344 1 5866666
+334 1 5888000
+345 1 5909333
+355 1 5930666
+322 1 5952000
+334 1 5973333
+353 1 5994666
+338 1 6016000
+351 1 6037333
+334 1 6058666
+339 1 6080000
+345 1 6101333
+347 1 6122666
+355 1 6144000
+312 1 6165333
+352 1 6186666
+354 1 6208000
+318 1 6229333
+344 1 6250666
+363 1 6272000
+321 1 6293333
+339 1 6314666
+356 1 6336000
+334 1 6357333
+354 1 6378666
+325 1 6400000
+321 1 6421333
+341 1 6442666
+337 1 6464000
+351 1 6485333
+343 1 6506666
+341 1 6528000
+344 1 6549333
+341 1 6570666
+364 1 6592000
+319 1 6613333
+348 1 6634666
+332 1 6656000
+333 1 6677333
+343 1 6698666
+348 1 6720000
+347 1 6741333
+350 1 6762666
+342 1 6784000
+341 1 6805333
+326 1 6826666
+351 1 6848000
+329 1 6869333
+323 1 6890666
+350 1 6912000
+361 1 6933333
+326 1 6954666
+345 1 6976000
+345 1 6997333
+311 1 7018666
+349 1 7040000
+358 1 7061333
+352 1 7082666
+347 1 7104000
+364 1 7125333
+328 1 7146666
+318 1 7168000
+351 1 7189333
+340 1 7210666
+341 1 7232000
+355 1 7253333
+336 1 7274666
+352 1 7296000
+341 1 7317333
+334 1 7338666
+348 1 7360000
+342 1 7381333
+335 1 7402666
+342 1 7424000
+359 1 7445333
+349 1 7466666
+329 1 7488000
+356 1 7509333
+292 1 7530666
+316 1 7552000
+318 1 7573333
+320 1 7594666
+342 1 7616000
+285 1 7637333
+326 1 7658666
+352 1 7680000
+392 1 7701333
+364 1 7722666
+384 1 7744000
+334 1 7765333
+317 1 7786666
+326 1 7808000
+373 1 7829333
+354 1 7850666
+329 1 7872000
+347 1 7893333
+353 1 7914666
+338 1 7936000
+317 1 7957333
+354 1 7978666
+345 1 8000000
+350 1 8021333
+351 1 8042666
+332 1 8064000
+358 1 8085333
+315 1 8106666
+336 1 8128000
+358 1 8149333
+343 1 8170666
+319 1 8192000
+370 1 8213333
+344 1 8234666
+361 1 8256000
+343 1 8277333
+337 1 8298666
+354 1 8320000
+332 1 8341333
+348 1 8362666
+328 1 8384000
+345 1 8405333
+340 1 8426666
+346 1 8448000
+341 1 8469333
+344 1 8490666
+342 1 8512000
+341 1 8533333
+345 1 8554666
+337 1 8576000
+335 1 8597333
+335 1 8618666
+340 1 8640000
+345 1 8661333
+341 1 8682666
+342 1 8704000
+338 1 8725333
+343 1 8746666
+336 1 8768000
+338 1 8789333
+353 1 8810666
+339 1 8832000
+329 1 8853333
+349 1 8874666
+323 1 8896000
+351 1 8917333
+359 1 8938666
+357 1 8960000
+341 1 8981333
+333 1 9002666
+335 1 9024000
+328 1 9045333
+347 1 9066666
+343 1 9088000
+369 1 9109333
+331 1 9130666
+344 1 9152000
+330 1 9173333
+346 1 9194666
+337 1 9216000
+341 1 9237333
+338 1 9258666
+329 1 9280000
+360 1 9301333
+336 1 9322666
+341 1 9344000
+341 1 9365333
+345 1 9386666
+351 1 9408000
+349 1 9429333
+336 1 9450666
+326 1 9472000
+349 1 9493333
+343 1 9514666
+357 1 9536000
+342 1 9557333
+325 1 9578666
+346 1 9600000
+326 1 9621333
+402 1 9642666
+331 1 9664000
+339 1 9685333
+371 1 9706666
+314 1 9728000
+310 1 9749333
+364 1 9770666
+338 1 9792000
+339 1 9813333
+337 1 9834666
+355 1 9856000
+351 1 9877333
+332 1 9898666
+316 1 9920000
+474 1 9941333
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
new file mode 100644
index 0000000..c420009
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
@@ -0,0 +1,460 @@
+41 1 0
+41 1 20000
+82 1 40000
+82 1 80000
+82 1 120000
+82 1 160000
+82 1 200000
+82 1 240000
+82 1 280000
+82 1 320000
+82 1 360000
+123 1 400000
+123 1 460000
+123 1 520000
+123 1 580000
+123 1 640000
+164 1 700000
+164 1 780000
+164 1 860000
+164 1 940000
+164 1 1020000
+41 1 1100000
+41 1 1120000
+41 1 1140000
+41 1 1160000
+41 1 1180000
+41 1 1200000
+41 1 1220000
+41 1 1240000
+41 1 1260000
+41 1 1280000
+41 1 1300000
+41 1 1320000
+41 1 1340000
+41 1 1360000
+41 1 1380000
+41 1 1400000
+41 1 1420000
+41 1 1440000
+41 1 1460000
+41 1 1480000
+41 1 1500000
+41 1 1520000
+41 1 1540000
+41 1 1560000
+41 1 1580000
+41 1 1600000
+41 1 1620000
+41 1 1640000
+41 1 1660000
+41 1 1680000
+41 1 1700000
+41 1 1720000
+41 1 1740000
+41 1 1760000
+41 1 1780000
+41 1 1800000
+41 1 1820000
+41 1 1840000
+41 1 1860000
+41 1 1880000
+41 1 1900000
+41 1 1920000
+41 1 1940000
+41 1 1960000
+41 1 1980000
+41 1 2000000
+41 1 2020000
+41 1 2040000
+41 1 2060000
+41 1 2080000
+41 1 2100000
+41 1 2120000
+41 1 2140000
+41 1 2160000
+41 1 2180000
+41 1 2200000
+41 1 2220000
+41 1 2240000
+41 1 2260000
+41 1 2280000
+41 1 2300000
+41 1 2320000
+41 1 2340000
+41 1 2360000
+41 1 2380000
+41 1 2400000
+41 1 2420000
+41 1 2440000
+41 1 2460000
+41 1 2480000
+41 1 2500000
+41 1 2520000
+41 1 2540000
+41 1 2560000
+41 1 2580000
+41 1 2600000
+41 1 2620000
+41 1 2640000
+41 1 2660000
+41 1 2680000
+41 1 2700000
+41 1 2720000
+41 1 2740000
+41 1 2760000
+41 1 2780000
+41 1 2800000
+41 1 2820000
+41 1 2840000
+41 1 2860000
+41 1 2880000
+41 1 2900000
+41 1 2920000
+41 1 2940000
+41 1 2960000
+41 1 2980000
+41 1 3000000
+41 1 3020000
+41 1 3040000
+41 1 3060000
+41 1 3080000
+41 1 3100000
+41 1 3120000
+41 1 3140000
+41 1 3160000
+41 1 3180000
+41 1 3200000
+41 1 3220000
+41 1 3240000
+41 1 3260000
+41 1 3280000
+41 1 3300000
+41 1 3320000
+41 1 3340000
+41 1 3360000
+41 1 3380000
+41 1 3400000
+41 1 3420000
+41 1 3440000
+41 1 3460000
+41 1 3480000
+41 1 3500000
+41 1 3520000
+41 1 3540000
+41 1 3560000
+41 1 3580000
+41 1 3600000
+41 1 3620000
+41 1 3640000
+41 1 3660000
+41 1 3680000
+41 1 3700000
+41 1 3720000
+41 1 3740000
+41 1 3760000
+41 1 3780000
+41 1 3800000
+41 1 3820000
+41 1 3840000
+41 1 3860000
+41 1 3880000
+41 1 3900000
+41 1 3920000
+41 1 3940000
+41 1 3960000
+41 1 3980000
+41 1 4000000
+41 1 4020000
+41 1 4040000
+41 1 4060000
+41 1 4080000
+41 1 4100000
+41 1 4120000
+41 1 4140000
+41 1 4160000
+41 1 4180000
+41 1 4200000
+41 1 4220000
+41 1 4240000
+41 1 4260000
+41 1 4280000
+41 1 4300000
+41 1 4320000
+41 1 4340000
+41 1 4360000
+41 1 4380000
+41 1 4400000
+41 1 4420000
+41 1 4440000
+41 1 4460000
+41 1 4480000
+41 1 4500000
+41 1 4520000
+41 1 4540000
+41 1 4560000
+41 1 4580000
+41 1 4600000
+41 1 4620000
+41 1 4640000
+41 1 4660000
+41 1 4680000
+41 1 4700000
+41 1 4720000
+41 1 4740000
+41 1 4760000
+41 1 4780000
+41 1 4800000
+41 1 4820000
+41 1 4840000
+41 1 4860000
+41 1 4880000
+41 1 4900000
+41 1 4920000
+41 1 4940000
+41 1 4960000
+41 1 4980000
+41 1 5000000
+41 1 5020000
+41 1 5040000
+41 1 5060000
+41 1 5080000
+41 1 5100000
+41 1 5120000
+41 1 5140000
+41 1 5160000
+41 1 5180000
+41 1 5200000
+41 1 5220000
+41 1 5240000
+41 1 5260000
+41 1 5280000
+41 1 5300000
+41 1 5320000
+41 1 5340000
+41 1 5360000
+41 1 5380000
+41 1 5400000
+41 1 5420000
+41 1 5440000
+41 1 5460000
+41 1 5480000
+41 1 5500000
+41 1 5520000
+41 1 5540000
+41 1 5560000
+41 1 5580000
+41 1 5600000
+41 1 5620000
+41 1 5640000
+41 1 5660000
+41 1 5680000
+41 1 5700000
+41 1 5720000
+41 1 5740000
+41 1 5760000
+41 1 5780000
+41 1 5800000
+41 1 5820000
+41 1 5840000
+41 1 5860000
+41 1 5880000
+41 1 5900000
+41 1 5920000
+41 1 5940000
+41 1 5960000
+41 1 5980000
+41 1 6000000
+41 1 6020000
+41 1 6040000
+41 1 6060000
+41 1 6080000
+41 1 6100000
+41 1 6120000
+41 1 6140000
+41 1 6160000
+41 1 6180000
+41 1 6200000
+41 1 6220000
+41 1 6240000
+41 1 6260000
+41 1 6280000
+41 1 6300000
+41 1 6320000
+41 1 6340000
+41 1 6360000
+41 1 6380000
+41 1 6400000
+41 1 6420000
+41 1 6440000
+41 1 6460000
+41 1 6480000
+41 1 6500000
+41 1 6520000
+41 1 6540000
+41 1 6560000
+41 1 6580000
+41 1 6600000
+41 1 6620000
+41 1 6640000
+41 1 6660000
+41 1 6680000
+41 1 6700000
+41 1 6720000
+41 1 6740000
+41 1 6760000
+41 1 6780000
+41 1 6800000
+41 1 6820000
+41 1 6840000
+41 1 6860000
+41 1 6880000
+41 1 6900000
+41 1 6920000
+41 1 6940000
+41 1 6960000
+41 1 6980000
+41 1 7000000
+41 1 7020000
+41 1 7040000
+41 1 7060000
+41 1 7080000
+41 1 7100000
+41 1 7120000
+41 1 7140000
+41 1 7160000
+41 1 7180000
+41 1 7200000
+41 1 7220000
+41 1 7240000
+41 1 7260000
+41 1 7280000
+41 1 7300000
+41 1 7320000
+41 1 7340000
+41 1 7360000
+41 1 7380000
+41 1 7400000
+41 1 7420000
+41 1 7440000
+41 1 7460000
+41 1 7480000
+41 1 7500000
+41 1 7520000
+41 1 7540000
+41 1 7560000
+41 1 7580000
+41 1 7600000
+41 1 7620000
+41 1 7640000
+41 1 7660000
+41 1 7680000
+41 1 7700000
+41 1 7720000
+41 1 7740000
+41 1 7760000
+41 1 7780000
+41 1 7800000
+41 1 7820000
+41 1 7840000
+41 1 7860000
+41 1 7880000
+41 1 7900000
+41 1 7920000
+41 1 7940000
+41 1 7960000
+41 1 7980000
+41 1 8000000
+41 1 8020000
+41 1 8040000
+41 1 8060000
+41 1 8080000
+41 1 8100000
+41 1 8120000
+41 1 8140000
+41 1 8160000
+41 1 8180000
+41 1 8200000
+41 1 8220000
+41 1 8240000
+41 1 8260000
+41 1 8280000
+41 1 8300000
+41 1 8320000
+41 1 8340000
+41 1 8360000
+41 1 8380000
+41 1 8400000
+41 1 8420000
+41 1 8440000
+41 1 8460000
+41 1 8480000
+41 1 8500000
+41 1 8520000
+41 1 8540000
+41 1 8560000
+41 1 8580000
+41 1 8600000
+41 1 8620000
+41 1 8640000
+41 1 8660000
+41 1 8680000
+41 1 8700000
+41 1 8720000
+41 1 8740000
+41 1 8760000
+41 1 8780000
+41 1 8800000
+41 1 8820000
+41 1 8840000
+41 1 8860000
+41 1 8880000
+41 1 8900000
+41 1 8920000
+41 1 8940000
+41 1 8960000
+41 1 8980000
+41 1 9000000
+41 1 9020000
+41 1 9040000
+41 1 9060000
+41 1 9080000
+41 1 9100000
+41 1 9120000
+41 1 9140000
+41 1 9160000
+41 1 9180000
+41 1 9200000
+41 1 9220000
+41 1 9240000
+41 1 9260000
+41 1 9280000
+41 1 9300000
+41 1 9320000
+41 1 9340000
+41 1 9360000
+41 1 9380000
+41 1 9400000
+41 1 9420000
+41 1 9440000
+41 1 9460000
+41 1 9480000
+41 1 9500000
+41 1 9520000
+41 1 9540000
+41 1 9560000
+41 1 9580000
+41 1 9600000
+41 1 9620000
+41 1 9640000
+41 1 9660000
+41 1 9680000
+41 1 9700000
+41 1 9720000
+41 1 9740000
+41 1 9760000
+41 1 9780000
+41 1 9800000
+41 1 9820000
+41 1 9840000
+41 1 9860000
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
new file mode 100644
index 0000000..575c75f
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
@@ -0,0 +1,385 @@
+576 1 0
+576 1 24000
+1152 1 48000
+1152 1 96000
+1152 1 144000
+1152 1 192000
+1728 1 240000
+1728 1 312000
+1728 1 384000
+1728 1 456000
+1728 1 528000
+2304 1 600000
+2304 1 696000
+2304 1 792000
+2304 1 888000
+2304 1 984000
+576 1 1080000
+576 1 1104000
+576 1 1128000
+576 1 1152000
+576 1 1176000
+576 1 1200000
+576 1 1224000
+576 1 1248000
+576 1 1272000
+576 1 1296000
+576 1 1320000
+576 1 1344000
+576 1 1368000
+576 1 1392000
+576 1 1416000
+576 1 1440000
+576 1 1464000
+576 1 1488000
+576 1 1512000
+576 1 1536000
+576 1 1560000
+576 1 1584000
+576 1 1608000
+576 1 1632000
+576 1 1656000
+576 1 1680000
+576 1 1704000
+576 1 1728000
+576 1 1752000
+576 1 1776000
+576 1 1800000
+576 1 1824000
+576 1 1848000
+576 1 1872000
+576 1 1896000
+576 1 1920000
+576 1 1944000
+576 1 1968000
+576 1 1992000
+576 1 2016000
+576 1 2040000
+576 1 2064000
+576 1 2088000
+576 1 2112000
+576 1 2136000
+576 1 2160000
+576 1 2184000
+576 1 2208000
+576 1 2232000
+576 1 2256000
+576 1 2280000
+576 1 2304000
+576 1 2328000
+576 1 2352000
+576 1 2376000
+576 1 2400000
+576 1 2424000
+576 1 2448000
+576 1 2472000
+576 1 2496000
+576 1 2520000
+576 1 2544000
+576 1 2568000
+576 1 2592000
+576 1 2616000
+576 1 2640000
+576 1 2664000
+576 1 2688000
+576 1 2712000
+576 1 2736000
+576 1 2760000
+576 1 2784000
+576 1 2808000
+576 1 2832000
+576 1 2856000
+576 1 2880000
+576 1 2904000
+576 1 2928000
+576 1 2952000
+576 1 2976000
+576 1 3000000
+576 1 3024000
+576 1 3048000
+576 1 3072000
+576 1 3096000
+576 1 3120000
+576 1 3144000
+576 1 3168000
+576 1 3192000
+576 1 3216000
+576 1 3240000
+576 1 3264000
+576 1 3288000
+576 1 3312000
+576 1 3336000
+576 1 3360000
+576 1 3384000
+576 1 3408000
+576 1 3432000
+576 1 3456000
+576 1 3480000
+576 1 3504000
+576 1 3528000
+576 1 3552000
+576 1 3576000
+576 1 3600000
+576 1 3624000
+576 1 3648000
+576 1 3672000
+576 1 3696000
+576 1 3720000
+576 1 3744000
+576 1 3768000
+576 1 3792000
+576 1 3816000
+576 1 3840000
+576 1 3864000
+576 1 3888000
+576 1 3912000
+576 1 3936000
+576 1 3960000
+576 1 3984000
+576 1 4008000
+576 1 4032000
+576 1 4056000
+576 1 4080000
+576 1 4104000
+576 1 4128000
+576 1 4152000
+576 1 4176000
+576 1 4200000
+576 1 4224000
+576 1 4248000
+576 1 4272000
+576 1 4296000
+576 1 4320000
+576 1 4344000
+576 1 4368000
+576 1 4392000
+576 1 4416000
+576 1 4440000
+576 1 4464000
+576 1 4488000
+576 1 4512000
+576 1 4536000
+576 1 4560000
+576 1 4584000
+576 1 4608000
+576 1 4632000
+576 1 4656000
+576 1 4680000
+576 1 4704000
+576 1 4728000
+576 1 4752000
+576 1 4776000
+576 1 4800000
+576 1 4824000
+576 1 4848000
+576 1 4872000
+576 1 4896000
+576 1 4920000
+576 1 4944000
+576 1 4968000
+576 1 4992000
+576 1 5016000
+576 1 5040000
+576 1 5064000
+576 1 5088000
+576 1 5112000
+576 1 5136000
+576 1 5160000
+576 1 5184000
+576 1 5208000
+576 1 5232000
+576 1 5256000
+576 1 5280000
+576 1 5304000
+576 1 5328000
+576 1 5352000
+576 1 5376000
+576 1 5400000
+576 1 5424000
+576 1 5448000
+576 1 5472000
+576 1 5496000
+576 1 5520000
+576 1 5544000
+576 1 5568000
+576 1 5592000
+576 1 5616000
+576 1 5640000
+576 1 5664000
+576 1 5688000
+576 1 5712000
+576 1 5736000
+576 1 5760000
+576 1 5784000
+576 1 5808000
+576 1 5832000
+576 1 5856000
+576 1 5880000
+576 1 5904000
+576 1 5928000
+576 1 5952000
+576 1 5976000
+576 1 6000000
+576 1 6024000
+576 1 6048000
+576 1 6072000
+576 1 6096000
+576 1 6120000
+576 1 6144000
+576 1 6168000
+576 1 6192000
+576 1 6216000
+576 1 6240000
+576 1 6264000
+576 1 6288000
+576 1 6312000
+576 1 6336000
+576 1 6360000
+576 1 6384000
+576 1 6408000
+576 1 6432000
+576 1 6456000
+576 1 6480000
+576 1 6504000
+576 1 6528000
+576 1 6552000
+576 1 6576000
+576 1 6600000
+576 1 6624000
+576 1 6648000
+576 1 6672000
+576 1 6696000
+576 1 6720000
+576 1 6744000
+576 1 6768000
+576 1 6792000
+576 1 6816000
+576 1 6840000
+576 1 6864000
+576 1 6888000
+576 1 6912000
+576 1 6936000
+576 1 6960000
+576 1 6984000
+576 1 7008000
+576 1 7032000
+576 1 7056000
+576 1 7080000
+576 1 7104000
+576 1 7128000
+576 1 7152000
+576 1 7176000
+576 1 7200000
+576 1 7224000
+576 1 7248000
+576 1 7272000
+576 1 7296000
+576 1 7320000
+576 1 7344000
+576 1 7368000
+576 1 7392000
+576 1 7416000
+576 1 7440000
+576 1 7464000
+576 1 7488000
+576 1 7512000
+576 1 7536000
+576 1 7560000
+576 1 7584000
+576 1 7608000
+576 1 7632000
+576 1 7656000
+576 1 7680000
+576 1 7704000
+576 1 7728000
+576 1 7752000
+576 1 7776000
+576 1 7800000
+576 1 7824000
+576 1 7848000
+576 1 7872000
+576 1 7896000
+576 1 7920000
+576 1 7944000
+576 1 7968000
+576 1 7992000
+576 1 8016000
+576 1 8040000
+576 1 8064000
+576 1 8088000
+576 1 8112000
+576 1 8136000
+576 1 8160000
+576 1 8184000
+576 1 8208000
+576 1 8232000
+576 1 8256000
+576 1 8280000
+576 1 8304000
+576 1 8328000
+576 1 8352000
+576 1 8376000
+576 1 8400000
+576 1 8424000
+576 1 8448000
+576 1 8472000
+576 1 8496000
+576 1 8520000
+576 1 8544000
+576 1 8568000
+576 1 8592000
+576 1 8616000
+576 1 8640000
+576 1 8664000
+576 1 8688000
+576 1 8712000
+576 1 8736000
+576 1 8760000
+576 1 8784000
+576 1 8808000
+576 1 8832000
+576 1 8856000
+576 1 8880000
+576 1 8904000
+576 1 8928000
+576 1 8952000
+576 1 8976000
+576 1 9000000
+576 1 9024000
+576 1 9048000
+576 1 9072000
+576 1 9096000
+576 1 9120000
+576 1 9144000
+576 1 9168000
+576 1 9192000
+576 1 9216000
+576 1 9240000
+576 1 9264000
+576 1 9288000
+576 1 9312000
+576 1 9336000
+576 1 9360000
+576 1 9384000
+576 1 9408000
+576 1 9432000
+576 1 9456000
+576 1 9480000
+576 1 9504000
+576 1 9528000
+576 1 9552000
+576 1 9576000
+576 1 9600000
+576 1 9624000
+576 1 9648000
+576 1 9672000
+576 1 9696000
+576 1 9720000
+576 1 9744000
+576 1 9768000
+576 1 9792000
+576 1 9816000
+576 1 9840000
+576 1 9864000
+576 1 9888000
+576 1 9912000
diff --git a/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
new file mode 100644
index 0000000..0176eaf4
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
@@ -0,0 +1,807 @@
+32 1 0
+32 1 20000
+64 1 40000
+64 1 80000
+64 1 120000
+96 1 160000
+96 1 220000
+96 1 280000
+96 1 340000
+128 1 400000
+128 1 480000
+128 1 560000
+128 1 640000
+128 1 720000
+32 1 800000
+32 1 820000
+32 1 840000
+32 1 860000
+32 1 880000
+32 1 900000
+32 1 920000
+32 1 940000
+32 1 960000
+32 1 980000
+32 1 1000000
+32 1 1020000
+32 1 1040000
+32 1 1060000
+32 1 1080000
+32 1 1100000
+32 1 1120000
+32 1 1140000
+32 1 1160000
+32 1 1180000
+32 1 1200000
+32 1 1220000
+32 1 1240000
+32 1 1260000
+32 1 1280000
+32 1 1300000
+32 1 1320000
+32 1 1340000
+32 1 1360000
+32 1 1380000
+32 1 1400000
+32 1 1420000
+32 1 1440000
+32 1 1460000
+32 1 1480000
+32 1 1500000
+32 1 1520000
+32 1 1540000
+32 1 1560000
+32 1 1580000
+32 1 1600000
+32 1 1620000
+32 1 1640000
+32 1 1660000
+32 1 1680000
+32 1 1700000
+32 1 1720000
+32 1 1740000
+32 1 1760000
+32 1 1780000
+32 1 1800000
+32 1 1820000
+32 1 1840000
+32 1 1860000
+32 1 1880000
+32 1 1900000
+32 1 1920000
+32 1 1940000
+32 1 1960000
+32 1 1980000
+32 1 2000000
+32 1 2020000
+32 1 2040000
+32 1 2060000
+32 1 2080000
+32 1 2100000
+32 1 2120000
+32 1 2140000
+32 1 2160000
+32 1 2180000
+32 1 2200000
+32 1 2220000
+32 1 2240000
+32 1 2260000
+32 1 2280000
+32 1 2300000
+32 1 2320000
+32 1 2340000
+32 1 2360000
+32 1 2380000
+32 1 2400000
+32 1 2420000
+32 1 2440000
+32 1 2460000
+32 1 2480000
+32 1 2500000
+32 1 2520000
+32 1 2540000
+32 1 2560000
+32 1 2580000
+32 1 2600000
+32 1 2620000
+32 1 2640000
+32 1 2660000
+32 1 2680000
+32 1 2700000
+32 1 2720000
+32 1 2740000
+32 1 2760000
+32 1 2780000
+32 1 2800000
+32 1 2820000
+32 1 2840000
+32 1 2860000
+32 1 2880000
+32 1 2900000
+32 1 2920000
+32 1 2940000
+32 1 2960000
+32 1 2980000
+32 1 3000000
+32 1 3020000
+32 1 3040000
+32 1 3060000
+32 1 3080000
+32 1 3100000
+32 1 3120000
+32 1 3140000
+32 1 3160000
+32 1 3180000
+32 1 3200000
+32 1 3220000
+32 1 3240000
+32 1 3260000
+32 1 3280000
+32 1 3300000
+32 1 3320000
+32 1 3340000
+32 1 3360000
+32 1 3380000
+32 1 3400000
+32 1 3420000
+32 1 3440000
+32 1 3460000
+32 1 3480000
+32 1 3500000
+32 1 3520000
+32 1 3540000
+32 1 3560000
+32 1 3580000
+32 1 3600000
+32 1 3620000
+32 1 3640000
+32 1 3660000
+32 1 3680000
+32 1 3700000
+32 1 3720000
+32 1 3740000
+32 1 3760000
+32 1 3780000
+32 1 3800000
+32 1 3820000
+32 1 3840000
+32 1 3860000
+32 1 3880000
+32 1 3900000
+32 1 3920000
+32 1 3940000
+32 1 3960000
+32 1 3980000
+32 1 4000000
+32 1 4020000
+32 1 4040000
+32 1 4060000
+32 1 4080000
+32 1 4100000
+32 1 4120000
+32 1 4140000
+32 1 4160000
+32 1 4180000
+32 1 4200000
+32 1 4220000
+32 1 4240000
+32 1 4260000
+32 1 4280000
+32 1 4300000
+32 1 4320000
+32 1 4340000
+32 1 4360000
+32 1 4380000
+32 1 4400000
+32 1 4420000
+32 1 4440000
+32 1 4460000
+32 1 4480000
+32 1 4500000
+32 1 4520000
+32 1 4540000
+32 1 4560000
+32 1 4580000
+32 1 4600000
+32 1 4620000
+32 1 4640000
+32 1 4660000
+32 1 4680000
+32 1 4700000
+32 1 4720000
+32 1 4740000
+32 1 4760000
+32 1 4780000
+32 1 4800000
+32 1 4820000
+32 1 4840000
+32 1 4860000
+32 1 4880000
+32 1 4900000
+32 1 4920000
+32 1 4940000
+32 1 4960000
+32 1 4980000
+32 1 5000000
+32 1 5020000
+32 1 5040000
+32 1 5060000
+32 1 5080000
+32 1 5100000
+32 1 5120000
+32 1 5140000
+32 1 5160000
+32 1 5180000
+32 1 5200000
+32 1 5220000
+32 1 5240000
+32 1 5260000
+32 1 5280000
+32 1 5300000
+32 1 5320000
+32 1 5340000
+32 1 5360000
+32 1 5380000
+32 1 5400000
+32 1 5420000
+32 1 5440000
+32 1 5460000
+32 1 5480000
+32 1 5500000
+32 1 5520000
+32 1 5540000
+32 1 5560000
+32 1 5580000
+32 1 5600000
+32 1 5620000
+32 1 5640000
+32 1 5660000
+32 1 5680000
+32 1 5700000
+32 1 5720000
+32 1 5740000
+32 1 5760000
+32 1 5780000
+32 1 5800000
+32 1 5820000
+32 1 5840000
+32 1 5860000
+32 1 5880000
+32 1 5900000
+32 1 5920000
+32 1 5940000
+32 1 5960000
+32 1 5980000
+32 1 6000000
+32 1 6020000
+32 1 6040000
+32 1 6060000
+32 1 6080000
+32 1 6100000
+32 1 6120000
+32 1 6140000
+32 1 6160000
+32 1 6180000
+32 1 6200000
+32 1 6220000
+32 1 6240000
+32 1 6260000
+32 1 6280000
+32 1 6300000
+32 1 6320000
+32 1 6340000
+32 1 6360000
+32 1 6380000
+32 1 6400000
+32 1 6420000
+32 1 6440000
+32 1 6460000
+32 1 6480000
+32 1 6500000
+32 1 6520000
+32 1 6540000
+32 1 6560000
+32 1 6580000
+32 1 6600000
+32 1 6620000
+32 1 6640000
+32 1 6660000
+32 1 6680000
+32 1 6700000
+32 1 6720000
+32 1 6740000
+32 1 6760000
+32 1 6780000
+32 1 6800000
+32 1 6820000
+32 1 6840000
+32 1 6860000
+32 1 6880000
+32 1 6900000
+32 1 6920000
+32 1 6940000
+32 1 6960000
+32 1 6980000
+32 1 7000000
+32 1 7020000
+32 1 7040000
+32 1 7060000
+32 1 7080000
+32 1 7100000
+32 1 7120000
+32 1 7140000
+32 1 7160000
+32 1 7180000
+32 1 7200000
+32 1 7220000
+32 1 7240000
+32 1 7260000
+32 1 7280000
+32 1 7300000
+32 1 7320000
+32 1 7340000
+32 1 7360000
+32 1 7380000
+32 1 7400000
+32 1 7420000
+32 1 7440000
+32 1 7460000
+32 1 7480000
+32 1 7500000
+32 1 7520000
+32 1 7540000
+32 1 7560000
+32 1 7580000
+32 1 7600000
+32 1 7620000
+32 1 7640000
+32 1 7660000
+32 1 7680000
+32 1 7700000
+32 1 7720000
+32 1 7740000
+32 1 7760000
+32 1 7780000
+32 1 7800000
+32 1 7820000
+32 1 7840000
+32 1 7860000
+32 1 7880000
+32 1 7900000
+32 1 7920000
+32 1 7940000
+32 1 7960000
+32 1 7980000
+32 1 8000000
+32 1 8020000
+32 1 8040000
+32 1 8060000
+32 1 8080000
+32 1 8100000
+32 1 8120000
+32 1 8140000
+32 1 8160000
+32 1 8180000
+32 1 8200000
+32 1 8220000
+32 1 8240000
+32 1 8260000
+32 1 8280000
+32 1 8300000
+32 1 8320000
+32 1 8340000
+32 1 8360000
+32 1 8380000
+32 1 8400000
+32 1 8420000
+32 1 8440000
+32 1 8460000
+32 1 8480000
+32 1 8500000
+32 1 8520000
+32 1 8540000
+32 1 8560000
+32 1 8580000
+32 1 8600000
+32 1 8620000
+32 1 8640000
+32 1 8660000
+32 1 8680000
+32 1 8700000
+32 1 8720000
+32 1 8740000
+32 1 8760000
+32 1 8780000
+32 1 8800000
+32 1 8820000
+32 1 8840000
+32 1 8860000
+32 1 8880000
+32 1 8900000
+32 1 8920000
+32 1 8940000
+32 1 8960000
+32 1 8980000
+32 1 9000000
+32 1 9020000
+32 1 9040000
+32 1 9060000
+32 1 9080000
+32 1 9100000
+32 1 9120000
+32 1 9140000
+32 1 9160000
+32 1 9180000
+32 1 9200000
+32 1 9220000
+32 1 9240000
+32 1 9260000
+32 1 9280000
+32 1 9300000
+32 1 9320000
+32 1 9340000
+32 1 9360000
+32 1 9380000
+32 1 9400000
+32 1 9420000
+32 1 9440000
+32 1 9460000
+32 1 9480000
+32 1 9500000
+32 1 9520000
+32 1 9540000
+32 1 9560000
+32 1 9580000
+32 1 9600000
+32 1 9620000
+32 1 9640000
+32 1 9660000
+32 1 9680000
+32 1 9700000
+32 1 9720000
+32 1 9740000
+32 1 9760000
+32 1 9780000
+32 1 9800000
+32 1 9820000
+32 1 9840000
+32 1 9860000
+32 1 9880000
+32 1 9900000
+32 1 9920000
+32 1 9940000
+32 1 9960000
+32 1 9980000
+32 1 10000000
+32 1 10020000
+32 1 10040000
+32 1 10060000
+32 1 10080000
+32 1 10100000
+32 1 10120000
+32 1 10140000
+32 1 10160000
+32 1 10180000
+32 1 10200000
+32 1 10220000
+32 1 10240000
+32 1 10260000
+32 1 10280000
+32 1 10300000
+32 1 10320000
+32 1 10340000
+32 1 10360000
+32 1 10380000
+32 1 10400000
+32 1 10420000
+32 1 10440000
+32 1 10460000
+32 1 10480000
+32 1 10500000
+32 1 10520000
+32 1 10540000
+32 1 10560000
+32 1 10580000
+32 1 10600000
+32 1 10620000
+32 1 10640000
+32 1 10660000
+32 1 10680000
+32 1 10700000
+32 1 10720000
+32 1 10740000
+32 1 10760000
+32 1 10780000
+32 1 10800000
+32 1 10820000
+32 1 10840000
+32 1 10860000
+32 1 10880000
+32 1 10900000
+32 1 10920000
+32 1 10940000
+32 1 10960000
+32 1 10980000
+32 1 11000000
+32 1 11020000
+32 1 11040000
+32 1 11060000
+32 1 11080000
+32 1 11100000
+32 1 11120000
+32 1 11140000
+32 1 11160000
+32 1 11180000
+32 1 11200000
+32 1 11220000
+32 1 11240000
+32 1 11260000
+32 1 11280000
+32 1 11300000
+32 1 11320000
+32 1 11340000
+32 1 11360000
+32 1 11380000
+32 1 11400000
+32 1 11420000
+32 1 11440000
+32 1 11460000
+32 1 11480000
+32 1 11500000
+32 1 11520000
+32 1 11540000
+32 1 11560000
+32 1 11580000
+32 1 11600000
+32 1 11620000
+32 1 11640000
+32 1 11660000
+32 1 11680000
+32 1 11700000
+32 1 11720000
+32 1 11740000
+32 1 11760000
+32 1 11780000
+32 1 11800000
+32 1 11820000
+32 1 11840000
+32 1 11860000
+32 1 11880000
+32 1 11900000
+32 1 11920000
+32 1 11940000
+32 1 11960000
+32 1 11980000
+32 1 12000000
+32 1 12020000
+32 1 12040000
+32 1 12060000
+32 1 12080000
+32 1 12100000
+32 1 12120000
+32 1 12140000
+32 1 12160000
+32 1 12180000
+32 1 12200000
+32 1 12220000
+32 1 12240000
+32 1 12260000
+32 1 12280000
+32 1 12300000
+32 1 12320000
+32 1 12340000
+32 1 12360000
+32 1 12380000
+32 1 12400000
+32 1 12420000
+32 1 12440000
+32 1 12460000
+32 1 12480000
+32 1 12500000
+32 1 12520000
+32 1 12540000
+32 1 12560000
+32 1 12580000
+32 1 12600000
+32 1 12620000
+32 1 12640000
+32 1 12660000
+32 1 12680000
+32 1 12700000
+32 1 12720000
+32 1 12740000
+32 1 12760000
+32 1 12780000
+32 1 12800000
+32 1 12820000
+32 1 12840000
+32 1 12860000
+32 1 12880000
+32 1 12900000
+32 1 12920000
+32 1 12940000
+32 1 12960000
+32 1 12980000
+32 1 13000000
+32 1 13020000
+32 1 13040000
+32 1 13060000
+32 1 13080000
+32 1 13100000
+32 1 13120000
+32 1 13140000
+32 1 13160000
+32 1 13180000
+32 1 13200000
+32 1 13220000
+32 1 13240000
+32 1 13260000
+32 1 13280000
+32 1 13300000
+32 1 13320000
+32 1 13340000
+32 1 13360000
+32 1 13380000
+32 1 13400000
+32 1 13420000
+32 1 13440000
+32 1 13460000
+32 1 13480000
+32 1 13500000
+32 1 13520000
+32 1 13540000
+32 1 13560000
+32 1 13580000
+32 1 13600000
+32 1 13620000
+32 1 13640000
+32 1 13660000
+32 1 13680000
+32 1 13700000
+32 1 13720000
+32 1 13740000
+32 1 13760000
+32 1 13780000
+32 1 13800000
+32 1 13820000
+32 1 13840000
+32 1 13860000
+32 1 13880000
+32 1 13900000
+32 1 13920000
+32 1 13940000
+32 1 13960000
+32 1 13980000
+32 1 14000000
+32 1 14020000
+32 1 14040000
+32 1 14060000
+32 1 14080000
+32 1 14100000
+32 1 14120000
+32 1 14140000
+32 1 14160000
+32 1 14180000
+32 1 14200000
+32 1 14220000
+32 1 14240000
+32 1 14260000
+32 1 14280000
+32 1 14300000
+32 1 14320000
+32 1 14340000
+32 1 14360000
+32 1 14380000
+32 1 14400000
+32 1 14420000
+32 1 14440000
+32 1 14460000
+32 1 14480000
+32 1 14500000
+32 1 14520000
+32 1 14540000
+32 1 14560000
+32 1 14580000
+32 1 14600000
+32 1 14620000
+32 1 14640000
+32 1 14660000
+32 1 14680000
+32 1 14700000
+32 1 14720000
+32 1 14740000
+32 1 14760000
+32 1 14780000
+32 1 14800000
+32 1 14820000
+32 1 14840000
+32 1 14860000
+32 1 14880000
+32 1 14900000
+32 1 14920000
+32 1 14940000
+32 1 14960000
+32 1 14980000
+32 1 15000000
+32 1 15020000
+32 1 15040000
+32 1 15060000
+32 1 15080000
+32 1 15100000
+32 1 15120000
+32 1 15140000
+32 1 15160000
+32 1 15180000
+32 1 15200000
+32 1 15220000
+32 1 15240000
+32 1 15260000
+32 1 15280000
+32 1 15300000
+32 1 15320000
+32 1 15340000
+32 1 15360000
+32 1 15380000
+32 1 15400000
+32 1 15420000
+32 1 15440000
+32 1 15460000
+32 1 15480000
+32 1 15500000
+32 1 15520000
+32 1 15540000
+32 1 15560000
+32 1 15580000
+32 1 15600000
+32 1 15620000
+32 1 15640000
+32 1 15660000
+32 1 15680000
+32 1 15700000
+32 1 15720000
+32 1 15740000
+32 1 15760000
+32 1 15780000
+32 1 15800000
+32 1 15820000
+32 1 15840000
+32 1 15860000
+32 1 15880000
+32 1 15900000
+32 1 15920000
+32 1 15940000
+32 1 15960000
+32 1 15980000
+32 1 16000000
+32 1 16020000
+32 1 16040000
+32 1 16060000
+32 1 16080000
+32 1 16100000
+32 1 16120000
+32 1 16140000
+32 1 16160000
+32 1 16180000
+32 1 16200000
+32 1 16220000
+32 1 16240000
+32 1 16260000
+32 1 16280000
+32 1 16300000
+32 1 16320000
+32 1 16340000
+32 1 16360000
+32 1 16380000
+32 1 16400000
+32 1 16420000
+32 1 16440000
+32 1 16460000
+32 1 16480000
+32 1 16500000
+32 1 16520000
+32 1 16540000
+32 1 16560000
+32 1 16580000
+32 1 16600000
+32 1 16620000
+32 1 16640000
diff --git a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
index 9a42d72..8cbb7a7 100644
--- a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
@@ -421,17 +421,21 @@
ASSERT_EQ(mDisableTest, false);
}
+class Codec2VideoDecDecodeTest : public Codec2VideoDecHidlTest,
+ public ::testing::WithParamInterface<int32_t> {
+};
+
// Bitstream Test
-TEST_F(Codec2VideoDecHidlTest, DecodeTest) {
+TEST_P(Codec2VideoDecDecodeTest, DecodeTest) {
description("Decodes input file");
if (mDisableTest) return;
+ uint32_t streamIndex = GetParam();
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
-
strcpy(mURL, gEnv->getRes().c_str());
strcpy(info, gEnv->getRes().c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mCompName, mURL, info, streamIndex);
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
@@ -452,6 +456,9 @@
eleInfo.close();
ASSERT_EQ(mComponent->start(), C2_OK);
+ // Reset total no of frames received
+ mFramesReceived = 0;
+ mTimestampUs = 0;
ALOGV("mURL : %s", mURL);
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
@@ -476,8 +483,11 @@
}
if (mTimestampDevTest) EXPECT_EQ(mTimestampUslist.empty(), true);
+ ASSERT_EQ(mComponent->stop(), C2_OK);
}
+INSTANTIATE_TEST_CASE_P(StreamIndexes, Codec2VideoDecDecodeTest,
+ ::testing::Values(0, 1));
// Adaptive Test
TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index f36027e..5d0ccd2 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -517,6 +517,13 @@
caps->addProfileLevel(VP9Profile2, VP9Level5);
caps->addProfileLevel(VP9Profile2HDR, VP9Level5);
}
+ } else if (mediaType == MIMETYPE_VIDEO_AV1 && !encoder) {
+ caps->addProfileLevel(AV1Profile0, AV1Level2);
+ caps->addProfileLevel(AV1Profile0, AV1Level21);
+ caps->addProfileLevel(AV1Profile1, AV1Level22);
+ caps->addProfileLevel(AV1Profile1, AV1Level3);
+ caps->addProfileLevel(AV1Profile2, AV1Level31);
+ caps->addProfileLevel(AV1Profile2, AV1Level32);
} else if (mediaType == MIMETYPE_VIDEO_HEVC && !encoder) {
caps->addProfileLevel(HEVCProfileMain, HEVCMainTierLevel51);
caps->addProfileLevel(HEVCProfileMainStill, HEVCMainTierLevel51);
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 97e17e8..b1b33e1 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -326,6 +326,41 @@
{ C2Config::PROFILE_VP9_3, VP9Profile3 },
};
+ALookup<C2Config::level_t, int32_t> sAv1Levels = {
+ { C2Config::LEVEL_AV1_2, AV1Level2 },
+ { C2Config::LEVEL_AV1_2_1, AV1Level21 },
+ { C2Config::LEVEL_AV1_2_2, AV1Level22 },
+ { C2Config::LEVEL_AV1_2_3, AV1Level23 },
+ { C2Config::LEVEL_AV1_3, AV1Level3 },
+ { C2Config::LEVEL_AV1_3_1, AV1Level31 },
+ { C2Config::LEVEL_AV1_3_2, AV1Level32 },
+ { C2Config::LEVEL_AV1_3_3, AV1Level33 },
+ { C2Config::LEVEL_AV1_4, AV1Level4 },
+ { C2Config::LEVEL_AV1_4_1, AV1Level41 },
+ { C2Config::LEVEL_AV1_4_2, AV1Level42 },
+ { C2Config::LEVEL_AV1_4_3, AV1Level43 },
+ { C2Config::LEVEL_AV1_5, AV1Level5 },
+ { C2Config::LEVEL_AV1_5_1, AV1Level51 },
+ { C2Config::LEVEL_AV1_5_2, AV1Level52 },
+ { C2Config::LEVEL_AV1_5_3, AV1Level53 },
+ { C2Config::LEVEL_AV1_6, AV1Level6 },
+ { C2Config::LEVEL_AV1_6_1, AV1Level61 },
+ { C2Config::LEVEL_AV1_6_2, AV1Level62 },
+ { C2Config::LEVEL_AV1_6_3, AV1Level63 },
+ { C2Config::LEVEL_AV1_7, AV1Level7 },
+ { C2Config::LEVEL_AV1_7_1, AV1Level71 },
+ { C2Config::LEVEL_AV1_7_2, AV1Level72 },
+ { C2Config::LEVEL_AV1_7_3, AV1Level73 },
+};
+
+
+ALookup<C2Config::profile_t, int32_t> sAv1Profiles = {
+ { C2Config::PROFILE_AV1_0, AV1Profile0 },
+ { C2Config::PROFILE_AV1_1, AV1Profile1 },
+ { C2Config::PROFILE_AV1_2, AV1Profile2 },
+};
+
+
/**
* A helper that passes through vendor extension profile and level values.
*/
diff --git a/media/codec2/vndk/C2Config.cpp b/media/codec2/vndk/C2Config.cpp
index da12903..782bec5 100644
--- a/media/codec2/vndk/C2Config.cpp
+++ b/media/codec2/vndk/C2Config.cpp
@@ -139,6 +139,9 @@
{ "vp9-1", C2Config::PROFILE_VP9_1 },
{ "vp9-2", C2Config::PROFILE_VP9_2 },
{ "vp9-3", C2Config::PROFILE_VP9_3 },
+ { "av1-0", C2Config::PROFILE_AV1_0 },
+ { "av1-1", C2Config::PROFILE_AV1_1 },
+ { "av1-2", C2Config::PROFILE_AV1_2 },
}))
DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(C2Config::level_t, ({
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 2d4e19e..a5dd203 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -821,6 +821,7 @@
emplace("c2.android.vp9.decoder", "libcodec2_soft_vp9dec.so");
emplace("c2.android.vp8.encoder", "libcodec2_soft_vp8enc.so");
emplace("c2.android.vp9.encoder", "libcodec2_soft_vp9enc.so");
+ emplace("c2.android.av1.decoder", "libcodec2_soft_av1dec.so");
emplace("c2.android.raw.decoder", "libcodec2_soft_rawdec.so");
emplace("c2.android.flac.decoder", "libcodec2_soft_flacdec.so");
emplace("c2.android.flac.encoder", "libcodec2_soft_flacenc.so");
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 4e9ac6e..beddad0 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -377,6 +377,10 @@
return NULL;
}
+static const char *extensions[] = {
+ "aac",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -387,7 +391,7 @@
UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
1, // version
"AAC Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 00d2a92..ffeff42 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -199,7 +199,7 @@
if (mInitCheck == OK) {
AMediaFormat_setString(meta,
- AMEDIAFORMAT_KEY_MIME, mIsWide ? "audio/amr-wb" : "audio/amr");
+ AMEDIAFORMAT_KEY_MIME, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB : "audio/amr");
}
return AMEDIA_OK;
@@ -280,8 +280,8 @@
ReadOptions::SeekMode mode;
if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) {
size_t size;
- int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame.
- mCurrentTimeUs = seekFrame * 20000ll;
+ int64_t seekFrame = seekTimeUs / 20000LL; // 20ms per frame.
+ mCurrentTimeUs = seekFrame * 20000LL;
size_t index = seekFrame < 0 ? 0 : seekFrame / 50;
if (index >= mOffsetTableLength) {
@@ -358,6 +358,12 @@
////////////////////////////////////////////////////////////////////////////////
+static const char *extensions[] = {
+ "amr",
+ "awb",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -368,21 +374,24 @@
1,
"AMR Extractor",
{
- .v2 = [](
- CDataSource *source,
- float *confidence,
- void **,
- FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffAMR(&helper, nullptr, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new AMRExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
- }
- }
+ .v3 = {
+ [](
+ CDataSource *source,
+ float *confidence,
+ void **,
+ FreeMetaFunc *) -> CreatorFunc {
+ DataSourceHelper helper(source);
+ if (SniffAMR(&helper, nullptr, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new AMRExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
+ },
+ },
};
}
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index b5eaf9b..e4bbc07 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -822,6 +822,11 @@
return true;
}
+static const char *extensions[] = {
+ "flac",
+ "fl",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -833,21 +838,24 @@
1,
"FLAC Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffFLAC(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new FLACExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffFLAC(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new FLACExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index 0c74376..9f4f9e6 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -326,6 +326,18 @@
}
+static const char *extensions[] = {
+ "imy",
+ "mid",
+ "midi",
+ "mxmf",
+ "ota",
+ "rtttl",
+ "rtx",
+ "smf",
+ "xmf",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -337,20 +349,23 @@
1,
"MIDI Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- if (SniffMidi(source, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MidiExtractor(source));};
- }
- return NULL;
+ if (SniffMidi(source, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MidiExtractor(source));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 42a9c42..4200a46 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1463,6 +1463,8 @@
AMediaFormat_setBuffer(meta,
AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
}
+ } else if (!strcmp("V_AV1", codecID)) {
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
} else {
ALOGW("%s is not supported.", codecID);
continue;
@@ -1667,6 +1669,12 @@
return true;
}
+static const char *extensions[] = {
+ "mka",
+ "mkv",
+ "webm",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -1678,19 +1686,22 @@
1,
"Matroska Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffMatroska(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffMatroska(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
}
};
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 20bcda8..61838f6 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -609,7 +609,7 @@
if (mInitCheck != OK) {
return AMEDIA_ERROR_UNKNOWN;
}
- AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, "audio/mpeg");
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
DataSourceHelper helper(mDataSource);
ID3 id3(&helper);
@@ -707,6 +707,14 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "mp3",
+ "mpeg",
+ "mpg",
+ "mpga",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -716,7 +724,7 @@
UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
1, // version
"MP3 Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} }
};
}
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index 9eb72a7..ca51b88 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -71,7 +71,7 @@
size_t numFrames = U32_AT(&vbriHeader[14]);
int64_t durationUs =
- numFrames * 1000000ll * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
+ numFrames * 1000000LL * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
ALOGV("duration = %.2f secs", durationUs / 1E6);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 2909a50..0441359 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -80,7 +80,8 @@
Vector<SidxEntry> &sidx,
const Trex *trex,
off64_t firstMoofOffset,
- const sp<ItemTable> &itemTable);
+ const sp<ItemTable> &itemTable,
+ int32_t elstShiftStartTicks);
virtual status_t init();
virtual media_status_t start();
@@ -109,7 +110,7 @@
off64_t mFirstMoofOffset;
off64_t mCurrentMoofOffset;
off64_t mNextMoofOffset;
- uint32_t mCurrentTime;
+ uint32_t mCurrentTime; // in media timescale ticks
int32_t mLastParsedTrackId;
int32_t mTrackId;
@@ -143,6 +144,10 @@
bool mIsHeif;
sp<ItemTable> mItemTable;
+ // Start offset from composition time to presentation time.
+ // Support shift only for video tracks through mElstShiftStartTicks for now.
+ int32_t mElstShiftStartTicks;
+
size_t parseNALSize(const uint8_t *data) const;
status_t parseChunk(off64_t *offset);
status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
@@ -338,6 +343,8 @@
case FOURCC('a', 'l', 'a', 'c'):
return MEDIA_MIMETYPE_AUDIO_ALAC;
+ case FOURCC('a', 'v', '0', '1'):
+ return MEDIA_MIMETYPE_VIDEO_AV1;
default:
ALOGW("Unknown fourcc: %c%c%c%c",
(fourcc >> 24) & 0xff,
@@ -459,11 +466,12 @@
[=] {
int64_t duration;
int32_t samplerate;
+ // Only for audio track.
if (track->has_elst && mHeaderTimescale != 0 &&
AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
- // elst has to be processed only the first time this function is called
+ // Elst has to be processed only the first time this function is called.
track->has_elst = false;
if (track->elst_segment_duration > INT64_MAX) {
@@ -479,67 +487,72 @@
halfscale, mHeaderTimescale, track->timescale);
if ((uint32_t)samplerate != track->timescale){
- ALOGV("samplerate:%" PRId32 ", track->timescale and samplerate are different!", samplerate);
+ ALOGV("samplerate:%" PRId32 ", track->timescale and samplerate are different!",
+ samplerate);
}
-
- int64_t delay;
- // delay = ((media_time * samplerate) + halfscale) / track->timescale;
- if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
- __builtin_add_overflow(delay, halfscale, &delay) ||
- (delay /= track->timescale, false) ||
- delay > INT32_MAX ||
- delay < INT32_MIN) {
- ALOGW("ignoring edit list with bogus values");
- return;
+ // Both delay and paddingsamples have to be set inorder for either to be
+ // effective in the lower layers.
+ int64_t delay = 0;
+ if (media_time > 0) { // Gapless playback
+ // delay = ((media_time * samplerate) + halfscale) / track->timescale;
+ if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
+ __builtin_add_overflow(delay, halfscale, &delay) ||
+ (delay /= track->timescale, false) ||
+ delay > INT32_MAX ||
+ delay < INT32_MIN) {
+ ALOGW("ignoring edit list with bogus values");
+ return;
+ }
}
ALOGV("delay = %" PRId64, delay);
AMediaFormat_setInt32(track->meta, AMEDIAFORMAT_KEY_ENCODER_DELAY, delay);
- int64_t scaled_duration;
- // scaled_duration = duration * mHeaderTimescale;
- if (__builtin_mul_overflow(duration, mHeaderTimescale, &scaled_duration)) {
- return;
- }
- ALOGV("scaled_duration = %" PRId64, scaled_duration);
-
- int64_t segment_end;
- int64_t padding;
- int64_t segment_duration_e6;
- int64_t media_time_scaled_e6;
- int64_t media_time_scaled;
- // padding = scaled_duration - ((segment_duration * 1000000) +
- // ((media_time * mHeaderTimeScale * 1000000)/track->timescale) )
- // segment_duration is based on timescale in movie header box(mdhd)
- // media_time is based on timescale track header/media timescale
- if (__builtin_mul_overflow(segment_duration, 1000000, &segment_duration_e6) ||
- __builtin_mul_overflow(media_time, mHeaderTimescale, &media_time_scaled) ||
- __builtin_mul_overflow(media_time_scaled, 1000000, &media_time_scaled_e6)) {
- return;
- }
- media_time_scaled_e6 /= track->timescale;
- if(__builtin_add_overflow(segment_duration_e6, media_time_scaled_e6, &segment_end) ||
- __builtin_sub_overflow(scaled_duration, segment_end, &padding)) {
- return;
- }
- ALOGV("segment_end = %" PRId64 ", padding = %" PRId64, segment_end, padding);
int64_t paddingsamples = 0;
- if (padding < 0) {
+ if (segment_duration > 0) {
+ int64_t scaled_duration;
+ // scaled_duration = duration * mHeaderTimescale;
+ if (__builtin_mul_overflow(duration, mHeaderTimescale, &scaled_duration)) {
+ return;
+ }
+ ALOGV("scaled_duration = %" PRId64, scaled_duration);
+
+ int64_t segment_end;
+ int64_t padding;
+ int64_t segment_duration_e6;
+ int64_t media_time_scaled_e6;
+ int64_t media_time_scaled;
+ // padding = scaled_duration - ((segment_duration * 1000000) +
+ // ((media_time * mHeaderTimescale * 1000000)/track->timescale) )
+ // segment_duration is based on timescale in movie header box(mdhd)
+ // media_time is based on timescale track header/media timescale
+ if (__builtin_mul_overflow(segment_duration, 1000000, &segment_duration_e6) ||
+ __builtin_mul_overflow(media_time, mHeaderTimescale, &media_time_scaled) ||
+ __builtin_mul_overflow(media_time_scaled, 1000000, &media_time_scaled_e6)) {
+ return;
+ }
+ media_time_scaled_e6 /= track->timescale;
+ if (__builtin_add_overflow(segment_duration_e6, media_time_scaled_e6, &segment_end)
+ || __builtin_sub_overflow(scaled_duration, segment_end, &padding)) {
+ return;
+ }
+ ALOGV("segment_end = %" PRId64 ", padding = %" PRId64, segment_end, padding);
// track duration from media header (which is what AMEDIAFORMAT_KEY_DURATION is)
// might be slightly shorter than the segment duration, which would make the
// padding negative. Clamp to zero.
- padding = 0;
- } else {
- int64_t halfscale_e6;
- int64_t timescale_e6;
- // paddingsamples = ((padding * samplerate) + (halfscale * 1000000))
- // / (mHeaderTimescale * 1000000);
- if (__builtin_mul_overflow(padding, samplerate, &paddingsamples) ||
- __builtin_mul_overflow(halfscale, 1000000, &halfscale_e6) ||
- __builtin_mul_overflow(mHeaderTimescale, 1000000, ×cale_e6) ||
- __builtin_add_overflow(paddingsamples, halfscale_e6, &paddingsamples) ||
- (paddingsamples /= timescale_e6, false) ||
- paddingsamples > INT32_MAX) {
- return;
+ if (padding > 0) {
+ int64_t halfscale_mht = mHeaderTimescale / 2;
+ int64_t halfscale_e6;
+ int64_t timescale_e6;
+ // paddingsamples = ((padding * samplerate) + (halfscale_mht * 1000000))
+ // / (mHeaderTimescale * 1000000);
+ if (__builtin_mul_overflow(padding, samplerate, &paddingsamples) ||
+ __builtin_mul_overflow(halfscale_mht, 1000000, &halfscale_e6) ||
+ __builtin_mul_overflow(mHeaderTimescale, 1000000, ×cale_e6) ||
+ __builtin_add_overflow(paddingsamples, halfscale_e6, &paddingsamples) ||
+ (paddingsamples /= timescale_e6, false) ||
+ paddingsamples > INT32_MAX) {
+ return;
+ }
}
}
ALOGV("paddingsamples = %" PRId64, paddingsamples);
@@ -668,6 +681,7 @@
track->includes_expensive_metadata = false;
track->skipTrack = false;
track->timescale = 1000000;
+ track->elstShiftStartTicks = 0;
}
}
@@ -965,6 +979,7 @@
AMEDIAFORMAT_KEY_MIME, "application/octet-stream");
track->has_elst = false;
track->subsample_encryption = false;
+ track->elstShiftStartTicks = 0;
}
off64_t stop_offset = *offset + chunk_size;
@@ -1092,6 +1107,7 @@
if (entry_count != 1) {
// we only support a single entry at the moment, for gapless playback
+ // or start offset
ALOGW("ignoring edit list with %d entries", entry_count);
} else {
off64_t entriesoffset = data_offset + 8;
@@ -1740,6 +1756,7 @@
case FOURCC('a', 'v', 'c', '1'):
case FOURCC('h', 'v', 'c', '1'):
case FOURCC('h', 'e', 'v', '1'):
+ case FOURCC('a', 'v', '0', '1'):
{
uint8_t buffer[78];
if (chunk_data_size < (ssize_t)sizeof(buffer)) {
@@ -3929,9 +3946,15 @@
}
}
+ if (track->has_elst and !strncasecmp("video/", mime, 6) and track->elst_media_time > 0) {
+ track->elstShiftStartTicks = track->elst_media_time;
+ ALOGV("video track->elstShiftStartTicks :%" PRId64, track->elst_media_time);
+ }
+
MPEG4Source *source = new MPEG4Source(
track->meta, mDataSource, track->timescale, track->sampleTable,
- mSidxEntries, trex, mMoofOffset, itemTable);
+ mSidxEntries, trex, mMoofOffset, itemTable,
+ track->elstShiftStartTicks);
if (source->init() != OK) {
delete source;
return NULL;
@@ -4332,7 +4355,8 @@
Vector<SidxEntry> &sidx,
const Trex *trex,
off64_t firstMoofOffset,
- const sp<ItemTable> &itemTable)
+ const sp<ItemTable> &itemTable,
+ int32_t elstShiftStartTicks)
: mFormat(format),
mDataSource(dataSource),
mTimescale(timeScale),
@@ -4360,7 +4384,8 @@
mBuffer(NULL),
mSrcBuffer(NULL),
mIsHeif(itemTable != NULL),
- mItemTable(itemTable) {
+ mItemTable(itemTable),
+ mElstShiftStartTicks(elstShiftStartTicks) {
memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
@@ -4445,11 +4470,31 @@
}
status_t MPEG4Source::init() {
+ status_t err = OK;
+ const char *mime;
+ CHECK(AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime));
if (mFirstMoofOffset != 0) {
off64_t offset = mFirstMoofOffset;
- return parseChunk(&offset);
+ err = parseChunk(&offset);
+ if(err == OK && !strncasecmp("video/", mime, 6)
+ && !mCurrentSamples.isEmpty()) {
+ // Start offset should be less or equal to composition time of first sample.
+ // ISO : sample_composition_time_offset, version 0 (unsigned) for major brands.
+ mElstShiftStartTicks = std::min(mElstShiftStartTicks,
+ (*mCurrentSamples.begin()).compositionOffset);
+ }
+ return err;
}
- return OK;
+
+ if (!strncasecmp("video/", mime, 6)) {
+ uint32_t firstSampleCTS = 0;
+ err = mSampleTable->getMetaDataForSample(0, NULL, NULL, &firstSampleCTS);
+ // Start offset should be less or equal to composition time of first sample.
+ // Composition time stamp of first sample cannot be negative.
+ mElstShiftStartTicks = std::min(mElstShiftStartTicks, (int32_t)firstSampleCTS);
+ }
+
+ return err;
}
MPEG4Source::~MPEG4Source() {
@@ -4990,7 +5035,7 @@
status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
- ALOGV("MPEG4Extractor::parseTrackFragmentRun");
+ ALOGV("MPEG4Source::parseTrackFragmentRun");
if (size < 8) {
return -EINVAL;
}
@@ -5132,10 +5177,10 @@
}
ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
- " flags 0x%08x", i + 1,
+ " flags 0x%08x ctsOffset %" PRIu32, i + 1,
dataOffset, sampleSize, sampleDuration,
(flags & kFirstSampleFlagsPresent) && i == 0
- ? firstSampleFlags : sampleFlags);
+ ? firstSampleFlags : sampleFlags, sampleCtsOffset);
tmp.offset = dataOffset;
tmp.size = sampleSize;
tmp.duration = sampleDuration;
@@ -5227,6 +5272,7 @@
int64_t seekTimeUs;
ReadOptions::SeekMode mode;
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+
if (mIsHeif) {
CHECK(mSampleTable == NULL);
CHECK(mItemTable != NULL);
@@ -5264,6 +5310,9 @@
CHECK(!"Should not be here.");
break;
}
+ if( mode != ReadOptions::SEEK_FRAME_INDEX) {
+ seekTimeUs += ((int64_t)mElstShiftStartTicks * 1000000) / mTimescale;
+ }
uint32_t sampleIndex;
status_t err = mSampleTable->findSampleAtTime(
@@ -5305,6 +5354,7 @@
if (mode == ReadOptions::SEEK_CLOSEST
|| mode == ReadOptions::SEEK_FRAME_INDEX) {
+ sampleTime -= mElstShiftStartTicks;
targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
}
@@ -5343,6 +5393,10 @@
if (!mIsHeif) {
err = mSampleTable->getMetaDataForSample(
mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
+ if(err == OK) {
+ cts -= mElstShiftStartTicks;
+ }
+
} else {
err = mItemTable->getImageOffsetAndSize(
options && options->getSeekTo(&seekTimeUs, &mode) ?
@@ -5623,6 +5677,10 @@
ReadOptions::SeekMode mode;
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ seekTimeUs += ((int64_t)mElstShiftStartTicks * 1000000) / mTimescale;
+ ALOGV("shifted seekTimeUs :%" PRId64 ", mElstShiftStartTicks:%" PRId32, seekTimeUs,
+ mElstShiftStartTicks);
+
int numSidxEntries = mSegments.size();
if (numSidxEntries != 0) {
int64_t totalTime = 0;
@@ -5709,6 +5767,8 @@
offset = smpl->offset;
size = smpl->size;
cts = mCurrentTime + smpl->compositionOffset;
+ cts -= mElstShiftStartTicks;
+
mCurrentTime += smpl->duration;
isSyncSample = (mCurrentSampleIndex == 0);
@@ -5960,6 +6020,7 @@
FOURCC('a', 'v', 'c', '1'),
FOURCC('h', 'v', 'c', '1'),
FOURCC('h', 'e', 'v', '1'),
+ FOURCC('a', 'v', '0', '1'),
FOURCC('3', 'g', 'p', '4'),
FOURCC('m', 'p', '4', '1'),
FOURCC('m', 'p', '4', '2'),
@@ -6122,6 +6183,19 @@
return NULL;
}
+static const char *extensions[] = {
+ "3g2",
+ "3gp",
+ "3gpp",
+ "3gpp2",
+ "m4a",
+ "m4r",
+ "m4v",
+ "mov",
+ "mp4",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -6131,7 +6205,7 @@
UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
2, // version
"MP4 Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 79d5ff6dd..fadfb50 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -85,6 +85,7 @@
bool has_elst;
int64_t elst_media_time;
uint64_t elst_segment_duration;
+ int32_t elstShiftStartTicks;
bool subsample_encryption;
};
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index 2f4196c..946a2a9 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <media/MediaExtractorPluginHelper.h>
+#include <media/stagefright/MediaDefs.h>
#include "MPEG2PSExtractor.h"
#include "MPEG2TSExtractor.h"
@@ -26,6 +27,12 @@
struct CDataSource;
+static const char *extensions[] = {
+ "m2p",
+ "ts",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -36,26 +43,29 @@
1,
"MPEG2-PS/TS Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffMPEG2TS(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
- } else if (SniffMPEG2PS(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffMPEG2TS(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
+ } else if (SniffMPEG2PS(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 554d252..731584d 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -734,6 +734,9 @@
if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
}
+ if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+ AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+ }
mbuf->release();
return AMEDIA_OK;
}
@@ -790,6 +793,7 @@
}
media_status_t MPEG2PSExtractor::WrappedTrack::start() {
+ mTrack->mBufferGroup = mBufferGroup;
return mTrack->start();
}
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 3bb2af7..e1509ee 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -224,6 +224,9 @@
if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
}
+ if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+ AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+ }
mbuf->release();
return AMEDIA_OK;
}
@@ -373,7 +376,7 @@
}
// Wait only for 2 seconds to detect audio/video streams.
- if (ALooper::GetNowUs() - startTime > 2000000ll) {
+ if (ALooper::GetNowUs() - startTime > 2000000LL) {
break;
}
}
@@ -385,7 +388,7 @@
List<int64_t> durations;
// Estimate duration --- stabilize until you get <500ms deviation.
while (feedMore() == OK
- && ALooper::GetNowUs() - startTime <= 2000000ll) {
+ && ALooper::GetNowUs() - startTime <= 2000000LL) {
if (mSeekSyncPoints->size() > prevSyncSize) {
prevSyncSize = mSeekSyncPoints->size();
int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index c3914f1..6efbfee 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -872,7 +872,7 @@
ALOGV("readPage returned %zd", n);
- return n < 0 ? (media_status_t) n : AMEDIA_ERROR_END_OF_STREAM;
+ return n == ERROR_END_OF_STREAM ? AMEDIA_ERROR_END_OF_STREAM : AMEDIA_ERROR_UNKNOWN;
}
// Prevent a harmless unsigned integer overflow by clamping to 0
@@ -1379,6 +1379,12 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "oga",
+ "ogg",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -1388,7 +1394,7 @@
UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
1, // version
"Ogg Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 6f9f689..e58bd1f 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -616,6 +616,11 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "wav",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -625,7 +630,7 @@
UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
1, // version
"WAV Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index d1f7525..9601d6d 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -22,6 +22,22 @@
namespace android {
//
+// AudioDeviceTypeAddr implementation
+//
+status_t AudioDeviceTypeAddr::readFromParcel(Parcel *parcel) {
+ mType = (audio_devices_t) parcel->readInt32();
+ mAddress = parcel->readString8();
+ return NO_ERROR;
+}
+
+status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32((int32_t) mType);
+ parcel->writeString8(mAddress);
+ return NO_ERROR;
+}
+
+
+//
// AudioMixMatchCriterion implementation
//
AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
@@ -40,11 +56,22 @@
status_t AudioMixMatchCriterion::readFromParcel(Parcel *parcel)
{
mRule = parcel->readInt32();
- if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
- mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
- mValue.mUsage = (audio_usage_t)parcel->readInt32();
- } else {
- mValue.mSource = (audio_source_t)parcel->readInt32();
+ switch (mRule) {
+ case RULE_MATCH_ATTRIBUTE_USAGE:
+ case RULE_EXCLUDE_ATTRIBUTE_USAGE:
+ mValue.mUsage = (audio_usage_t) parcel->readInt32();
+ break;
+ case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+ case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
+ mValue.mSource = (audio_source_t) parcel->readInt32();
+ break;
+ case RULE_MATCH_UID:
+ case RULE_EXCLUDE_UID:
+ mValue.mUid = (uid_t) parcel->readInt32();
+ break;
+ default:
+ ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
+ return BAD_VALUE;
}
return NO_ERROR;
}
@@ -116,4 +143,11 @@
return NO_ERROR;
}
+void AudioMix::excludeUid(uid_t uid) const {
+ AudioMixMatchCriterion crit;
+ crit.mRule = RULE_EXCLUDE_UID;
+ crit.mValue.mUid = uid;
+ mCriteria.add(crit);
+}
+
} // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index dc7531c..baeae8b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1236,6 +1236,19 @@
return aps->registerPolicyMixes(mixes, registration);
}
+status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setUidDeviceAffinities(uid, devices);
+}
+
+status_t AudioSystem::removeUidDeviceAffinities(uid_t uid) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->removeUidDeviceAffinities(uid);
+}
+
status_t AudioSystem::startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId)
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 0ce8b16..272415c 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -90,6 +90,8 @@
SET_ASSISTANT_UID,
SET_A11Y_SERVICES_UIDS,
IS_HAPTIC_PLAYBACK_SUPPORTED,
+ SET_UID_DEVICE_AFFINITY,
+ REMOVE_UID_DEVICE_AFFINITY,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -990,6 +992,50 @@
return reply.readBool();
}
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) uid);
+ size_t size = devices.size();
+ size_t sizePosition = data.dataPosition();
+ data.writeInt32((int32_t) size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = data.dataPosition();
+ if (devices[i].writeToParcel(&data) != NO_ERROR) {
+ data.setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = data.dataPosition();
+ data.setDataPosition(sizePosition);
+ data.writeInt32(finalSize);
+ data.setDataPosition(position);
+ }
+
+ status_t status = remote()->transact(SET_UID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t removeUidDeviceAffinities(uid_t uid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) uid);
+
+ status_t status = remote()->transact(REMOVE_UID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1048,7 +1094,9 @@
case GET_SURROUND_FORMATS:
case SET_SURROUND_FORMAT_ENABLED:
case SET_ASSISTANT_UID:
- case SET_A11Y_SERVICES_UIDS: {
+ case SET_A11Y_SERVICES_UIDS:
+ case SET_UID_DEVICE_AFFINITY:
+ case REMOVE_UID_DEVICE_AFFINITY: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1811,6 +1859,30 @@
CHECK_INTERFACE(IAudioPolicyService, data, reply);
bool isSupported = isHapticPlaybackSupported();
reply->writeBool(isSupported);
+ return NO_ERROR;
+ }
+
+ case SET_UID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const uid_t uid = (uid_t) data.readInt32();
+ Vector<AudioDeviceTypeAddr> devices;
+ size_t size = (size_t)data.readInt32();
+ for (size_t i = 0; i < size; i++) {
+ AudioDeviceTypeAddr device;
+ if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
+ devices.add(device);
+ }
+ }
+ status_t status = setUidDeviceAffinities(uid, devices);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case REMOVE_UID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const uid_t uid = (uid_t) data.readInt32();
+ status_t status = removeUidDeviceAffinities(uid);
+ reply->writeInt32(status);
return NO_ERROR;
}
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 8da0069..96e1235 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -56,6 +56,19 @@
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20
+class AudioDeviceTypeAddr {
+public:
+ AudioDeviceTypeAddr() {}
+ AudioDeviceTypeAddr(audio_devices_t type, String8 address) :
+ mType(type), mAddress(address) {}
+
+ status_t readFromParcel(Parcel *parcel);
+ status_t writeToParcel(Parcel *parcel) const;
+
+ audio_devices_t mType;
+ String8 mAddress;
+};
+
class AudioMixMatchCriterion {
public:
AudioMixMatchCriterion() {}
@@ -87,7 +100,9 @@
status_t readFromParcel(Parcel *parcel);
status_t writeToParcel(Parcel *parcel) const;
- Vector<AudioMixMatchCriterion> mCriteria;
+ void excludeUid(uid_t uid) const;
+
+ mutable Vector<AudioMixMatchCriterion> mCriteria;
uint32_t mMixType;
audio_config_t mFormat;
uint32_t mRouteFlags;
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index b0da5b8..781e9df 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -325,6 +325,10 @@
static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
+ static status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+
+ static status_t removeUidDeviceAffinities(uid_t uid);
+
static status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 61f3b27..fb4fe93 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -167,6 +167,11 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration) = 0;
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ = 0;
+
+ virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId) = 0;
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 2567b3b..86711de 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -302,14 +302,19 @@
if (audio_channel_mask_get_representation(channelMask)
== AUDIO_CHANNEL_REPRESENTATION_POSITION
&& DownmixerBufferProvider::isMultichannelCapable()) {
- mDownmixerBufferProvider.reset(new DownmixerBufferProvider(channelMask,
- mMixerChannelMask,
- AUDIO_FORMAT_PCM_16_BIT /* TODO: use mMixerInFormat, now only PCM 16 */,
- sampleRate, sessionId, kCopyBufferFrameCount));
- if (static_cast<DownmixerBufferProvider *>(mDownmixerBufferProvider.get())->isValid()) {
- mDownmixRequiresFormat = AUDIO_FORMAT_PCM_16_BIT; // PCM 16 bit required for downmix
- reconfigureBufferProviders();
- return NO_ERROR;
+
+ // Check if we have a float or int16 downmixer, in that order.
+ for (const audio_format_t format : { AUDIO_FORMAT_PCM_FLOAT, AUDIO_FORMAT_PCM_16_BIT }) {
+ mDownmixerBufferProvider.reset(new DownmixerBufferProvider(
+ channelMask, mMixerChannelMask,
+ format,
+ sampleRate, sessionId, kCopyBufferFrameCount));
+ if (static_cast<DownmixerBufferProvider *>(mDownmixerBufferProvider.get())
+ ->isValid()) {
+ mDownmixRequiresFormat = format;
+ reconfigureBufferProviders();
+ return NO_ERROR;
+ }
}
// mDownmixerBufferProvider reset below.
}
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index 227f2a1..9c82b1d 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -13,7 +13,7 @@
relative_install_path: "soundfx",
cflags: [
- //"-DBUILD_FLOAT",
+ "-DBUILD_FLOAT",
"-fvisibility=hidden",
"-Wall",
"-Werror",
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index b4a1d77..99ac4f5 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -31,10 +31,12 @@
// Do not submit with DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER defined, strictly for testing
//#define DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER 0
-#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
-
#ifdef BUILD_FLOAT
#define MINUS_3_DB_IN_FLOAT 0.70710678f // -3dB = 0.70710678f
+const audio_format_t gTargetFormat = AUDIO_FORMAT_PCM_FLOAT;
+#else
+#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
+const audio_format_t gTargetFormat = AUDIO_FORMAT_PCM_16_BIT;
#endif
// subset of possible audio_channel_mask_t values, and AUDIO_CHANNEL_OUT_* renamed to CHANNEL_MASK_*
@@ -703,7 +705,7 @@
memset(&pDwmModule->context, 0, sizeof(downmix_object_t));
pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
- pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pDwmModule->config.inputCfg.format = gTargetFormat;
pDwmModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
pDwmModule->config.inputCfg.bufferProvider.getBuffer = NULL;
pDwmModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
@@ -715,7 +717,7 @@
// set a default value for the access mode, but should be overwritten by caller
pDwmModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
- pDwmModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pDwmModule->config.outputCfg.format = gTargetFormat;
pDwmModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
pDwmModule->config.outputCfg.bufferProvider.getBuffer = NULL;
pDwmModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
@@ -762,8 +764,8 @@
// Check configuration compatibility with build options, and effect capabilities
if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate
|| pConfig->outputCfg.channels != DOWNMIX_OUTPUT_CHANNELS
- || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT
- || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ || pConfig->inputCfg.format != gTargetFormat
+ || pConfig->outputCfg.format != gTargetFormat) {
ALOGE("Downmix_Configure error: invalid config");
return -EINVAL;
}
@@ -1185,8 +1187,8 @@
if (accumulate) {
while (numFrames) {
// centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
- centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
- + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+ centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
+ + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
// FL + centerPlusLfeContrib + SL + RL
lt = pSrc[0] + centerPlusLfeContrib + pSrc[6] + pSrc[4];
// FR + centerPlusLfeContrib + SR + RR
@@ -1427,4 +1429,4 @@
}
return true;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index b5860de..0c6f8de 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1544,7 +1544,7 @@
int VirtualizerIsConfigurationSupported(audio_channel_mask_t channelMask,
audio_devices_t deviceType) {
uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
- if (channelCount < 1 || channelCount > LVM_MAX_CHANNELS) {
+ if (channelCount < 1 || channelCount > FCC_2) { // TODO: update to 8 channels when supported.
return -EINVAL;
}
return VirtualizerIsDeviceSupported(deviceType);
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 6002e95..7d759e0 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -216,8 +216,7 @@
"libutils",
"libbinder",
"libsonivox",
- "libicuuc",
- "libicui18n",
+ "libandroidicu",
"libexpat",
"libcamera_client",
"libstagefright_foundation",
@@ -232,8 +231,7 @@
export_shared_lib_headers: [
"libaudioclient",
"libbinder",
- "libicuuc",
- "libicui18n",
+ "libandroidicu",
"libsonivox",
"libmedia_omx",
],
diff --git a/media/libmedia/IMediaExtractorService.cpp b/media/libmedia/IMediaExtractorService.cpp
index 0295abc..243b09d 100644
--- a/media/libmedia/IMediaExtractorService.cpp
+++ b/media/libmedia/IMediaExtractorService.cpp
@@ -29,6 +29,7 @@
enum {
MAKE_EXTRACTOR = IBinder::FIRST_CALL_TRANSACTION,
MAKE_IDATA_SOURCE_FD,
+ GET_SUPPORTED_TYPES,
};
class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
@@ -68,6 +69,24 @@
}
return nullptr;
}
+
+ virtual std::unordered_set<std::string> getSupportedTypes() {
+ std::unordered_set<std::string> supportedTypes;
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
+ status_t ret = remote()->transact(GET_SUPPORTED_TYPES, data, &reply);
+ if (ret == NO_ERROR) {
+ // process reply
+ while(true) {
+ const char *ext = reply.readCString();
+ if (!ext) {
+ break;
+ }
+ supportedTypes.insert(std::string(ext));
+ }
+ }
+ return supportedTypes;
+ }
};
IMPLEMENT_META_INTERFACE(MediaExtractorService, "android.media.IMediaExtractorService");
@@ -113,6 +132,15 @@
return NO_ERROR;
}
+ case GET_SUPPORTED_TYPES:
+ {
+ CHECK_INTERFACE(IMediaExtractorService, data, reply);
+ std::unordered_set<std::string> supportedTypes = getSupportedTypes();
+ for (auto it = supportedTypes.begin(); it != supportedTypes.end(); ++it) {
+ reply->writeCString((*it).c_str());
+ }
+ return NO_ERROR;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index eed96e7..6dbc9b8 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -57,6 +57,10 @@
AMEDIAFORMAT_KEY_COLOR_STANDARD,
AMEDIAFORMAT_KEY_COLOR_TRANSFER,
AMEDIAFORMAT_KEY_COMPLEXITY,
+ AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE,
+ AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK,
+ AMEDIAFORMAT_KEY_CRYPTO_MODE,
+ AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK,
AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL,
AMEDIAFORMAT_KEY_GRID_COLUMNS,
AMEDIAFORMAT_KEY_GRID_ROWS,
@@ -102,6 +106,8 @@
};
static const char *AMediaFormatKeyGroupBuffer[] = {
+ AMEDIAFORMAT_KEY_CRYPTO_IV,
+ AMEDIAFORMAT_KEY_CRYPTO_KEY,
AMEDIAFORMAT_KEY_HDR_STATIC_INFO,
AMEDIAFORMAT_KEY_SEI,
AMEDIAFORMAT_KEY_MPEG_USER_DATA,
@@ -1243,7 +1249,11 @@
if (mAMediaExtractor == NULL) {
return NULL;
}
- return new AMediaCodecCryptoInfoWrapper(AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor));
+ AMediaCodecCryptoInfo *cryptoInfo = AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor);
+ if (cryptoInfo == NULL) {
+ return NULL;
+ }
+ return new AMediaCodecCryptoInfoWrapper(cryptoInfo);
}
AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
diff --git a/media/libmedia/include/media/IMediaExtractorService.h b/media/libmedia/include/media/IMediaExtractorService.h
index 45e9620..5ce2cdb 100644
--- a/media/libmedia/include/media/IMediaExtractorService.h
+++ b/media/libmedia/include/media/IMediaExtractorService.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_IMEDIAEXTRACTORSERVICE_H
#define ANDROID_IMEDIAEXTRACTORSERVICE_H
+#include <unordered_set>
+
#include <binder/IInterface.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
@@ -33,6 +35,8 @@
virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) = 0;
virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length) = 0;
+
+ virtual std::unordered_set<std::string> getSupportedTypes() = 0;
};
class BnMediaExtractorService: public BnInterface<IMediaExtractorService>
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index caa0186..33be559 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -115,9 +115,6 @@
* The state machine of the media_recorder.
*/
enum media_recorder_states {
- // Error state.
- MEDIA_RECORDER_ERROR = 0,
-
// Recorder was just created.
MEDIA_RECORDER_IDLE = 1 << 0,
@@ -132,6 +129,9 @@
// Recording is in progress.
MEDIA_RECORDER_RECORDING = 1 << 4,
+
+ // Error state.
+ MEDIA_RECORDER_ERROR = 1 << 5,
};
// The "msg" code passed to the listener in notify.
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index 6b43375..38f42dc 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -16,6 +16,7 @@
"libandroid_runtime",
"libaudioclient",
"libbinder",
+ "libbinder_ndk",
"libcutils",
"libgui",
"liblog",
@@ -91,18 +92,15 @@
"JMedia2HTTPConnection.cpp",
],
+ header_libs: [
+ "libbinder_headers",
+ "libnativehelper_header_only",
+ ],
+
shared_libs: [
- "android.hidl.token@1.0-utils",
"liblog",
- "libcutils",
"libutils",
- "libbinder",
- "libstagefright_foundation",
- "libmediaextractor",
"libdl",
- "libaudioutils",
- "libaudioclient",
- "libnativehelper",
],
include_dirs: [
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
index 5e98589..0c8d016 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
@@ -30,7 +30,6 @@
#include <media/AudioSystem.h>
#include <media/AudioTimestamp.h>
#include <media/BufferingSettings.h>
-#include <media/Metadata.h>
#include <media/stagefright/foundation/AHandler.h>
#include <mediaplayer2/MediaPlayer2Types.h>
@@ -224,18 +223,6 @@
// @return OK if the call was successful.
virtual status_t invoke(const PlayerMessage &request, PlayerMessage *reply) = 0;
- // The Client in the MetadataPlayerService calls this method on
- // the native player to retrieve all or a subset of metadata.
- //
- // @param ids SortedList of metadata ID to be fetch. If empty, all
- // the known metadata should be returned.
- // @param[inout] records Parcel where the player appends its metadata.
- // @return OK if the call was successful.
- virtual status_t getMetadata(const media::Metadata::Filter& /* ids */,
- Parcel* /* records */) {
- return INVALID_OPERATION;
- };
-
void setListener(const sp<MediaPlayer2InterfaceListener> &listener) {
Mutex::Autolock autoLock(mListenerLock);
mListener = listener;
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index a945ffd..78865c4 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -20,7 +20,6 @@
#include <media/AVSyncSettings.h>
#include <media/AudioResamplerPublic.h>
#include <media/BufferingSettings.h>
-#include <media/Metadata.h>
#include <media/mediaplayer_common.h>
#include <mediaplayer2/MediaPlayer2Interface.h>
#include <mediaplayer2/MediaPlayer2Types.h>
@@ -55,7 +54,7 @@
public:
~MediaPlayer2();
- static sp<MediaPlayer2> Create(int32_t sessionId);
+ static sp<MediaPlayer2> Create(int32_t sessionId, jobject context);
static status_t DumpAll(int fd, const Vector<String16>& args);
void disconnect();
@@ -118,7 +117,7 @@
status_t dump(int fd, const Vector<String16>& args);
private:
- MediaPlayer2(int32_t sessionId);
+ MediaPlayer2(int32_t sessionId, jobject context);
bool init();
// Disconnect from the currently connected ANativeWindow.
@@ -154,6 +153,7 @@
int mVideoHeight;
int32_t mAudioSessionId;
sp<JObjectHolder> mAudioAttributes;
+ sp<JObjectHolder> mContext;
float mSendLevel;
sp<ANativeWindowWrapper> mConnectedWindow;
};
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index f432059..f75380c 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -18,14 +18,11 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaPlayer2Native"
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-
+#include <android/binder_ibinder.h>
#include <media/AudioSystem.h>
#include <media/DataSourceDesc.h>
#include <media/MediaAnalyticsItem.h>
#include <media/MemoryLeakTrackUtil.h>
-#include <media/Metadata.h>
#include <media/NdkWrapper.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooperRoster.h>
@@ -103,114 +100,110 @@
String8 result;
SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- snprintf(buffer, SIZE, "Permission Denial: can't dump MediaPlayer2\n");
- result.append(buffer);
+ {
+ Mutex::Autolock lock(sRecordLock);
+ ensureInit_l();
+ for (int i = 0, n = sPlayers->size(); i < n; ++i) {
+ sp<MediaPlayer2> p = (*sPlayers)[i].promote();
+ if (p != 0) {
+ p->dump(fd, args);
+ }
+ players.add(p);
+ }
+ }
+
+ result.append(" Files opened and/or mapped:\n");
+ snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
+ FILE *f = fopen(buffer, "r");
+ if (f) {
+ while (!feof(f)) {
+ fgets(buffer, SIZE, f);
+ if (strstr(buffer, " /storage/") ||
+ strstr(buffer, " /system/sounds/") ||
+ strstr(buffer, " /data/") ||
+ strstr(buffer, " /system/media/")) {
+ result.append(" ");
+ result.append(buffer);
+ }
+ }
+ fclose(f);
} else {
- {
- Mutex::Autolock lock(sRecordLock);
- ensureInit_l();
- for (int i = 0, n = sPlayers->size(); i < n; ++i) {
- sp<MediaPlayer2> p = (*sPlayers)[i].promote();
- if (p != 0) {
- p->dump(fd, args);
- }
- players.add(p);
- }
- }
+ result.append("couldn't open ");
+ result.append(buffer);
+ result.append("\n");
+ }
- result.append(" Files opened and/or mapped:\n");
- snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
- FILE *f = fopen(buffer, "r");
- if (f) {
- while (!feof(f)) {
- fgets(buffer, SIZE, f);
- if (strstr(buffer, " /storage/") ||
- strstr(buffer, " /system/sounds/") ||
- strstr(buffer, " /data/") ||
- strstr(buffer, " /system/media/")) {
- result.append(" ");
- result.append(buffer);
- }
- }
- fclose(f);
- } else {
- result.append("couldn't open ");
- result.append(buffer);
- result.append("\n");
- }
-
- snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
- DIR *d = opendir(buffer);
- if (d) {
- struct dirent *ent;
- while((ent = readdir(d)) != NULL) {
- if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
- snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
- struct stat s;
- if (lstat(buffer, &s) == 0) {
- if ((s.st_mode & S_IFMT) == S_IFLNK) {
- char linkto[256];
- int len = readlink(buffer, linkto, sizeof(linkto));
- if(len > 0) {
- if(len > 255) {
- linkto[252] = '.';
- linkto[253] = '.';
- linkto[254] = '.';
- linkto[255] = 0;
- } else {
- linkto[len] = 0;
- }
- if (strstr(linkto, "/storage/") == linkto ||
- strstr(linkto, "/system/sounds/") == linkto ||
- strstr(linkto, "/data/") == linkto ||
- strstr(linkto, "/system/media/") == linkto) {
- result.append(" ");
- result.append(buffer);
- result.append(" -> ");
- result.append(linkto);
- result.append("\n");
- }
+ snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
+ DIR *d = opendir(buffer);
+ if (d) {
+ struct dirent *ent;
+ while((ent = readdir(d)) != NULL) {
+ if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
+ snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
+ struct stat s;
+ if (lstat(buffer, &s) == 0) {
+ if ((s.st_mode & S_IFMT) == S_IFLNK) {
+ char linkto[256];
+ int len = readlink(buffer, linkto, sizeof(linkto));
+ if(len > 0) {
+ if(len > 255) {
+ linkto[252] = '.';
+ linkto[253] = '.';
+ linkto[254] = '.';
+ linkto[255] = 0;
+ } else {
+ linkto[len] = 0;
}
- } else {
- result.append(" unexpected type for ");
- result.append(buffer);
- result.append("\n");
+ if (strstr(linkto, "/storage/") == linkto ||
+ strstr(linkto, "/system/sounds/") == linkto ||
+ strstr(linkto, "/data/") == linkto ||
+ strstr(linkto, "/system/media/") == linkto) {
+ result.append(" ");
+ result.append(buffer);
+ result.append(" -> ");
+ result.append(linkto);
+ result.append("\n");
+ }
}
+ } else {
+ result.append(" unexpected type for ");
+ result.append(buffer);
+ result.append("\n");
}
}
}
- closedir(d);
- } else {
- result.append("couldn't open ");
- result.append(buffer);
- result.append("\n");
}
+ closedir(d);
+ } else {
+ result.append("couldn't open ");
+ result.append(buffer);
+ result.append("\n");
+ }
- gLooperRoster.dump(fd, args);
+ gLooperRoster.dump(fd, args);
- bool dumpMem = false;
- bool unreachableMemory = false;
- for (size_t i = 0; i < args.size(); i++) {
- if (args[i] == String16("-m")) {
- dumpMem = true;
- } else if (args[i] == String16("--unreachable")) {
- unreachableMemory = true;
- }
- }
- if (dumpMem) {
- result.append("\nDumping memory:\n");
- std::string s = dumpMemoryAddresses(100 /* limit */);
- result.append(s.c_str(), s.size());
- }
- if (unreachableMemory) {
- result.append("\nDumping unreachable memory:\n");
- // TODO - should limit be an argument parameter?
- // TODO: enable GetUnreachableMemoryString if it's part of stable API
- //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
- //result.append(s.c_str(), s.size());
+ bool dumpMem = false;
+ bool unreachableMemory = false;
+ for (size_t i = 0; i < args.size(); i++) {
+ if (args[i] == String16("-m")) {
+ dumpMem = true;
+ } else if (args[i] == String16("--unreachable")) {
+ unreachableMemory = true;
}
}
+ if (dumpMem) {
+ result.append("\nDumping memory:\n");
+ std::string s = dumpMemoryAddresses(100 /* limit */);
+ result.append(s.c_str(), s.size());
+ }
+ if (unreachableMemory) {
+ result.append("\nDumping unreachable memory:\n");
+ // TODO - should limit be an argument parameter?
+ // TODO: enable GetUnreachableMemoryString if it's part of stable API
+ //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
+ //result.append(s.c_str(), s.size());
+ }
+
write(fd, result.string(), result.size());
return NO_ERROR;
}
@@ -218,8 +211,8 @@
} // anonymous namespace
//static
-sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId) {
- sp<MediaPlayer2> player = new MediaPlayer2(sessionId);
+sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId, jobject context) {
+ sp<MediaPlayer2> player = new MediaPlayer2(sessionId, context);
if (!player->init()) {
return NULL;
@@ -236,13 +229,14 @@
return dumpPlayers(fd, args);
}
-MediaPlayer2::MediaPlayer2(int32_t sessionId) {
+MediaPlayer2::MediaPlayer2(int32_t sessionId, jobject context) {
ALOGV("constructor");
mSrcId = 0;
mLockThreadId = 0;
mListener = NULL;
mStreamType = AUDIO_STREAM_MUSIC;
mAudioAttributes = NULL;
+ mContext = new JObjectHolder(context);
mCurrentPosition = -1;
mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
mSeekPosition = -1;
@@ -253,9 +247,8 @@
mVideoWidth = mVideoHeight = 0;
mSendLevel = 0;
- // TODO: get pid and uid from JAVA
- mPid = IPCThreadState::self()->getCallingPid();
- mUid = IPCThreadState::self()->getCallingUid();
+ mPid = AIBinder_getCallingPid();
+ mUid = AIBinder_getCallingUid();
mAudioOutput = new MediaPlayer2AudioOutput(sessionId, mUid, mPid, NULL /*attributes*/);
}
@@ -334,15 +327,15 @@
sp<MediaPlayer2Interface> oldPlayer;
- Mutex::Autolock _l(mLock);
{
+ Mutex::Autolock _l(mLock);
if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
|| mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
ALOGE("setDataSource called in wrong state %d", mCurrentState);
return INVALID_OPERATION;
}
- sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
+ sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid, mContext);
status_t err = player->initCheck();
if (err != NO_ERROR) {
ALOGE("Failed to create player object, initCheck failed(%d)", err);
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index f01361b..9552580 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -1286,6 +1286,11 @@
mVideoTimeUs = timeUs;
}
+ sp<AMediaCodecCryptoInfoWrapper> cryptInfo = extractor->getSampleCryptoInfo();
+ if (cryptInfo != NULL) {
+ meta->setObject("cryptInfo", cryptInfo);
+ }
+
queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
if (numBuffers == 0 && actualTimeUs != nullptr) {
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
index c9a1071..983d77e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
@@ -20,55 +20,50 @@
#include "JWakeLock.h"
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
#include <media/stagefright/foundation/ADebug.h>
-#include <powermanager/PowerManager.h>
-
namespace android {
-//TODO: use JAVA PowerManager, instead of binder
-JWakeLock::JWakeLock() :
- mPowerManager(NULL),
- mWakeLockToken(NULL),
+JWakeLock::JWakeLock(const sp<JObjectHolder> &context) :
mWakeLockCount(0),
- mDeathRecipient(new PMDeathRecipient(this)) {}
+ mWakeLock(NULL),
+ mContext(context) {}
JWakeLock::~JWakeLock() {
- if (mPowerManager != NULL) {
- sp<IBinder> binder = IInterface::asBinder(mPowerManager);
- binder->unlinkToDeath(mDeathRecipient);
- }
- clearPowerManager();
+ clearJavaWakeLock();
}
bool JWakeLock::acquire() {
if (mWakeLockCount == 0) {
- CHECK(mWakeLockToken == NULL);
- if (mPowerManager == NULL) {
- // use checkService() to avoid blocking if power service is not up yet
- sp<IBinder> binder =
- defaultServiceManager()->checkService(String16("power"));
- if (binder == NULL) {
- ALOGW("could not get the power manager service");
- } else {
- mPowerManager = interface_cast<IPowerManager>(binder);
- binder->linkToDeath(mDeathRecipient);
- }
+ if (mWakeLock == NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass jContextCls = env->FindClass("android/content/Context");
+ jclass jPowerManagerCls = env->FindClass("android/os/PowerManager");
+
+ jmethodID jGetSystemService = env->GetMethodID(jContextCls,
+ "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+ jobject javaPowerManagerObj = env->CallObjectMethod(mContext->getJObject(),
+ jGetSystemService, env->NewStringUTF("power"));
+
+ jfieldID jPARTIAL_WAKE_LOCK = env->GetStaticFieldID(jPowerManagerCls,
+ "PARTIAL_WAKE_LOCK", "I");
+ jint PARTIAL_WAKE_LOCK = env->GetStaticIntField(jPowerManagerCls, jPARTIAL_WAKE_LOCK);
+
+ jmethodID jNewWakeLock = env->GetMethodID(jPowerManagerCls,
+ "newWakeLock", "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;");
+ jobject javaWakeLock = env->CallObjectMethod(javaPowerManagerObj,
+ jNewWakeLock, PARTIAL_WAKE_LOCK, env->NewStringUTF("JWakeLock"));
+ mWakeLock = new JObjectHolder(javaWakeLock);
+ env->DeleteLocalRef(javaPowerManagerObj);
+ env->DeleteLocalRef(javaWakeLock);
}
- if (mPowerManager != NULL) {
- sp<IBinder> binder = new BBinder();
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- status_t status = mPowerManager->acquireWakeLock(
- POWERMANAGER_PARTIAL_WAKE_LOCK,
- binder, String16("JWakeLock"), String16("media"));
- IPCThreadState::self()->restoreCallingIdentity(token);
- if (status == NO_ERROR) {
- mWakeLockToken = binder;
- mWakeLockCount++;
- return true;
- }
+ if (mWakeLock != NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+ jmethodID jAcquire = env->GetMethodID(wakeLockCls, "acquire", "()V");
+ env->CallVoidMethod(mWakeLock->getJObject(), jAcquire);
+ mWakeLockCount++;
+ return true;
}
} else {
mWakeLockCount++;
@@ -86,25 +81,17 @@
mWakeLockCount = 1;
}
if (--mWakeLockCount == 0) {
- CHECK(mWakeLockToken != NULL);
- if (mPowerManager != NULL) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- mPowerManager->releaseWakeLock(mWakeLockToken, 0 /* flags */);
- IPCThreadState::self()->restoreCallingIdentity(token);
+ if (mWakeLock != NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+ jmethodID jRelease = env->GetMethodID(wakeLockCls, "release", "()V");
+ env->CallVoidMethod(mWakeLock->getJObject(), jRelease);
}
- mWakeLockToken.clear();
}
}
-void JWakeLock::clearPowerManager() {
+void JWakeLock::clearJavaWakeLock() {
release(true);
- mPowerManager.clear();
-}
-
-void JWakeLock::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused) {
- if (mWakeLock != NULL) {
- mWakeLock->clearPowerManager();
- }
}
} // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.h b/media/libmediaplayer2/nuplayer2/JWakeLock.h
index eace87e..36c542e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.h
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.h
@@ -18,7 +18,7 @@
#define J_WAKELOCK_H_
#include <media/stagefright/foundation/ABase.h>
-#include <powermanager/IPowerManager.h>
+#include <mediaplayer2/JObjectHolder.h>
#include <utils/RefBase.h>
namespace android {
@@ -26,7 +26,7 @@
class JWakeLock : public RefBase {
public:
- JWakeLock();
+ JWakeLock(const sp<JObjectHolder> &context);
// NOTE: acquire and release are not thread safe
@@ -37,28 +37,11 @@
virtual ~JWakeLock();
private:
- sp<IPowerManager> mPowerManager;
- sp<IBinder> mWakeLockToken;
- uint32_t mWakeLockCount;
+ uint32_t mWakeLockCount;
+ sp<JObjectHolder> mWakeLock;
+ const sp<JObjectHolder> mContext;
- class PMDeathRecipient : public IBinder::DeathRecipient {
- public:
- explicit PMDeathRecipient(JWakeLock *wakeLock) : mWakeLock(wakeLock) {}
- virtual ~PMDeathRecipient() {}
-
- // IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder> &who);
-
- private:
- PMDeathRecipient(const PMDeathRecipient&);
- PMDeathRecipient& operator= (const PMDeathRecipient&);
-
- JWakeLock *mWakeLock;
- };
-
- const sp<PMDeathRecipient> mDeathRecipient;
-
- void clearPowerManager();
+ void clearJavaWakeLock();
DISALLOW_EVIL_CONSTRUCTORS(JWakeLock);
};
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 080d923..5da6e24 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -209,7 +209,8 @@
////////////////////////////////////////////////////////////////////////////////
-NuPlayer2::NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock)
+NuPlayer2::NuPlayer2(
+ pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context)
: mPID(pid),
mUID(uid),
mMediaClock(mediaClock),
@@ -240,7 +241,8 @@
mVideoDecoderError(false),
mPaused(false),
mPausedByClient(true),
- mPausedForBuffering(false) {
+ mPausedForBuffering(false),
+ mContext(context) {
CHECK(mediaClock != NULL);
clearFlushComplete();
}
@@ -1738,7 +1740,7 @@
sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
++mRendererGeneration;
notify->setInt32("generation", mRendererGeneration);
- mRenderer = new Renderer(mAudioSink, mMediaClock, notify, flags);
+ mRenderer = new Renderer(mAudioSink, mMediaClock, notify, mContext, flags);
mRendererLooper = new ALooper;
mRendererLooper->setName("NuPlayer2Renderer");
mRendererLooper->start(false, true, ANDROID_PRIORITY_AUDIO);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index fdc128f..798c725 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/AHandler.h>
#include <mediaplayer2/MediaPlayer2Interface.h>
+#include <mediaplayer2/JObjectHolder.h>
#include "mediaplayer2.pb.h"
@@ -42,7 +43,8 @@
struct NuPlayer2Driver;
struct NuPlayer2 : public AHandler {
- explicit NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock);
+ explicit NuPlayer2(pid_t pid, uid_t uid,
+ const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context);
void setDriver(const wp<NuPlayer2Driver> &driver);
@@ -272,6 +274,9 @@
// Pause state as requested by source (internally) due to buffering
bool mPausedForBuffering;
+ // Passed from JAVA
+ const sp<JObjectHolder> mContext;
+
inline const sp<DecoderBase> &getDecoder(bool audio) {
return audio ? mAudioDecoder : mVideoDecoder;
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
index 49e3e3b..a5bd62d 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
@@ -1108,6 +1108,11 @@
} // buffer->data()
} // needsCopy
+ sp<RefBase> cryptInfoObj;
+ if (buffer->meta()->findObject("cryptInfo", &cryptInfoObj)) {
+ cryptInfo = static_cast<AMediaCodecCryptoInfoWrapper *>(cryptInfoObj.get());
+ }
+
status_t err;
if (cryptInfo != NULL) {
err = mCodec->queueSecureInputBuffer(
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index 2dab2dd..56e9471 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -108,7 +108,7 @@
static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
-NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
+NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context)
: mState(STATE_IDLE),
mAsyncResult(UNKNOWN_ERROR),
mSrcId(0),
@@ -123,7 +123,7 @@
mLooper(new ALooper),
mNuPlayer2Looper(new ALooper),
mMediaClock(new MediaClock),
- mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
+ mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)),
mPlayerFlags(0),
mAnalyticsItem(NULL),
mClientUid(uid),
@@ -662,33 +662,6 @@
return INVALID_OPERATION;
}
-status_t NuPlayer2Driver::getMetadata(
- const media::Metadata::Filter& /* ids */, Parcel *records) {
- Mutex::Autolock autoLock(mLock);
-
- using media::Metadata;
-
- Metadata meta(records);
-
- meta.appendBool(
- Metadata::kPauseAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
-
- meta.appendBool(
- Metadata::kSeekBackwardAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
-
- meta.appendBool(
- Metadata::kSeekForwardAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
-
- meta.appendBool(
- Metadata::kSeekAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
-
- return OK;
-}
-
void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
ALOGD("notifyResetComplete(%p)", this);
Mutex::Autolock autoLock(mLock);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
index bb30c76..0ec3a4b 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
@@ -18,6 +18,7 @@
#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ABase.h>
+#include <mediaplayer2/JObjectHolder.h>
namespace android {
@@ -26,7 +27,7 @@
struct NuPlayer2;
struct NuPlayer2Driver : public MediaPlayer2Interface {
- explicit NuPlayer2Driver(pid_t pid, uid_t uid);
+ explicit NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context);
virtual status_t initCheck() override;
@@ -61,9 +62,6 @@
virtual status_t setParameter(int key, const Parcel &request) override;
virtual status_t getParameter(int key, Parcel *reply) override;
- virtual status_t getMetadata(
- const media::Metadata::Filter& ids, Parcel *records) override;
-
virtual status_t dump(int fd, const Vector<String16> &args) const override;
virtual void onMessageReceived(const sp<AMessage> &msg) override;
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index e3c9b4b..3be7e36 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -26,6 +26,8 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaClock.h>
+#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
#include <media/stagefright/VideoFrameScheduler2.h>
@@ -86,10 +88,25 @@
// static
const int64_t NuPlayer2::Renderer::kMinPositionUpdateDelayUs = 100000LL;
+static audio_format_t constexpr audioFormatFromEncoding(int32_t pcmEncoding) {
+ switch (pcmEncoding) {
+ case kAudioEncodingPcmFloat:
+ return AUDIO_FORMAT_PCM_FLOAT;
+ case kAudioEncodingPcm16bit:
+ return AUDIO_FORMAT_PCM_16_BIT;
+ case kAudioEncodingPcm8bit:
+ return AUDIO_FORMAT_PCM_8_BIT; // TODO: do we want to support this?
+ default:
+ ALOGE("%s: Invalid encoding: %d", __func__, pcmEncoding);
+ return AUDIO_FORMAT_INVALID;
+ }
+}
+
NuPlayer2::Renderer::Renderer(
const sp<MediaPlayer2Interface::AudioSink> &sink,
const sp<MediaClock> &mediaClock,
const sp<AMessage> ¬ify,
+ const sp<JObjectHolder> &context,
uint32_t flags)
: mAudioSink(sink),
mUseVirtualAudioSink(false),
@@ -131,7 +148,7 @@
mTotalBuffersQueued(0),
mLastAudioBufferDrained(0),
mUseAudioCallback(false),
- mWakeLock(new JWakeLock()) {
+ mWakeLock(new JWakeLock(context)) {
CHECK(mediaClock != NULL);
mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
}
@@ -1269,10 +1286,10 @@
mAnchorTimeMediaUs = mediaTimeUs;
}
}
- mNextVideoTimeMediaUs = mediaTimeUs + 100000;
+ mNextVideoTimeMediaUs = mediaTimeUs;
if (!mHasAudio) {
// smooth out videos >= 10fps
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
}
if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
@@ -1406,9 +1423,15 @@
mHasAudio = false;
if (mNextVideoTimeMediaUs >= 0) {
int64_t mediaUs = 0;
- mMediaClock->getMediaTime(ALooper::GetNowUs(), &mediaUs);
- if (mNextVideoTimeMediaUs > mediaUs) {
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ int64_t nowUs = ALooper::GetNowUs();
+ status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
+ if (result == OK) {
+ if (mNextVideoTimeMediaUs > mediaUs) {
+ mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ }
+ } else {
+ mMediaClock->updateAnchor(
+ mNextVideoTimeMediaUs, nowUs, mNextVideoTimeMediaUs + 100000);
}
}
}
@@ -1864,8 +1887,13 @@
int32_t sampleRate;
CHECK(format->findInt32("sample-rate", &sampleRate));
+ // read pcm encoding from MediaCodec output format, if available
+ int32_t pcmEncoding;
+ audio_format_t audioFormat =
+ format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
+ audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
+
if (offloadingAudio()) {
- audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
AString mime;
CHECK(format->findString("mime", &mime));
status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
@@ -1966,7 +1994,7 @@
const PcmInfo info = {
(audio_channel_mask_t)channelMask,
(audio_output_flags_t)pcmFlags,
- AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
+ audioFormat,
numChannels,
sampleRate
};
@@ -1998,7 +2026,7 @@
sampleRate,
numChannels,
(audio_channel_mask_t)channelMask,
- AUDIO_FORMAT_PCM_16_BIT,
+ audioFormat,
mUseAudioCallback ? &NuPlayer2::Renderer::AudioSinkCallback : NULL,
mUseAudioCallback ? this : NULL,
(audio_output_flags_t)pcmFlags,
@@ -2054,4 +2082,3 @@
}
} // namespace android
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
index 484d9b7..d065dee 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
@@ -20,6 +20,7 @@
#include <media/AudioResamplerPublic.h>
#include <media/AVSyncSettings.h>
+#include <mediaplayer2/JObjectHolder.h>
#include "NuPlayer2.h"
@@ -38,6 +39,7 @@
Renderer(const sp<MediaPlayer2Interface::AudioSink> &sink,
const sp<MediaClock> &mediaClock,
const sp<AMessage> ¬ify,
+ const sp<JObjectHolder> &context,
uint32_t flags = 0);
static size_t AudioSinkCallback(
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index e2aa8f8..1e85804 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -171,6 +171,7 @@
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
@@ -179,6 +180,7 @@
size_t numtracks = extractor->countTracks();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index c8f6738..c990b2a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1299,10 +1299,10 @@
mAnchorTimeMediaUs = mediaTimeUs;
}
}
- mNextVideoTimeMediaUs = mediaTimeUs + 100000;
+ mNextVideoTimeMediaUs = mediaTimeUs;
if (!mHasAudio) {
// smooth out videos >= 10fps
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
}
if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
@@ -1436,9 +1436,15 @@
mHasAudio = false;
if (mNextVideoTimeMediaUs >= 0) {
int64_t mediaUs = 0;
- mMediaClock->getMediaTime(ALooper::GetNowUs(), &mediaUs);
- if (mNextVideoTimeMediaUs > mediaUs) {
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ int64_t nowUs = ALooper::GetNowUs();
+ status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
+ if (result == OK) {
+ if (mNextVideoTimeMediaUs > mediaUs) {
+ mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ }
+ } else {
+ mMediaClock->updateAnchor(
+ mNextVideoTimeMediaUs, nowUs, mNextVideoTimeMediaUs + 100000);
}
}
}
diff --git a/media/libnblog/Reader.cpp b/media/libnblog/Reader.cpp
index fd53090..f556e37 100644
--- a/media/libnblog/Reader.cpp
+++ b/media/libnblog/Reader.cpp
@@ -284,6 +284,15 @@
EntryIterator DumpReader::handleFormat(const FormatEntry &fmtEntry,
String8 *timestamp, String8 *body)
{
+ String8 timestampLocal;
+ String8 bodyLocal;
+ if (timestamp == nullptr) {
+ timestamp = ×tampLocal;
+ }
+ if (body == nullptr) {
+ body = &bodyLocal;
+ }
+
// log timestamp
const int64_t ts = fmtEntry.timestamp();
timestamp->clear();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 6ad0417..dadfe28 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -566,8 +566,8 @@
mDequeueCounter(0),
mMetadataBuffersToSubmit(0),
mNumUndequeuedBuffers(0),
- mRepeatFrameDelayUs(-1ll),
- mMaxPtsGapUs(0ll),
+ mRepeatFrameDelayUs(-1LL),
+ mMaxPtsGapUs(0LL),
mMaxFps(-1),
mFps(-1.0),
mCaptureFps(-1.0),
@@ -1822,15 +1822,15 @@
if (!msg->findInt64(
"repeat-previous-frame-after",
&mRepeatFrameDelayUs)) {
- mRepeatFrameDelayUs = -1ll;
+ mRepeatFrameDelayUs = -1LL;
}
// only allow 32-bit value, since we pass it as U32 to OMX.
if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
- mMaxPtsGapUs = 0ll;
+ mMaxPtsGapUs = 0LL;
} else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < INT32_MIN) {
ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
- mMaxPtsGapUs = 0ll;
+ mMaxPtsGapUs = 0LL;
}
if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
@@ -1838,7 +1838,7 @@
}
// notify GraphicBufferSource to allow backward frames
- if (mMaxPtsGapUs < 0ll) {
+ if (mMaxPtsGapUs < 0LL) {
mMaxFps = -1;
}
@@ -2183,7 +2183,8 @@
err = setupG711Codec(encoder, sampleRate, numChannels);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
- int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
+ // numChannels needs to be set to properly communicate PCM values.
+ int32_t numChannels = 2, sampleRate = 44100, compressionLevel = -1;
if (encoder &&
(!msg->findInt32("channel-count", &numChannels)
|| !msg->findInt32("sample-rate", &sampleRate))) {
@@ -2209,7 +2210,7 @@
}
}
err = setupFlacCodec(
- encoder, numChannels, sampleRate, compressionLevel);
+ encoder, numChannels, sampleRate, compressionLevel, pcmEncoding);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
int32_t numChannels, sampleRate;
@@ -2320,12 +2321,16 @@
(void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding);
if (mConverter[kPortIndexInput] != NULL) {
+ ALOGD("%s: encoder %s input format pcm encoding converter from %d to %d",
+ __func__, mComponentName.c_str(), pcmEncoding, codecPcmEncoding);
mInputFormat->setInt32("pcm-encoding", pcmEncoding);
}
} else {
(void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
if (mConverter[kPortIndexOutput] != NULL) {
+ ALOGD("%s: decoder %s output format pcm encoding converter from %d to %d",
+ __func__, mComponentName.c_str(), codecPcmEncoding, pcmEncoding);
mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
}
}
@@ -3029,8 +3034,8 @@
}
status_t ACodec::setupFlacCodec(
- bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
-
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+ AudioEncoding encoding) {
if (encoder) {
OMX_AUDIO_PARAM_FLACTYPE def;
InitOMXParams(&def);
@@ -3053,7 +3058,8 @@
return setupRawAudioFormat(
encoder ? kPortIndexInput : kPortIndexOutput,
sampleRate,
- numChannels);
+ numChannels,
+ encoding);
}
status_t ACodec::setupRawAudioFormat(
@@ -3111,6 +3117,7 @@
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
+ ALOGE("%s: incorrect numChannels: %d", __func__, numChannels);
return OMX_ErrorNone;
}
@@ -4421,8 +4428,8 @@
h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
// disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames
- h264type.nRefFrames = 1;
- h264type.nBFrames = 0;
+ // h264type.nRefFrames = 1;
+ // h264type.nBFrames = 0;
h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
h264type.nAllowedPictureTypes =
@@ -6700,7 +6707,7 @@
mCodec->mDequeueCounter = 0;
mCodec->mMetadataBuffersToSubmit = 0;
- mCodec->mRepeatFrameDelayUs = -1ll;
+ mCodec->mRepeatFrameDelayUs = -1LL;
mCodec->mInputFormat.clear();
mCodec->mOutputFormat.clear();
mCodec->mBaseOutputFormat.clear();
@@ -6842,7 +6849,7 @@
return err;
}
- if (mCodec->mRepeatFrameDelayUs > 0ll) {
+ if (mCodec->mRepeatFrameDelayUs > 0LL) {
err = statusFromBinderStatus(
mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
mCodec->mRepeatFrameDelayUs));
@@ -6855,7 +6862,7 @@
}
}
- if (mCodec->mMaxPtsGapUs != 0ll) {
+ if (mCodec->mMaxPtsGapUs != 0LL) {
OMX_PARAM_U32TYPE maxPtsGapParams;
InitOMXParams(&maxPtsGapParams);
maxPtsGapParams.nPortIndex = kPortIndexInput;
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index a6f0a0b..199b57b 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -118,6 +118,13 @@
}
sp<MetaData> format = mSource->getFormat();
+
+ if (format == NULL) {
+ ALOGE("No metadata b/118620871");
+ android_errorWriteLog(0x534e4554, "118620871");
+ return BAD_VALUE;
+ }
+
const char *mime;
bool success = format->findCString(kKeyMIMEType, &mime);
CHECK(success);
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 9de1e22..5027303 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -337,7 +337,7 @@
} else {
// This should not happen in normal case.
ALOGW("Failed to get audio timestamp, fallback to use systemclock");
- timeUs = systemTime() / 1000ll;
+ timeUs = systemTime() / 1000LL;
// Estimate the real sampling time of the 1st sample in this buffer
// from AudioRecord's latency. (Apply this adjustment first so that
// the start time logic is not affected.)
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 3ad82d9..2a819ad 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -19,6 +19,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "CameraSourceTimeLapse"
+#include <media/hardware/HardwareAPI.h>
#include <binder/IPCThreadState.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
@@ -172,8 +173,16 @@
ALOGV("signalBufferReturned");
Mutex::Autolock autoLock(mQuickStopLock);
if (mQuickStop && (buffer == mLastReadBufferCopy)) {
+ if (metaDataStoredInVideoBuffers() == kMetadataBufferTypeNativeHandleSource) {
+ native_handle_t* handle = (
+ (VideoNativeHandleMetadata*)(mLastReadBufferCopy->data()))->pHandle;
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ }
buffer->setObserver(NULL);
buffer->release();
+ mLastReadBufferCopy = NULL;
+ mForceRead = true;
} else {
return CameraSource::signalBufferReturned(buffer);
}
@@ -182,7 +191,8 @@
void createMediaBufferCopy(
const MediaBufferBase& sourceBuffer,
int64_t frameTime,
- MediaBufferBase **newBuffer) {
+ MediaBufferBase **newBuffer,
+ int32_t videoBufferMode) {
ALOGV("createMediaBufferCopy");
size_t sourceSize = sourceBuffer.size();
@@ -192,13 +202,20 @@
memcpy((*newBuffer)->data(), sourcePointer, sourceSize);
(*newBuffer)->meta_data().setInt64(kKeyTime, frameTime);
+
+ if (videoBufferMode == kMetadataBufferTypeNativeHandleSource) {
+ ((VideoNativeHandleMetadata*)((*newBuffer)->data()))->pHandle =
+ native_handle_clone(
+ ((VideoNativeHandleMetadata*)(sourceBuffer.data()))->pHandle);
+ }
}
void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBufferBase& sourceBuffer) {
ALOGV("fillLastReadBufferCopy");
int64_t frameTime;
CHECK(sourceBuffer.meta_data().findInt64(kKeyTime, &frameTime));
- createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
+ createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy,
+ metaDataStoredInVideoBuffers());
mLastReadBufferCopy->add_ref();
mLastReadBufferCopy->setObserver(this);
}
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index c62c05a..42b98b1 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -39,7 +39,7 @@
namespace android {
-static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec
+static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
static const size_t kRetryCount = 50; // must be >0
sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
@@ -274,7 +274,7 @@
size_t retriesLeft = kRetryCount;
do {
size_t index;
- int64_t ptsUs = 0ll;
+ int64_t ptsUs = 0LL;
uint32_t flags = 0;
// Queue as many inputs as we possibly can, then block on dequeuing
@@ -406,7 +406,7 @@
: FrameDecoder(componentName, trackMeta, source),
mIsAvcOrHevc(false),
mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC),
- mTargetTimeUs(-1ll),
+ mTargetTimeUs(-1LL),
mNumFrames(0),
mNumFramesDecoded(0) {
}
@@ -487,7 +487,7 @@
const sp<MediaCodecBuffer> &videoFrameBuffer,
const sp<AMessage> &outputFormat,
int64_t timeUs, bool *done) {
- bool shouldOutput = (mTargetTimeUs < 0ll) || (timeUs >= mTargetTimeUs);
+ bool shouldOutput = (mTargetTimeUs < 0LL) || (timeUs >= mTargetTimeUs);
// If this is not the target frame, skip color convert.
if (!shouldOutput) {
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 770535c..a9715c9 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -240,7 +240,7 @@
size -= length;
}
- out->meta()->setInt64("timeUs", 0ll);
+ out->meta()->setInt64("timeUs", 0LL);
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kNotifyBuffer);
@@ -842,7 +842,7 @@
int64_t timeUs;
CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
- uint32_t PTS = (timeUs * 9ll) / 100ll;
+ uint32_t PTS = (timeUs * 9LL) / 100LL;
size_t PES_packet_length = accessUnit->size() + 8;
bool padding = (accessUnit->size() < (188 - 18));
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a48466a..7df1a2d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -137,6 +137,8 @@
private:
enum {
+ // TODO: need to increase this considering the bug
+ // about camera app not sending video frames continuously?
kMaxCttsOffsetTimeUs = 1000000LL, // 1 second
kSampleArraySize = 1000,
};
@@ -317,6 +319,7 @@
ListTableEntries<uint32_t, 1> *mStssTableEntries;
ListTableEntries<uint32_t, 2> *mSttsTableEntries;
ListTableEntries<uint32_t, 2> *mCttsTableEntries;
+ ListTableEntries<uint32_t, 3> *mElstTableEntries; // 3columns: segDuration, mediaTime, mediaRate
int64_t mMinCttsOffsetTimeUs;
int64_t mMinCttsOffsetTicks;
@@ -416,6 +419,8 @@
// Duration is time scale based
void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+ void addOneElstTableEntry(uint32_t segmentDuration, int32_t mediaTime,
+ int16_t mediaRate, int16_t mediaRateFraction);
bool isTrackMalFormed() const;
void sendTrackSummary(bool hasMultipleTracks);
@@ -448,6 +453,7 @@
void writeVideoFourCCBox();
void writeMetadataFourCCBox();
void writeStblBox(bool use32BitOffset);
+ void writeEdtsBox();
Track(const Track &);
Track &operator=(const Track &);
@@ -481,8 +487,9 @@
mInterleaveDurationUs = 1000000;
- mStartTimestampUs = -1ll;
+ mStartTimestampUs = -1LL;
mStartTimeOffsetMs = -1;
+ mStartTimeOffsetBFramesUs = 0;
mPaused = false;
mStarted = false;
mWriterThreadStarted = false;
@@ -1272,6 +1279,10 @@
// Adjust the global start time.
mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
+ // Add mStartTimeOffsetBFramesUs(-ve or zero) to the duration of first entry in STTS.
+ mStartTimeOffsetBFramesUs = minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
+ ALOGV("mStartTimeOffsetBFramesUs :%" PRId32, mStartTimeOffsetBFramesUs);
+
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
if (!(*it)->isHeic()) {
@@ -1734,7 +1745,7 @@
void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
ALOGI("setStartTimestampUs: %" PRId64, timeUs);
- CHECK_GE(timeUs, 0ll);
+ CHECK_GE(timeUs, 0LL);
Mutex::Autolock autoLock(mLock);
if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
mStartTimestampUs = timeUs;
@@ -1747,6 +1758,11 @@
return mStartTimestampUs;
}
+int32_t MPEG4Writer::getStartTimeOffsetBFramesUs() {
+ Mutex::Autolock autoLock(mLock);
+ return mStartTimeOffsetBFramesUs;
+}
+
size_t MPEG4Writer::numTracks() {
Mutex::Autolock autolock(mLock);
return mTracks.size();
@@ -1776,6 +1792,7 @@
mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
+ mElstTableEntries(new ListTableEntries<uint32_t, 3>(3)), // Reserve 3 rows, a row has 3 items
mMinCttsOffsetTimeUs(0),
mMinCttsOffsetTicks(0),
mMaxCttsOffsetTicks(0),
@@ -1842,46 +1859,48 @@
// Clear all the internal states except the CSD data.
void MPEG4Writer::Track::resetInternal() {
- mDone = false;
- mPaused = false;
- mResumed = false;
- mStarted = false;
- mGotStartKeyFrame = false;
- mIsMalformed = false;
- mTrackDurationUs = 0;
- mEstimatedTrackSizeBytes = 0;
- mSamplesHaveSameSize = 0;
- if (mStszTableEntries != NULL) {
- delete mStszTableEntries;
- mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
- }
-
- if (mStcoTableEntries != NULL) {
- delete mStcoTableEntries;
- mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
- }
- if (mCo64TableEntries != NULL) {
- delete mCo64TableEntries;
- mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
- }
-
- if (mStscTableEntries != NULL) {
- delete mStscTableEntries;
- mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
- }
- if (mStssTableEntries != NULL) {
- delete mStssTableEntries;
- mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
- }
- if (mSttsTableEntries != NULL) {
- delete mSttsTableEntries;
- mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
- }
- if (mCttsTableEntries != NULL) {
- delete mCttsTableEntries;
- mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
- }
- mReachedEOS = false;
+ mDone = false;
+ mPaused = false;
+ mResumed = false;
+ mStarted = false;
+ mGotStartKeyFrame = false;
+ mIsMalformed = false;
+ mTrackDurationUs = 0;
+ mEstimatedTrackSizeBytes = 0;
+ mSamplesHaveSameSize = 0;
+ if (mStszTableEntries != NULL) {
+ delete mStszTableEntries;
+ mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
+ }
+ if (mStcoTableEntries != NULL) {
+ delete mStcoTableEntries;
+ mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
+ }
+ if (mCo64TableEntries != NULL) {
+ delete mCo64TableEntries;
+ mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
+ }
+ if (mStscTableEntries != NULL) {
+ delete mStscTableEntries;
+ mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
+ }
+ if (mStssTableEntries != NULL) {
+ delete mStssTableEntries;
+ mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
+ }
+ if (mSttsTableEntries != NULL) {
+ delete mSttsTableEntries;
+ mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
+ }
+ if (mCttsTableEntries != NULL) {
+ delete mCttsTableEntries;
+ mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
+ }
+ if (mElstTableEntries != NULL) {
+ delete mElstTableEntries;
+ mElstTableEntries = new ListTableEntries<uint32_t, 3>(3);
+ }
+ mReachedEOS = false;
}
void MPEG4Writer::Track::updateTrackSizeEstimate() {
@@ -1900,6 +1919,7 @@
mStssTableEntries->count() * 4 + // stss box size
mSttsTableEntries->count() * 8 + // stts box size
mCttsTableEntries->count() * 8 + // ctts box size
+ mElstTableEntries->count() * 12 + // elst box size
stcoBoxSizeBytes + // stco box size
stszBoxSizeBytes; // stsz box size
}
@@ -1936,6 +1956,16 @@
mCttsTableEntries->add(htonl(duration));
}
+void MPEG4Writer::Track::addOneElstTableEntry(
+ uint32_t segmentDuration, int32_t mediaTime, int16_t mediaRate, int16_t mediaRateFraction) {
+ ALOGV("segmentDuration:%u, mediaTime:%d", segmentDuration, mediaTime);
+ ALOGV("mediaRate :%" PRId16 ", mediaRateFraction :%" PRId16 ", Ored %u", mediaRate,
+ mediaRateFraction, ((((uint32_t)mediaRate) << 16) | ((uint32_t)mediaRateFraction)));
+ mElstTableEntries->add(htonl(segmentDuration));
+ mElstTableEntries->add(htonl(mediaTime));
+ mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction));
+}
+
status_t MPEG4Writer::setNextFd(int fd) {
ALOGV("addNextFd");
Mutex::Autolock l(mLock);
@@ -2173,6 +2203,7 @@
delete mSttsTableEntries;
delete mStssTableEntries;
delete mCttsTableEntries;
+ delete mElstTableEntries;
mStszTableEntries = NULL;
mStcoTableEntries = NULL;
@@ -2181,6 +2212,7 @@
mSttsTableEntries = NULL;
mStssTableEntries = NULL;
mCttsTableEntries = NULL;
+ mElstTableEntries = NULL;
if (mCodecSpecificData != NULL) {
free(mCodecSpecificData);
@@ -3067,7 +3099,7 @@
if (mResumed) {
int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
- if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3088,7 +3120,7 @@
TimestampDebugHelperEntry timestampDebugEntry;
timestampUs -= previousPausedDurationUs;
timestampDebugEntry.pts = timestampUs;
- if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3127,7 +3159,7 @@
cttsOffsetTimeUs =
timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
- if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(cttsOffsetTimeUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3185,7 +3217,7 @@
}
}
- if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3206,7 +3238,7 @@
currDurationTicks =
((timestampUs * mTimeScale + 500000LL) / 1000000LL -
(lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
- if (currDurationTicks < 0ll) {
+ if (currDurationTicks < 0LL) {
ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
(long long)timestampUs, (long long)lastTimestampUs, trackName);
copy->release();
@@ -3612,6 +3644,7 @@
uint32_t now = getMpeg4Time();
mOwner->beginBox("trak");
writeTkhdBox(now);
+ writeEdtsBox();
mOwner->beginBox("mdia");
writeMdhdBox(now);
writeHdlrBox();
@@ -3982,6 +4015,33 @@
mOwner->endBox();
}
+void MPEG4Writer::Track::writeEdtsBox(){
+ ALOGV("%s : getStartTimeOffsetTimeUs of track:%" PRId64 " us", getTrackType(),
+ getStartTimeOffsetTimeUs());
+
+ // Prepone video playback.
+ if (mMinCttsOffsetTicks != mMaxCttsOffsetTicks) {
+ int32_t mvhdTimeScale = mOwner->getTimeScale();
+ uint32_t tkhdDuration = (mTrackDurationUs * mvhdTimeScale + 5E5) / 1E6;
+ int64_t mediaTime = ((kMaxCttsOffsetTimeUs - getMinCttsOffsetTimeUs())
+ * mTimeScale + 5E5) / 1E6;
+ if (tkhdDuration > 0 && mediaTime > 0) {
+ addOneElstTableEntry(tkhdDuration, mediaTime, 1, 0);
+ }
+ }
+
+ if (mElstTableEntries->count() == 0) {
+ return;
+ }
+
+ mOwner->beginBox("edts");
+ mOwner->beginBox("elst");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mElstTableEntries->write(mOwner);
+ mOwner->endBox(); // elst;
+ mOwner->endBox(); // edts
+}
+
void MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
int64_t trakDurationUs = getDurationUs();
int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
@@ -4118,7 +4178,9 @@
uint32_t duration;
CHECK(mSttsTableEntries->get(duration, 1));
duration = htonl(duration); // Back to host byte order
- mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
+ int32_t startTimeOffsetScaled = (((getStartTimeOffsetTimeUs() +
+ mOwner->getStartTimeOffsetBFramesUs()) * mTimeScale) + 500000LL) / 1000000LL;
+ mSttsTableEntries->set(htonl((int32_t)duration + startTimeOffsetScaled), 1);
}
mSttsTableEntries->write(mOwner);
mOwner->endBox(); // stts
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 41dbfd4..8bff9f7 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -28,7 +28,7 @@
// Maximum allowed time backwards from anchor change.
// If larger than this threshold, it's treated as discontinuity.
-static const int64_t kAnchorFluctuationAllowedUs = 10000ll;
+static const int64_t kAnchorFluctuationAllowedUs = 10000LL;
MediaClock::Timer::Timer(const sp<AMessage> ¬ify, int64_t mediaTimeUs, int64_t adjustRealUs)
: mNotify(notify),
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index bd9e2bb..7816fae 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2699,7 +2699,7 @@
int64_t timeoutUs;
CHECK(msg->findInt64("timeoutUs", &timeoutUs));
- if (timeoutUs == 0ll) {
+ if (timeoutUs == 0LL) {
PostReplyWithError(replyID, -EAGAIN);
break;
}
@@ -2707,7 +2707,7 @@
mFlags |= kFlagDequeueInputPending;
mDequeueInputReplyID = replyID;
- if (timeoutUs > 0ll) {
+ if (timeoutUs > 0LL) {
sp<AMessage> timeoutMsg =
new AMessage(kWhatDequeueInputTimedOut, this);
timeoutMsg->setInt32(
@@ -2773,7 +2773,7 @@
int64_t timeoutUs;
CHECK(msg->findInt64("timeoutUs", &timeoutUs));
- if (timeoutUs == 0ll) {
+ if (timeoutUs == 0LL) {
PostReplyWithError(replyID, -EAGAIN);
break;
}
@@ -2781,7 +2781,7 @@
mFlags |= kFlagDequeueOutputPending;
mDequeueOutputReplyID = replyID;
- if (timeoutUs > 0ll) {
+ if (timeoutUs > 0LL) {
sp<AMessage> timeoutMsg =
new AMessage(kWhatDequeueOutputTimedOut, this);
timeoutMsg->setInt32(
@@ -3042,7 +3042,7 @@
msg->setSize("index", bufferIndex);
msg->setSize("offset", 0);
msg->setSize("size", csd->size());
- msg->setInt64("timeUs", 0ll);
+ msg->setInt64("timeUs", 0LL);
msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
msg->setPointer("errorDetailMsg", &errorDetailMsg);
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 20881a4..0f75822 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -372,7 +372,7 @@
msg->postAndAwaitResponse(&response);
int64_t timeUs;
if (!response->findInt64("time-us", &timeUs)) {
- timeUs = -1ll;
+ timeUs = -1LL;
}
return timeUs;
}
@@ -452,9 +452,9 @@
mEncoderDataSpace(0),
mPersistentSurface(persistentSurface),
mInputBufferTimeOffsetUs(0),
- mFirstSampleSystemTimeUs(-1ll),
+ mFirstSampleSystemTimeUs(-1LL),
mPausePending(false),
- mFirstSampleTimeUs(-1ll),
+ mFirstSampleTimeUs(-1LL),
mGeneration(0) {
CHECK(mLooper != NULL);
@@ -687,13 +687,13 @@
size_t bufferIndex = *mAvailEncoderInputIndices.begin();
mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
- int64_t timeUs = 0ll;
+ int64_t timeUs = 0LL;
uint32_t flags = 0;
size_t size = 0;
if (mbuf != NULL) {
CHECK(mbuf->meta_data().findInt64(kKeyTime, &timeUs));
- if (mFirstSampleSystemTimeUs < 0ll) {
+ if (mFirstSampleSystemTimeUs < 0LL) {
mFirstSampleSystemTimeUs = systemTime() / 1000;
if (mPausePending) {
mPausePending = false;
@@ -767,7 +767,7 @@
}
int64_t startTimeUs;
if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
- startTimeUs = -1ll;
+ startTimeUs = -1LL;
}
if (mStarted) {
@@ -914,7 +914,7 @@
if (mIsVideo) {
int64_t decodingTimeUs;
if (mFlags & FLAG_USE_SURFACE_INPUT) {
- if (mFirstSampleSystemTimeUs < 0ll) {
+ if (mFirstSampleSystemTimeUs < 0LL) {
mFirstSampleSystemTimeUs = systemTime() / 1000;
if (mPausePending) {
mPausePending = false;
@@ -926,7 +926,7 @@
// Timestamp offset is already adjusted in GraphicBufferSource.
// GraphicBufferSource is supposed to discard samples
// queued before start, and offset timeUs by start time
- CHECK_GE(timeUs, 0ll);
+ CHECK_GE(timeUs, 0LL);
// TODO:
// Decoding time for surface source is unavailable,
// use presentation time for now. May need to move
@@ -954,7 +954,7 @@
}
mbuf->meta_data().setInt64(kKeyTime, timeUs);
} else {
- mbuf->meta_data().setInt64(kKeyTime, 0ll);
+ mbuf->meta_data().setInt64(kKeyTime, 0LL);
mbuf->meta_data().setInt32(kKeyIsCodecConfig, true);
}
if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
@@ -1081,7 +1081,7 @@
MetaData *params = static_cast<MetaData *>(obj.get());
int64_t pauseStartTimeUs = -1;
if (params == NULL || !params->findInt64(kKeyTime, &pauseStartTimeUs)) {
- pauseStartTimeUs = -1ll;
+ pauseStartTimeUs = -1LL;
}
onPause(pauseStartTimeUs);
}
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 2c7a4e5..86402ce 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/IMediaExtractor.h>
#include <media/IMediaExtractorService.h>
+#include <private/android_filesystem_config.h>
#include <cutils/properties.h>
#include <utils/String8.h>
#include <ziparchive/zip_archive.h>
@@ -106,7 +107,8 @@
}
MediaExtractor *ex = nullptr;
- if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1) {
+ if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1 ||
+ creatorVersion == EXTRACTORDEF_VERSION_NDK_V2) {
CMediaExtractor *ret = ((CreatorFunc)creator)(source->wrap(), meta);
if (meta != nullptr && freeMeta != nullptr) {
freeMeta(meta);
@@ -184,7 +186,10 @@
void *curCreator = NULL;
if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V1) {
- curCreator = (void*) (*it)->def.sniff.v2(
+ curCreator = (void*) (*it)->def.u.v2.sniff(
+ source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
+ } else if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ curCreator = (void*) (*it)->def.u.v3.sniff(
source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
}
@@ -214,7 +219,8 @@
void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin,
std::list<sp<ExtractorPlugin>> &pluginList) {
// sanity check check struct version, uuid, name
- if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1) {
+ if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1 &&
+ plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V2) {
ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
return;
}
@@ -394,6 +400,8 @@
return strcmp(first->def.extractor_name, second->def.extractor_name) < 0;
}
+static std::unordered_set<std::string> gSupportedExtensions;
+
// static
void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
Mutex::Autolock autoLock(gPluginMutex);
@@ -426,9 +434,37 @@
newList->sort(compareFunc);
gPlugins = newList;
+
+ for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
+ if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ for (size_t i = 0;; i++) {
+ const char* ext = (*it)->def.u.v3.supported_types[i];
+ if (ext == nullptr) {
+ break;
+ }
+ gSupportedExtensions.insert(std::string(ext));
+ }
+ }
+ }
+
gPluginsRegistered = true;
}
+// static
+std::unordered_set<std::string> MediaExtractorFactory::getSupportedTypes() {
+ if (getuid() == AID_MEDIA_EX) {
+ return gSupportedExtensions;
+ }
+ ALOGV("get service manager");
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+
+ if (binder != 0) {
+ sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
+ return mediaExService->getSupportedTypes();
+ }
+ return std::unordered_set<std::string>();
+}
+
status_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
Mutex::Autolock autoLock(gPluginMutex);
String8 out;
@@ -445,13 +481,25 @@
out.append("Available extractors:\n");
if (gPluginsRegistered) {
for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
- out.appendFormat(" %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)\n",
+ out.appendFormat(" %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)",
(*it)->def.extractor_name,
(*it)->def.def_version,
(*it)->uuidString.c_str(),
(*it)->def.extractor_version,
(*it)->libPath.c_str());
+ if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ out.append(", supports: ");
+ for (size_t i = 0;; i++) {
+ const char* mime = (*it)->def.u.v3.supported_types[i];
+ if (mime == nullptr) {
+ break;
+ }
+ out.appendFormat("%s ", mime);
+ }
+ }
+ out.append("\n");
}
+ out.append("\n");
} else {
out.append(" (no plugins registered)\n");
}
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index ba14e5d..a3f55da 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -36,7 +36,7 @@
// Maximum late time allowed for a video frame to be rendered. When a video
// frame arrives later than this number, it will be discarded without rendering.
-static const int64_t kMaxAllowedVideoLateTimeUs = 40000ll;
+static const int64_t kMaxAllowedVideoLateTimeUs = 40000LL;
namespace android {
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 1c1be30..036e79d 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -120,7 +120,7 @@
if (format->mFormat->findInt64("timeUs", &val64)) {
meta.setInt64(kKeyTime, val64);
}
- if (format->mFormat->findInt64("duration", &val64)) {
+ if (format->mFormat->findInt64("durationUs", &val64)) {
meta.setInt64(kKeyDuration, val64);
}
if (format->mFormat->findInt64("target-time", &val64)) {
@@ -172,6 +172,10 @@
meta.setData(kKeySEI,
MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
}
+ if (format->mFormat->findBuffer("audio-presentation-info", &valbuf)) {
+ meta.setData(kKeyAudioPresentationInfo,
+ MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+ }
} else {
*buffer = nullptr;
}
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 7025af7..522c81d 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -440,12 +440,12 @@
if (mFetching) {
if (mFinalStatus != OK && mNumRetriesLeft > 0) {
// We failed this time and will try again in 3 seconds.
- delayUs = 3000000ll;
+ delayUs = 3000000LL;
} else {
delayUs = 0;
}
} else {
- delayUs = 100000ll;
+ delayUs = 100000LL;
}
(new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
@@ -740,7 +740,7 @@
}
if (keepAliveSecs >= 0) {
- mKeepAliveIntervalUs = keepAliveSecs * 1000000ll;
+ mKeepAliveIntervalUs = keepAliveSecs * 1000000LL;
} else {
mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
}
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index f5178dd..83b87d9 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -41,7 +41,7 @@
NuMediaExtractor::Sample::Sample()
: mBuffer(NULL),
- mSampleTimeUs(-1ll) {
+ mSampleTimeUs(-1LL) {
}
NuMediaExtractor::Sample::Sample(MediaBufferBase *buffer, int64_t timeUs)
@@ -50,8 +50,8 @@
}
NuMediaExtractor::NuMediaExtractor()
- : mTotalBitrate(-1ll),
- mDurationUs(-1ll) {
+ : mTotalBitrate(-1LL),
+ mDurationUs(-1LL) {
}
NuMediaExtractor::~NuMediaExtractor() {
@@ -209,8 +209,8 @@
return ERROR_UNSUPPORTED;
}
- mTotalBitrate = 0ll;
- mDurationUs = -1ll;
+ mTotalBitrate = 0LL;
+ mDurationUs = -1LL;
for (size_t i = 0; i < mImpl->countTracks(); ++i) {
sp<MetaData> meta = mImpl->getTrackMetaData(i);
@@ -225,8 +225,8 @@
CHECK(meta->findCString(kKeyMIMEType, &mime));
ALOGV("track of type '%s' does not publish bitrate", mime);
- mTotalBitrate = -1ll;
- } else if (mTotalBitrate >= 0ll) {
+ mTotalBitrate = -1LL;
+ } else if (mTotalBitrate >= 0LL) {
mTotalBitrate += bitrate;
}
@@ -503,7 +503,7 @@
}
MediaSource::ReadOptions options;
- if (seekTimeUs >= 0ll) {
+ if (seekTimeUs >= 0LL) {
options.setSeekTo(seekTimeUs, mode);
info->mFinalResult = OK;
releaseTrackSamples(info);
@@ -768,7 +768,7 @@
off64_t size;
if (mDurationUs > 0 && mDataSource->getSize(&size) == OK) {
- *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
+ *bitrate = size * 8000000LL / mDurationUs; // in bits/sec
return true;
}
@@ -795,30 +795,34 @@
}
// Return OK if we have received an audio presentation info.
+// Return ERROR_END_OF_STREAM if no tracks are available.
// Return ERROR_UNSUPPORTED if the track has no audio presentation.
// Return INVALID_OPERATION if audio presentation metadata version does not match.
status_t NuMediaExtractor::getAudioPresentations(
- size_t trackIndex, AudioPresentationCollection *presentations) const {
+ size_t trackIndex, AudioPresentationCollection *presentations) {
Mutex::Autolock autoLock(mLock);
-
- if (mImpl == NULL) {
- return -EINVAL;
+ ssize_t minIndex = fetchAllTrackSamples();
+ if (minIndex < 0) {
+ return ERROR_END_OF_STREAM;
}
+ for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+ TrackInfo *info = &mSelectedTracks.editItemAt(i);
- if (trackIndex >= mImpl->countTracks()) {
- return -ERANGE;
+ if (info->mTrackIndex == trackIndex) {
+ sp<MetaData> meta = new MetaData(info->mSamples.begin()->mBuffer->meta_data());
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
+ std::istringstream inStream(std::string(static_cast<const char*>(data), size));
+ return deserializeAudioPresentations(&inStream, presentations);
+ }
+ ALOGV("Track %zu does not contain any audio presentation", trackIndex);
+ return ERROR_UNSUPPORTED;
+ }
}
-
- sp<MetaData> meta = mImpl->getTrackMetaData(trackIndex);
-
- uint32_t type;
- const void *data;
- size_t size;
- if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
- std::istringstream inStream(std::string(static_cast<const char*>(data), size));
- return deserializeAudioPresentations(&inStream, presentations);
- }
- ALOGE("Source does not contain any audio presentation");
+ ALOGV("Source does not contain any audio presentation");
return ERROR_UNSUPPORTED;
}
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 17187a8..cf4edae 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -22,6 +22,7 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/StagefrightMediaScanner.h>
#include <media/IMediaHTTPService.h>
@@ -34,25 +35,16 @@
StagefrightMediaScanner::~StagefrightMediaScanner() {}
-static bool FileHasAcceptableExtension(const char *extension) {
- static const char *kValidExtensions[] = {
- ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
- ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
- ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
- ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
- ".avi", ".mpeg", ".mpg", ".awb", ".mpga", ".mov",
- ".m4v", ".oga", ".m4r"
- };
- static const size_t kNumValidExtensions =
- sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
+static std::unordered_set<std::string> gSupportedExtensions;
- for (size_t i = 0; i < kNumValidExtensions; ++i) {
- if (!strcasecmp(extension, kValidExtensions[i])) {
- return true;
- }
+static bool FileHasAcceptableExtension(const char *extension) {
+
+ if (gSupportedExtensions.empty()) {
+ // get the list from the service
+ gSupportedExtensions = MediaExtractorFactory::getSupportedTypes();
}
- return false;
+ return gSupportedExtensions.count(std::string(extension + 1)) != 0;
}
MediaScanResult StagefrightMediaScanner::processFile(
@@ -135,6 +127,8 @@
{ "colorstandard", METADATA_KEY_COLOR_STANDARD },
{ "colortransfer", METADATA_KEY_COLOR_TRANSFER },
{ "colorrange", METADATA_KEY_COLOR_RANGE },
+ { "samplerate", METADATA_KEY_SAMPLERATE },
+ { "bitspersample", METADATA_KEY_BITS_PER_SAMPLE },
};
static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp
index 7496752..49cea9e 100644
--- a/media/libstagefright/ThrottledSource.cpp
+++ b/media/libstagefright/ThrottledSource.cpp
@@ -51,7 +51,7 @@
// How long would it have taken to transfer everything we ever
// transferred given the limited bandwidth.
int64_t durationUs =
- mTotalTransferred * 1000000ll / mBandwidthLimitBytesPerSecond;
+ mTotalTransferred * 1000000LL / mBandwidthLimitBytesPerSecond;
int64_t whenUs = mStartTimeUs + durationUs;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 163cd05..49e485a 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -2020,7 +2020,7 @@
HLSTime::HLSTime(const sp<AMessage>& meta) :
mSeq(-1),
- mTimeUs(-1ll),
+ mTimeUs(-1LL),
mMeta(meta) {
if (meta != NULL) {
CHECK(meta->findInt32("discontinuitySeq", &mSeq));
@@ -2029,7 +2029,7 @@
}
int64_t HLSTime::getSegmentTimeUs() const {
- int64_t segmentStartTimeUs = -1ll;
+ int64_t segmentStartTimeUs = -1LL;
if (mMeta != NULL) {
CHECK(mMeta->findInt64("segmentStartTimeUs", &segmentStartTimeUs));
diff --git a/media/libstagefright/VideoFrameScheduler2.cpp b/media/libstagefright/VideoFrameScheduler2.cpp
index e02ae7d..fc76904 100644
--- a/media/libstagefright/VideoFrameScheduler2.cpp
+++ b/media/libstagefright/VideoFrameScheduler2.cpp
@@ -36,7 +36,7 @@
namespace android {
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr);
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr);
/* ======================================================================= */
/* VsyncTracker */
@@ -46,19 +46,19 @@
public:
VsyncTracker();
~VsyncTracker() {}
- long getVsyncPeriod();
- long getVsyncTime(long periodOffset);
- void addSample(long timestamp);
+ nsecs_t getVsyncPeriod();
+ nsecs_t getVsyncTime(nsecs_t periodOffset);
+ void addSample(nsecs_t timestamp);
private:
static const int kMaxSamples = 32;
static const int kMinSamplesForUpdate = 6;
int mNumSamples;
int mFirstSample;
- long mReferenceTime;
- long mPhase;
- long mPeriod;
- long mTimestampSamples[kMaxSamples];
+ nsecs_t mReferenceTime;
+ nsecs_t mPhase;
+ nsecs_t mPeriod;
+ nsecs_t mTimestampSamples[kMaxSamples];
Mutex mLock;
void updateModelLocked();
@@ -75,19 +75,39 @@
}
}
-long VsyncTracker::getVsyncPeriod() {
+nsecs_t VsyncTracker::getVsyncPeriod() {
Mutex::Autolock dataLock(mLock);
return mPeriod;
}
-long VsyncTracker::getVsyncTime(long periodOffset) {
+nsecs_t VsyncTracker::getVsyncTime(nsecs_t periodOffset) {
Mutex::Autolock dataLock(mLock);
- const long now = systemTime();
- long phase = mReferenceTime + mPhase;
- return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
+ const nsecs_t now = systemTime();
+ nsecs_t phase = mReferenceTime + mPhase;
+
+ // result = (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase
+ // prevent overflow
+ nsecs_t result = (now - phase) / mPeriod;
+ if (result > LONG_LONG_MAX - periodOffset - 1) {
+ return LONG_LONG_MAX;
+ } else {
+ result += periodOffset + 1;
+ }
+ if (result > LONG_LONG_MAX / mPeriod) {
+ return LONG_LONG_MAX;
+ } else {
+ result *= mPeriod;
+ }
+ if (result > LONG_LONG_MAX - phase) {
+ return LONG_LONG_MAX;
+ } else {
+ result += phase;
+ }
+
+ return result;
}
-void VsyncTracker::addSample(long timestamp) {
+void VsyncTracker::addSample(nsecs_t timestamp) {
Mutex::Autolock dataLock(mLock);
if (mNumSamples == 0) {
mPhase = 0;
@@ -107,17 +127,17 @@
if (mNumSamples < kMinSamplesForUpdate) {
return;
}
- long durationSum = 0;
- long minDuration = LONG_MAX;
- long maxDuration = 0;
+ nsecs_t durationSum = 0;
+ nsecs_t minDuration = LONG_MAX;
+ nsecs_t maxDuration = 0;
for (int i = 1; i < mNumSamples; i++) {
int idx = (mFirstSample + i) % kMaxSamples;
int prev = (idx + kMaxSamples - 1) % kMaxSamples;
long duration = mTimestampSamples[idx] - mTimestampSamples[prev];
durationSum += duration;
- minDuration = min(minDuration, duration);
- maxDuration = max(maxDuration, duration);
+ if (minDuration > duration) { minDuration = duration; }
+ if (maxDuration < duration) { maxDuration = duration; }
}
durationSum -= (minDuration + maxDuration);
@@ -154,9 +174,9 @@
/* JNI */
/* ======================================================================= */
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr) {
- static const long kOneMillisecInNanosec = 1000000;
- static const long kOneSecInNanosec = kOneMillisecInNanosec * 1000;
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr) {
+ static const nsecs_t kOneMillisecInNanosec = 1000000;
+ static const nsecs_t kOneSecInNanosec = kOneMillisecInNanosec * 1000;
JNIEnv *env = JavaVMHelper::getJNIEnv();
jclass jDisplayManagerGlobalCls = env->FindClass(
@@ -178,19 +198,19 @@
jmethodID jGetRefreshRate = env->GetMethodID(jDisplayCls, "getRefreshRate", "()F");
jfloat javaRefreshRate = env->CallFloatMethod(javaDisplayObj, jGetRefreshRate);
- long vsyncPeriod = (long) (kOneSecInNanosec / (float) javaRefreshRate);
+ nsecs_t vsyncPeriod = (nsecs_t) (kOneSecInNanosec / (float) javaRefreshRate);
jmethodID jGetAppVsyncOffsetNanos = env->GetMethodID(
jDisplayCls, "getAppVsyncOffsetNanos", "()J");
jlong javaAppVsyncOffset = env->CallLongMethod(javaDisplayObj, jGetAppVsyncOffsetNanos);
- *appVsyncOffsetPtr = (long) javaAppVsyncOffset;
+ *appVsyncOffsetPtr = (nsecs_t) javaAppVsyncOffset;
jmethodID jGetPresentationDeadlineNanos = env->GetMethodID(
jDisplayCls, "getPresentationDeadlineNanos", "()J");
jlong javaPresentationDeadline = env->CallLongMethod(
javaDisplayObj, jGetPresentationDeadlineNanos);
- *sfVsyncOffsetPtr = vsyncPeriod - ((long) javaPresentationDeadline - kOneMillisecInNanosec);
+ *sfVsyncOffsetPtr = vsyncPeriod - ((nsecs_t) javaPresentationDeadline - kOneMillisecInNanosec);
}
/* ======================================================================= */
diff --git a/media/libstagefright/bqhelper/FrameDropper.cpp b/media/libstagefright/bqhelper/FrameDropper.cpp
index d2a2473..387ac5a 100644
--- a/media/libstagefright/bqhelper/FrameDropper.cpp
+++ b/media/libstagefright/bqhelper/FrameDropper.cpp
@@ -35,7 +35,7 @@
status_t FrameDropper::setMaxFrameRate(float maxFrameRate) {
if (maxFrameRate < 0) {
- mMinIntervalUs = -1ll;
+ mMinIntervalUs = -1LL;
return OK;
}
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 8c1da76..a4374c9 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -292,20 +292,20 @@
mSuspended(false),
mLastFrameTimestampUs(-1),
mStopTimeUs(-1),
- mLastActionTimeUs(-1ll),
- mSkipFramesBeforeNs(-1ll),
- mFrameRepeatIntervalUs(-1ll),
+ mLastActionTimeUs(-1LL),
+ mSkipFramesBeforeNs(-1LL),
+ mFrameRepeatIntervalUs(-1LL),
mRepeatLastFrameGeneration(0),
mOutstandingFrameRepeatCount(0),
mFrameRepeatBlockedOnCodecBuffer(false),
mFps(-1.0),
mCaptureFps(-1.0),
- mBaseCaptureUs(-1ll),
- mBaseFrameUs(-1ll),
+ mBaseCaptureUs(-1LL),
+ mBaseFrameUs(-1LL),
mFrameCount(0),
- mPrevCaptureUs(-1ll),
- mPrevFrameUs(-1ll),
- mInputBufferTimeOffsetUs(0ll) {
+ mPrevCaptureUs(-1LL),
+ mPrevFrameUs(-1LL),
+ mInputBufferTimeOffsetUs(0LL) {
ALOGV("GraphicBufferSource");
String8 name("GraphicBufferSource");
@@ -392,7 +392,7 @@
submitEndOfInputStream_l();
}
- if (mFrameRepeatIntervalUs > 0ll && mLooper == NULL) {
+ if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) {
mReflector = new AHandlerReflector<GraphicBufferSource>(this);
mLooper = new ALooper;
@@ -655,7 +655,7 @@
// only submit sample if start time is unspecified, or sample
// is queued after the specified start time
- if (mSkipFramesBeforeNs < 0ll || item.mTimestampNs >= mSkipFramesBeforeNs) {
+ if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) {
// if start time is set, offset time stamp by start time
if (mSkipFramesBeforeNs > 0) {
item.mTimestampNs -= mSkipFramesBeforeNs;
@@ -677,7 +677,7 @@
} else {
// Don't set the last buffer id if we're not repeating,
// we'll be holding on to the last buffer for nothing.
- if (mFrameRepeatIntervalUs > 0ll) {
+ if (mFrameRepeatIntervalUs > 0LL) {
setLatestBuffer_l(item);
}
ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
@@ -755,7 +755,7 @@
&& (mFps > 2 * mCaptureFps
|| mCaptureFps > 2 * mFps)) {
// Time lapse or slow motion mode
- if (mPrevCaptureUs < 0ll) {
+ if (mPrevCaptureUs < 0LL) {
// first capture
mPrevCaptureUs = mBaseCaptureUs = timeUs;
// adjust the first sample timestamp.
@@ -1123,19 +1123,19 @@
mSuspended = false;
mEndOfStream = false;
mEndOfStreamSent = false;
- mSkipFramesBeforeNs = -1ll;
+ mSkipFramesBeforeNs = -1LL;
mFrameDropper.clear();
- mFrameRepeatIntervalUs = -1ll;
+ mFrameRepeatIntervalUs = -1LL;
mRepeatLastFrameGeneration = 0;
mOutstandingFrameRepeatCount = 0;
mLatestBuffer.mBuffer.reset();
mFrameRepeatBlockedOnCodecBuffer = false;
mFps = -1.0;
mCaptureFps = -1.0;
- mBaseCaptureUs = -1ll;
- mBaseFrameUs = -1ll;
- mPrevCaptureUs = -1ll;
- mPrevFrameUs = -1ll;
+ mBaseCaptureUs = -1LL;
+ mBaseFrameUs = -1LL;
+ mPrevCaptureUs = -1LL;
+ mPrevFrameUs = -1LL;
mFrameCount = 0;
mInputBufferTimeOffsetUs = 0;
mStopTimeUs = -1;
@@ -1201,7 +1201,7 @@
Mutex::Autolock autoLock(mMutex);
- if (mExecuting || repeatAfterUs <= 0ll) {
+ if (mExecuting || repeatAfterUs <= 0LL) {
return INVALID_OPERATION;
}
@@ -1213,7 +1213,7 @@
Mutex::Autolock autoLock(mMutex);
// timeOffsetUs must be negative for adjustment.
- if (timeOffsetUs >= 0ll) {
+ if (timeOffsetUs >= 0LL) {
return INVALID_OPERATION;
}
@@ -1247,7 +1247,7 @@
mSkipFramesBeforeNs =
(skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ?
- (skipFramesBeforeUs * 1000) : -1ll;
+ (skipFramesBeforeUs * 1000) : -1LL;
return OK;
}
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index d393c7a..41bc16c 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -738,7 +738,7 @@
} else {
int64_t currentTime = mBufferTimestamps.top();
currentTime += mStreamInfo->aacSamplesPerFrame *
- 1000000ll / mStreamInfo->aacSampleRate;
+ 1000000LL / mStreamInfo->aacSampleRate;
mBufferTimestamps.add(currentTime);
}
} else {
@@ -989,7 +989,7 @@
// adjust/interpolate next time stamp
*currentBufLeft -= decodedSize;
*nextTimeStamp += mStreamInfo->aacSamplesPerFrame *
- 1000000ll / mStreamInfo->aacSampleRate;
+ 1000000LL / mStreamInfo->aacSampleRate;
ALOGV("adjusted nextTimeStamp/size to %lld/%d",
(long long) *nextTimeStamp, *currentBufLeft);
} else {
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 96e668e..6e437cf 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -63,7 +63,7 @@
mInputSize(0),
mInputFrame(NULL),
mAllocatedFrameSize(0),
- mInputTimeUs(-1ll),
+ mInputTimeUs(-1LL),
mSawInputEOS(false),
mSignalledError(false) {
initPorts();
@@ -587,7 +587,7 @@
// "Time" on the input buffer has in effect advanced by the
// number of audio frames we just advanced nOffset by.
inHeader->nTimeStamp +=
- (copy * 1000000ll / mSampleRate)
+ (copy * 1000000LL / mSampleRate)
/ (mNumChannels * sizeof(int16_t));
if (inHeader->nFilledLen == 0) {
@@ -725,7 +725,7 @@
mAllocatedFrameSize = 0;
mSentCodecSpecificData = false;
- mInputTimeUs = -1ll;
+ mInputTimeUs = -1LL;
mSawInputEOS = false;
mSignalledError = false;
}
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index b7e84ec..34dd011 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -505,7 +505,7 @@
outHeader->nTimeStamp =
mAnchorTimeUs
- + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;
+ + (mNumSamplesOutput * 1000000LL) / kSampleRateNB;
mNumSamplesOutput += kNumSamplesPerFrameNB;
} else {
@@ -513,7 +513,7 @@
outHeader->nTimeStamp =
mAnchorTimeUs
- + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;
+ + (mNumSamplesOutput * 1000000LL) / kSampleRateWB;
mNumSamplesOutput += kNumSamplesPerFrameWB;
}
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index f97c44f..85ab64e 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -49,7 +49,7 @@
mBitRate(0),
mMode(MR475),
mInputSize(0),
- mInputTimeUs(-1ll),
+ mInputTimeUs(-1LL),
mSawInputEOS(false),
mSignalledError(false) {
initPorts();
@@ -340,7 +340,7 @@
// "Time" on the input buffer has in effect advanced by the
// number of audio frames we just advanced nOffset by.
inHeader->nTimeStamp +=
- (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+ (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
if (inHeader->nFilledLen == 0) {
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index a644b66..7fb8a4c 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -50,7 +50,7 @@
mBitRate(0),
mMode(VOAMRWB_MD66),
mInputSize(0),
- mInputTimeUs(-1ll),
+ mInputTimeUs(-1LL),
mSawInputEOS(false),
mSignalledError(false) {
initPorts();
@@ -387,7 +387,7 @@
// "Time" on the input buffer has in effect advanced by the
// number of audio frames we just advanced nOffset by.
inHeader->nTimeStamp +=
- (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+ (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
if (inHeader->nFilledLen == 0) {
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 3924fc2..bf5e243 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -607,7 +607,7 @@
timeTaken = mTimeEnd - mTimeStart;
ALOGV("timeTaken=%6lldus delay=%6lldus numBytes=%6d",
- (long long) (timeTaken / 1000ll), (long long) (timeDelay / 1000ll),
+ (long long) (timeTaken / 1000LL), (long long) (timeDelay / 1000LL),
s_dec_op.u4_num_bytes_consumed);
if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
mFlushNeeded = true;
diff --git a/media/libstagefright/codecs/flac/dec/Android.bp b/media/libstagefright/codecs/flac/dec/Android.bp
index 1674cb2..3d4a44f 100644
--- a/media/libstagefright/codecs/flac/dec/Android.bp
+++ b/media/libstagefright/codecs/flac/dec/Android.bp
@@ -29,7 +29,6 @@
},
shared_libs: [
- "libcutils",
"liblog",
"libstagefright_flacdec",
"libstagefright_omx",
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index 4db0060..842a7ce 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -89,12 +89,12 @@
def.eDir = OMX_DirOutput;
def.nBufferCountMin = kNumOutputBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = 4096 * FLACDecoder::kMaxChannels;
+ def.nBufferSize = kNumSamplesPerFrame * FLACDecoder::kMaxChannels * sizeof(float);
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
+ def.nBufferAlignment = sizeof(float);
def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
def.format.audio.pNativeRender = NULL;
@@ -173,7 +173,7 @@
flacParams->nChannels = mStreamInfo.channels;
flacParams->nSampleRate = mStreamInfo.sample_rate;
} else {
- flacParams->nChannels = 1;
+ flacParams->nChannels = 2;
flacParams->nSampleRate = 44100;
}
@@ -195,10 +195,10 @@
return OMX_ErrorBadPortIndex;
}
- pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eNumData = mNumericalData;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
- pcmParams->nBitPerSample = 16;
+ pcmParams->nBitPerSample = mBitsPerSample;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -211,7 +211,7 @@
pcmParams->nChannels = mStreamInfo.channels;
pcmParams->nSamplingRate = mStreamInfo.sample_rate;
} else {
- pcmParams->nChannels = 1;
+ pcmParams->nChannels = 2;
pcmParams->nSamplingRate = 44100;
}
@@ -281,6 +281,19 @@
return OMX_ErrorBadPortIndex;
}
+ if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+ mNumericalData = OMX_NumericalDataFloat;
+ mBitsPerSample = 32;
+ } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+ && pcmParams->nBitPerSample == 16) {
+ mNumericalData = OMX_NumericalDataSigned;
+ mBitsPerSample = 16;
+ } else {
+ ALOGE("Invalid eNumData %d, nBitsPerSample %d",
+ pcmParams->eNumData, pcmParams->nBitPerSample);
+ return OMX_ErrorUndefined;
+ }
+
return OMX_ErrorNone;
}
@@ -301,11 +314,13 @@
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
+ const bool outputFloat = mNumericalData == OMX_NumericalDataFloat;
+
ALOGV("onQueueFilled %d/%d:", inQueue.empty(), outQueue.empty());
while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mFinishedDecoder) {
BufferInfo *outInfo = *outQueue.begin();
OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
- int16_t *outBuffer = reinterpret_cast<int16_t *>(outHeader->pBuffer + outHeader->nOffset);
+ void *outBuffer = reinterpret_cast<void *>(outHeader->pBuffer + outHeader->nOffset);
size_t outBufferSize = outHeader->nAllocLen - outHeader->nOffset;
int64_t timeStamp = 0;
@@ -374,7 +389,7 @@
}
status_t decoderErr = mFLACDecoder->decodeOneFrame(
- inBuffer, inBufferLength, outBuffer, &outBufferSize);
+ inBuffer, inBufferLength, outBuffer, &outBufferSize, outputFloat);
if (decoderErr != OK) {
ALOGE("onQueueFilled: FLACDecoder decodeOneFrame returns error %d", decoderErr);
mSignalledError = true;
@@ -393,7 +408,9 @@
continue;
}
} else if (mSawInputEOS) {
- status_t decoderErr = mFLACDecoder->decodeOneFrame(NULL, 0, outBuffer, &outBufferSize);
+ status_t decoderErr = mFLACDecoder->decodeOneFrame(
+ nullptr /* inBuffer */, 0 /* inBufferLen */,
+ outBuffer, &outBufferSize, outputFloat);
mFinishedDecoder = true;
if (decoderErr != OK) {
ALOGE("onQueueFilled: FLACDecoder finish returns error %d", decoderErr);
@@ -456,7 +473,8 @@
mOutputPortSettingsChange = AWAITING_ENABLED;
PortInfo *info = editPortInfo(1 /* portIndex */);
if (!info->mDef.bEnabled) {
- info->mDef.nBufferSize = mStreamInfo.max_blocksize * mStreamInfo.channels * 2;
+ info->mDef.nBufferSize =
+ mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(float);
}
break;
}
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
index b63f7ad..ba02074 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
@@ -45,10 +45,14 @@
virtual void onReset() override;
private:
+ static constexpr unsigned int kNumSamplesPerFrame = 2048; // adjusted based on stream.
+
enum {
kNumInputBuffers = 4,
kNumOutputBuffers = 4,
};
+ OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+ OMX_U32 mBitsPerSample = 16;
FLACDecoder *mFLACDecoder;
FLAC__StreamMetadata_StreamInfo mStreamInfo;
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index 9b696da..b32ab08 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -28,7 +28,10 @@
],
header_libs: ["libbase_headers"],
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libaudioutils",
+ "libFLAC",
+ ],
name: "libstagefright_soft_flacenc",
vendor_available: true,
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 955f211..3add006 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -20,7 +20,7 @@
#include <utils/Log.h>
#include "SoftFlacEncoder.h"
-
+#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
@@ -75,7 +75,9 @@
}
if (!mSignalledError) { // no use allocating input buffer if we had an error above
- mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame);
+ // 2x the pcm16 samples can exist with the same size as pcmFloat samples.
+ mInputBufferPcm32 = (FLAC__int32*) malloc(
+ sizeof(FLAC__int32) * kNumSamplesPerFrame * kMaxChannels * 2);
if (mInputBufferPcm32 == NULL) {
ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name);
mSignalledError = true;
@@ -115,14 +117,14 @@
// configure input port of the encoder
def.nPortIndex = 0;
def.eDir = OMX_DirInput;
- def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+ def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = kMaxInputBufferSize;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
+ def.nBufferAlignment = sizeof(float);
def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
def.format.audio.pNativeRender = NULL;
@@ -134,7 +136,7 @@
// configure output port of the encoder
def.nPortIndex = 1;
def.eDir = OMX_DirOutput;
- def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+ def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = kMaxOutputBufferSize;
def.bEnabled = OMX_TRUE;
@@ -193,10 +195,10 @@
return OMX_ErrorUndefined;
}
- pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eNumData = mNumericalData;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
- pcmParams->nBitPerSample = 16;
+ pcmParams->nBitPerSample = mBitsPerSample;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -270,12 +272,26 @@
return OMX_ErrorUndefined;
}
- if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
+ if (pcmParams->nChannels < 1 || pcmParams->nChannels > kMaxChannels) {
return OMX_ErrorUndefined;
}
mNumChannels = pcmParams->nChannels;
mSampleRate = pcmParams->nSamplingRate;
+
+ if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+ mNumericalData = OMX_NumericalDataFloat;
+ mBitsPerSample = 32;
+ } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+ && pcmParams->nBitPerSample == 16) {
+ mNumericalData = OMX_NumericalDataSigned;
+ mBitsPerSample = 16;
+ } else {
+ ALOGE("%s: invalid eNumData %d, nBitsPerSample %d",
+ __func__, pcmParams->eNumData, pcmParams->nBitPerSample);
+ return OMX_ErrorUndefined;
+ }
+
ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate);
return configureEncoder();
@@ -356,6 +372,10 @@
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
+ const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+ const size_t sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+ const size_t frameSize = sampleSize * mNumChannels;
+
FLAC__bool ok = true;
while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mSentOutputEOS) {
@@ -381,13 +401,21 @@
mEncoderReturnedNbBytes = 0;
mCurrentInputTimeStamp = inHeader->nTimeStamp;
- const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels);
- const unsigned nbInputSamples = inHeader->nFilledLen / 2;
- const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
+ const unsigned nbInputFrames = inHeader->nFilledLen / frameSize;
+ const unsigned nbInputSamples = inHeader->nFilledLen / sampleSize;
- CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
- for (unsigned i=0 ; i < nbInputSamples ; i++) {
- mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ if (inputFloat) {
+ CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels);
+ const float * const pcmFloat = reinterpret_cast<float *>(inHeader->pBuffer);
+ memcpy_to_q8_23_from_float_with_clamp(
+ mInputBufferPcm32, pcmFloat, nbInputSamples);
+ } else {
+ // note nbInputSamples may be 2x as large for pcm16 data.
+ CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels * 2);
+ const int16_t * const pcm16 = reinterpret_cast<int16_t *>(inHeader->pBuffer);
+ for (unsigned i = 0; i < nbInputSamples; ++i) {
+ mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ }
}
ALOGV(" about to encode %u samples per channel", nbInputFrames);
ok = FLAC__stream_encoder_process_interleaved(
@@ -526,10 +554,12 @@
return OMX_ErrorInvalidState;
}
+ const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+ const int codecBitsPerSample = inputFloat ? 24 : 16;
FLAC__bool ok = true;
ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
- ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+ ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, codecBitsPerSample);
ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
(unsigned)mCompressionLevel);
ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
index 64a6b1e..722fc13 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
@@ -45,8 +45,10 @@
private:
const unsigned int kNumBuffers = 2;
- const unsigned int kMaxNumSamplesPerFrame = 1152;
- const unsigned int kMaxInputBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2;
+ static constexpr unsigned int kMaxChannels = 2;
+ static constexpr unsigned int kNumSamplesPerFrame = 1152;
+ static constexpr unsigned int kMaxInputBufferSize =
+ kNumSamplesPerFrame * kMaxChannels * sizeof(float);
const unsigned int kMaxOutputBufferSize = 65536; //TODO check if this can be reduced
bool mSignalledError;
@@ -54,6 +56,8 @@
OMX_U32 mNumChannels;
OMX_U32 mSampleRate;
OMX_U32 mCompressionLevel;
+ OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+ OMX_U32 mBitsPerSample = 16;
// should the data received by the callback be written to the output port
bool mEncoderWriteData;
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 7a4cca9..c14983a 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -372,7 +372,7 @@
int32_t step = 4 << segment;
- int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
+ int32_t abs = (0x80L << exponent) + step * mantissa + step / 2 - 4 * 33;
*out++ = (x < 0x80) ? -abs : abs;
}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
index 53149c1..ecc3217 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
@@ -377,15 +377,15 @@
/* In/out : Nr, B, Rr */
/* Return : Void */
/* Modified : */
+/* Input argument "video" is guaranteed non-null by caller */
/* ======================================================================== */
-
PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip)
{
rateControl *rc = video->rc[currLayer];
MultiPass *pMP = video->pMP[currLayer];
- if (video == NULL || rc == NULL || pMP == NULL)
+ if (rc == NULL || pMP == NULL)
return PV_FAIL;
rc->VBV_fullness -= (Int)(rc->bitrate / rc->framerate * num_skip); //rc[currLayer]->Rp;
@@ -524,6 +524,7 @@
/* In/out : rc->T */
/* Return : Void */
/* Modified : */
+/* Input argument "input" is guaranteed non-null by caller */
/* ================================================================================ */
void targetBitCalculation(void *input)
@@ -537,7 +538,7 @@
Int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
/* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */
- if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+ if (currVol == NULL || pMP == NULL || rc == NULL)
return;
/* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
@@ -693,6 +694,7 @@
/* In/out : rc->T and rc->Qc */
/* Return : Void */
/* Modified : */
+/* Input argument "input" is guaranteed non-null by caller */
/* ================================================================================ */
/* Mad based variable bit allocation + QP calculation with a new quadratic method */
@@ -708,7 +710,7 @@
float curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;
- if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+ if (currVol == NULL || pMP == NULL || rc == NULL)
return;
/* Mad based variable bit allocation */
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index cd984f0..80083f7 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -407,7 +407,7 @@
}
outHeader->nTimeStamp =
- mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
+ mAnchorTimeUs + (mNumFramesOutput * 1000000LL) / mSamplingRate;
if (inHeader) {
CHECK_GE((int32_t)inHeader->nFilledLen, mConfig->inputBufferUsedLength);
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 942f850..4f61aa8 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -430,6 +430,15 @@
return;
}
+ if (size < sizeof(int64_t)) {
+ // The 2nd and 3rd input buffer are expected to contain
+ // an int64_t (see below), so make sure we get at least
+ // that much. The first input buffer must contain 19 bytes,
+ // but that is checked already.
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
if (mInputBufferCount == 0) {
delete mHeader;
mHeader = new OpusHeader();
@@ -573,7 +582,7 @@
outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
outHeader->nTimeStamp = mAnchorTimeUs +
- (mNumFramesOutput * 1000000ll) /
+ (mNumFramesOutput * 1000000LL) /
kRate;
mNumFramesOutput += numFrames;
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index ce8d458..76a400c 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -554,7 +554,7 @@
outHeader->nTimeStamp =
mAnchorTimeUs
- + (mNumFramesOutput * 1000000ll) / mVi->rate;
+ + (mNumFramesOutput * 1000000LL) / mVi->rate;
mNumFramesOutput += numFrames;
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index f352fba..8a86a0d 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -110,15 +110,22 @@
{
initPorts();
- CHECK_EQ(initDecoder(), (status_t)OK);
+ mMemoryVec.clear();
+ mDrcMemoryVec.clear();
+
+ CHECK_EQ(initDecoder(), IA_NO_ERROR);
}
SoftXAAC::~SoftXAAC() {
- int errCode = deInitXAACDecoder();
- if (0 != errCode) {
- ALOGE("deInitXAACDecoder() failed %d", errCode);
+ IA_ERRORCODE err_code = deInitXAACDecoder();
+ if (IA_NO_ERROR != err_code) {
+ ALOGE("deInitXAACDecoder() failed %d", err_code);
}
+ err_code = deInitMPEGDDDrc();
+ if (IA_NO_ERROR != err_code) {
+ ALOGE("deInitMPEGDDDrc() failed %d", err_code);
+ }
mIsCodecInitialized = false;
mIsCodecConfigFlushRequired = false;
}
@@ -164,36 +171,16 @@
addPort(def);
}
-status_t SoftXAAC::initDecoder() {
- status_t status = UNKNOWN_ERROR;
-
+IA_ERRORCODE SoftXAAC::initDecoder() {
int ui_drc_val;
IA_ERRORCODE err_code = IA_NO_ERROR;
int loop = 0;
err_code = initXAACDecoder();
if (err_code != IA_NO_ERROR) {
- if (NULL == mXheaacCodecHandle) {
- ALOGE("AAC decoder handle is null");
- }
- if (NULL == mMpegDDrcHandle) {
- ALOGE("MPEG-D DRC decoder handle is null");
- }
- for (loop = 1; loop < mMallocCount; loop++) {
- if (mMemoryArray[loop] == NULL) {
- ALOGE(" memory allocation error %d\n", loop);
- break;
- }
- }
- ALOGE("initXAACDecoder Failed");
-
- for (loop = 0; loop < mMallocCount; loop++) {
- if (mMemoryArray[loop]) free(mMemoryArray[loop]);
- }
- mMallocCount = 0;
- return status;
- } else {
- status = OK;
+ ALOGE("initXAACDecoder failed with error %d", err_code);
+ deInitXAACDecoder();
+ return err_code;
}
mEndOfInput = false;
@@ -274,7 +261,7 @@
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE");
#endif
- return status;
+ return IA_NO_ERROR;
}
OMX_ERRORTYPE SoftXAAC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params) {
@@ -547,9 +534,6 @@
/* sample currently */
if (mIsCodecInitialized) {
numOutBytes = mOutputFrameLength * (mPcmWdSz / 8) * mNumChannels;
- if ((mPcmWdSz / 8) != 2) {
- ALOGE("XAAC assumes 2 bytes per sample! mPcmWdSz %d", mPcmWdSz);
- }
}
while ((!inQueue.empty() || mEndOfInput) && !outQueue.empty()) {
@@ -569,8 +553,8 @@
inBufferLength = inHeader->nFilledLen;
/* GA header configuration sent to Decoder! */
- int err_code = configXAACDecoder(inBuffer, inBufferLength);
- if (0 != err_code) {
+ IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
+ if (IA_NO_ERROR != err_code) {
ALOGW("configXAACDecoder err_code = %d", err_code);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
@@ -665,7 +649,7 @@
mCurrentTimestamp = inHeader->nTimeStamp;
mLastInHeader = inHeader;
} else {
- mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000ll / mSampFreq;
+ mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000LL / mSampFreq;
}
} else {
inBuffer = inHeader->pBuffer + inHeader->nOffset;
@@ -682,8 +666,8 @@
/* which should initialize the codec. Once this state is reached, call the */
/* decodeXAACStream API with same frame to decode! */
if (!mIsCodecInitialized) {
- int err_code = configXAACDecoder(inBuffer, inBufferLength);
- if (0 != err_code) {
+ IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
+ if (IA_NO_ERROR != err_code) {
ALOGW("configXAACDecoder Failed 2 err_code = %d", err_code);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
@@ -845,7 +829,7 @@
}
}
-int SoftXAAC::configflushDecode() {
+IA_ERRORCODE SoftXAAC::configflushDecode() {
IA_ERRORCODE err_code;
UWORD32 ui_init_done;
uint32_t inBufferLength = 8203;
@@ -871,16 +855,13 @@
"Found Codec with below config---\nsampFreq %d\nnumChannels %d\npcmWdSz "
"%d\nchannelMask %d\noutputFrameLength %d",
mSampFreq, mNumChannels, mPcmWdSz, mChannelMask, mOutputFrameLength);
- if (mNumChannels > MAX_CHANNEL_COUNT) {
- ALOGE(" No of channels are more than max channels\n");
- mIsCodecInitialized = false;
- } else
- mIsCodecInitialized = true;
+
+ mIsCodecInitialized = true;
}
- return err_code;
+ return IA_NO_ERROR;
}
-int SoftXAAC::drainDecoder() {
- return 0;
+IA_ERRORCODE SoftXAAC::drainDecoder() {
+ return IA_NO_ERROR;
}
void SoftXAAC::onReset() {
@@ -921,7 +902,7 @@
}
}
-int SoftXAAC::initXAACDecoder() {
+IA_ERRORCODE SoftXAAC::initXAACDecoder() {
LOOPIDX i;
/* Error code */
@@ -939,11 +920,11 @@
UWORD32 ui_proc_mem_tabs_size;
/* API size */
UWORD32 pui_api_size;
+ pVOID pv_alloc_ptr;
mInputBufferSize = 0;
mInputBuffer = 0;
mOutputBuffer = 0;
- mMallocCount = 0;
/* Process struct initing end */
/* ******************************************************************/
@@ -954,20 +935,13 @@
err_code = ixheaacd_dec_api(NULL, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
/* Allocate memory for API */
- mMemoryArray[mMallocCount] = memalign(4, pui_api_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ mXheaacCodecHandle = memalign(4, pui_api_size);
+ if (mXheaacCodecHandle == NULL) {
ALOGE("malloc for pui_api_size + 4 >> %d Failed", pui_api_size + 4);
return IA_FATAL_ERROR;
}
- /* Set API object with the memory allocated */
- mXheaacCodecHandle = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
+ mMemoryVec.push(mXheaacCodecHandle);
/* Set the config params to default values */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
@@ -979,23 +953,16 @@
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
/* Allocate memory for API */
- mMemoryArray[mMallocCount] = memalign(4, pui_api_size);
+ mMpegDDrcHandle = memalign(4, pui_api_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ if (mMpegDDrcHandle == NULL) {
ALOGE("malloc for drc api structure Failed");
return IA_FATAL_ERROR;
}
- memset(mMemoryArray[mMallocCount], 0, pui_api_size);
+ mMemoryVec.push(mMpegDDrcHandle);
- /* Set API object with the memory allocated */
- mMpegDDrcHandle = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
+ memset(mMpegDDrcHandle, 0, pui_api_size);
/* Set the config params to default values */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
@@ -1021,23 +988,17 @@
&ui_proc_mem_tabs_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEMTABS_SIZE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
- mMemoryArray[mMallocCount] = memalign(4, ui_proc_mem_tabs_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ pv_alloc_ptr = memalign(4, ui_proc_mem_tabs_size);
+ if (pv_alloc_ptr == NULL) {
ALOGE("Malloc for size (ui_proc_mem_tabs_size + 4) = %d failed!",
ui_proc_mem_tabs_size + 4);
return IA_FATAL_ERROR;
}
- mMallocCount++;
- /* Set pointer for process memory tables */
- err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0,
- (pVOID)((WORD8*)mMemoryArray[mMallocCount - 1]));
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
+ mMemoryVec.push(pv_alloc_ptr);
+ /* Set pointer for process memory tables */
+ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0, pv_alloc_ptr);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
/* initialize the API, post config, fill memory tables */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
@@ -1066,17 +1027,12 @@
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
- mMemoryArray[mMallocCount] = memalign(ui_alignment, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ pv_alloc_ptr = memalign(ui_alignment, ui_size);
+ if (pv_alloc_ptr == NULL) {
ALOGE("Malloc for size (ui_size + ui_alignment) = %d failed!", ui_size + ui_alignment);
return IA_FATAL_ERROR;
}
- pv_alloc_ptr = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
+ mMemoryVec.push(pv_alloc_ptr);
/* Set the buffer pointer */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
@@ -1095,7 +1051,7 @@
return IA_NO_ERROR;
}
-int SoftXAAC::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) {
+IA_ERRORCODE SoftXAAC::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) {
UWORD32 ui_init_done;
int32_t i_bytes_consumed;
@@ -1154,13 +1110,73 @@
return IA_NO_ERROR;
}
-int SoftXAAC::configMPEGDDrc() {
+IA_ERRORCODE SoftXAAC::initMPEGDDDrc() {
+ IA_ERRORCODE err_code = IA_NO_ERROR;
+ int i;
+
+ for (i = 0; i < (WORD32)2; i++) {
+ WORD32 ui_size, ui_alignment, ui_type;
+ pVOID pv_alloc_ptr;
+
+ /* Get memory size */
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
+
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
+
+ /* Get memory alignment */
+ err_code =
+ ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment);
+
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
+
+ /* Get memory type */
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
+
+ pv_alloc_ptr = memalign(4, ui_size);
+ if (pv_alloc_ptr == NULL) {
+ ALOGE(" Cannot create requested memory %d", ui_size);
+ return IA_FATAL_ERROR;
+ }
+ mDrcMemoryVec.push(pv_alloc_ptr);
+
+ /* Set the buffer pointer */
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
+
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+ }
+
+ WORD32 ui_size;
+ ui_size = 8192 * 2;
+
+ mDrcInBuf = (int8_t*)memalign(4, ui_size);
+ if (mDrcInBuf == NULL) {
+ ALOGE(" Cannot create requested memory %d", ui_size);
+ return IA_FATAL_ERROR;
+ }
+ mDrcMemoryVec.push(mDrcInBuf);
+
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2, mDrcInBuf);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+
+ mDrcOutBuf = (int8_t*)memalign(4, ui_size);
+ if (mDrcOutBuf == NULL) {
+ ALOGE(" Cannot create requested memory %d", ui_size);
+ return IA_FATAL_ERROR;
+ }
+ mDrcMemoryVec.push(mDrcOutBuf);
+
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3, mDrcOutBuf);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+
+ return IA_NO_ERROR;
+}
+IA_ERRORCODE SoftXAAC::configMPEGDDrc() {
IA_ERRORCODE err_code = IA_NO_ERROR;
int i_effect_type;
int i_loud_norm;
int i_target_loudness;
unsigned int i_sbr_mode;
- int n_mems;
int i;
#ifdef ENABLE_MPEG_D_DRC
@@ -1217,78 +1233,16 @@
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS");
- for (i = 0; i < (WORD32)2; i++) {
- WORD32 ui_size, ui_alignment, ui_type;
- pVOID pv_alloc_ptr;
+ /* Free any memory that is allocated for MPEG D Drc so far */
+ deInitMPEGDDDrc();
- /* Get memory size */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
-
- RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
-
- /* Get memory alignment */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i,
- &ui_alignment);
-
- RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
-
- /* Get memory type */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
- mMemoryArray[mMallocCount] = memalign(4, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
- ALOGE(" Cannot create requested memory %d", ui_size);
- return IA_FATAL_ERROR;
- }
- pv_alloc_ptr = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
-
- /* Set the buffer pointer */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
-
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+ err_code = initMPEGDDDrc();
+ if (err_code != IA_NO_ERROR) {
+ ALOGE("initMPEGDDDrc failed with error %d", err_code);
+ deInitMPEGDDDrc();
+ return err_code;
}
- {
- WORD32 ui_size;
- ui_size = 8192 * 2;
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
- mMemoryArray[mMallocCount] = memalign(4, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
- ALOGE(" Cannot create requested memory %d", ui_size);
- return IA_FATAL_ERROR;
- }
-
- mDrcInBuf = (int8_t*)mMemoryArray[mMallocCount];
- mMallocCount++;
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2,
- /*mOutputBuffer*/ mDrcInBuf);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
-
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
- mMemoryArray[mMallocCount] = memalign(4, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
- ALOGE(" Cannot create requested memory %d", ui_size);
- return IA_FATAL_ERROR;
- }
-
- mDrcOutBuf = (int8_t*)mMemoryArray[mMallocCount];
- mMallocCount++;
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3,
- /*mOutputBuffer*/ mDrcOutBuf);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
- }
/* DRC buffers
buf[0] - contains extension element pay load loudness related
buf[1] - contains extension element pay load*/
@@ -1423,10 +1377,10 @@
}
#endif
- return err_code;
+ return IA_NO_ERROR;
}
-int SoftXAAC::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed,
- int32_t* outBytes) {
+IA_ERRORCODE SoftXAAC::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength,
+ int32_t* bytesConsumed, int32_t* outBytes) {
if (mInputBufferSize < inBufferLength) {
ALOGE("Cannot config AAC, input buffer size %d < inBufferLength %d", mInputBufferSize,
inBufferLength);
@@ -1516,24 +1470,33 @@
memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
}
#endif
- return err_code;
+ return IA_NO_ERROR;
}
-int SoftXAAC::deInitXAACDecoder() {
+IA_ERRORCODE SoftXAAC::deInitXAACDecoder() {
ALOGI("deInitXAACDecoder");
/* Tell that the input is over in this buffer */
IA_ERRORCODE err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INPUT_OVER, 0, NULL);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_INPUT_OVER");
- for (int i = 0; i < mMallocCount; i++) {
- if (mMemoryArray[i]) free(mMemoryArray[i]);
+ /* Irrespective of error returned in IA_API_CMD_INPUT_OVER, free allocated memory */
+ for (void* buf : mMemoryVec) {
+ free(buf);
}
- mMallocCount = 0;
-
+ mMemoryVec.clear();
return err_code;
}
+IA_ERRORCODE SoftXAAC::deInitMPEGDDDrc() {
+ ALOGI("deInitMPEGDDDrc");
+
+ for (void* buf : mDrcMemoryVec) {
+ free(buf);
+ }
+ mDrcMemoryVec.clear();
+ return IA_NO_ERROR;
+}
+
IA_ERRORCODE SoftXAAC::getXAACStreamInfo() {
IA_ERRORCODE err_code = IA_NO_ERROR;
@@ -1546,11 +1509,19 @@
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS");
+ if (mNumChannels > MAX_CHANNEL_COUNT) {
+ ALOGE(" No of channels are more than max channels\n");
+ return IA_FATAL_ERROR;
+ }
/* PCM word size */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ");
+ if ((mPcmWdSz / 8) != 2) {
+ ALOGE("Invalid Number of bytes per sample: %d, Expected is 2", mPcmWdSz);
+ return IA_FATAL_ERROR;
+ }
/* channel mask to tell the arrangement of channels in bit stream */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.h b/media/libstagefright/codecs/xaacdec/SoftXAAC.h
index 6176082..a62a797 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.h
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.h
@@ -33,8 +33,6 @@
#include "impd_apicmd_standards.h"
#include "impd_drc_config_params.h"
-#define MAX_MEM_ALLOCS 100
-
extern "C" IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx,
pVOID pv_value);
extern "C" IA_ERRORCODE ia_drc_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx,
@@ -80,18 +78,19 @@
enum { NONE, AWAITING_DISABLED, AWAITING_ENABLED } mOutputPortSettingsChange;
void initPorts();
- status_t initDecoder();
+ IA_ERRORCODE initDecoder();
bool isConfigured() const;
- int drainDecoder();
- int initXAACDecoder();
- int deInitXAACDecoder();
+ IA_ERRORCODE drainDecoder();
+ IA_ERRORCODE initXAACDecoder();
+ IA_ERRORCODE deInitXAACDecoder();
+ IA_ERRORCODE initMPEGDDDrc();
+ IA_ERRORCODE deInitMPEGDDDrc();
+ IA_ERRORCODE configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength);
+ IA_ERRORCODE configMPEGDDrc();
+ IA_ERRORCODE decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength,
+ int32_t* bytesConsumed, int32_t* outBytes);
- int configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength);
- int configMPEGDDrc();
- int decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed,
- int32_t* outBytes);
-
- int configflushDecode();
+ IA_ERRORCODE configflushDecode();
IA_ERRORCODE getXAACStreamInfo();
IA_ERRORCODE setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, int32_t drcRefLevel,
int32_t drcHeavyCompression
@@ -120,9 +119,8 @@
int8_t* mDrcOutBuf;
int32_t mMpegDDRCPresent;
int32_t mDRCFlag;
-
- void* mMemoryArray[MAX_MEM_ALLOCS];
- int32_t mMallocCount;
+ Vector<void*> mMemoryVec;
+ Vector<void*> mDrcMemoryVec;
DISALLOW_EVIL_CONSTRUCTORS(SoftXAAC);
};
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 86bd9d6..d136d9e 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -27,6 +27,7 @@
#include "libyuv/convert_from.h"
#include "libyuv/convert_argb.h"
+#include "libyuv/planar_functions.h"
#include "libyuv/video_common.h"
#include <functional>
#include <sys/time.h>
@@ -91,10 +92,17 @@
case OMX_COLOR_FormatCbYCrY:
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
- case OMX_COLOR_FormatYUV420SemiPlanar:
case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
return mDstFormat == OMX_COLOR_Format16bitRGB565;
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+#ifdef USE_LIBYUV
+ return mDstFormat == OMX_COLOR_Format16bitRGB565
+ || mDstFormat == OMX_COLOR_Format32BitRGBA8888;
+#else
+ return mDstFormat == OMX_COLOR_Format16bitRGB565;
+#endif
+
default:
return false;
}
@@ -236,7 +244,11 @@
break;
case OMX_COLOR_FormatYUV420SemiPlanar:
+#ifdef USE_LIBYUV
+ err = convertYUV420SemiPlanarUseLibYUV(src, dst);
+#else
err = convertYUV420SemiPlanar(src, dst);
+#endif
break;
case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
@@ -365,6 +377,36 @@
return OK;
}
+status_t ColorConverter::convertYUV420SemiPlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst) {
+ uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src.mBits + src.mStride * src.mHeight
+ + (src.mCropTop / 2) * src.mStride + src.mCropLeft;
+
+ switch (mDstFormat) {
+ case OMX_COLOR_Format16bitRGB565:
+ libyuv::NV12ToRGB565(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+ dst.mStride, src.cropWidth(), src.cropHeight());
+ break;
+
+ case OMX_COLOR_Format32BitRGBA8888:
+ libyuv::NV12ToARGB(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+ dst.mStride, src.cropWidth(), src.cropHeight());
+ break;
+
+ default:
+ return ERROR_UNSUPPORTED;
+ }
+
+ return OK;
+}
+
std::function<void (void *, void *, void *, size_t,
signed *, signed *, signed *, signed *)>
getReadFromSrc(OMX_COLOR_FORMATTYPE srcFormat) {
@@ -852,7 +894,7 @@
const uint8_t *src_u =
(const uint8_t *)src.mBits + src.mHeight * src.mStride +
- src.mCropTop * src.mStride / 2 + src.mCropLeft;
+ (src.mCropTop / 2) * src.mStride + src.mCropLeft;
for (size_t y = 0; y < src.cropHeight(); ++y) {
for (size_t x = 0; x < src.cropWidth(); x += 2) {
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 751b053..307c9b0 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -27,11 +27,17 @@
},
static: {
- whole_static_libs: ["libFLAC"],
+ whole_static_libs: [
+ "libFLAC",
+ "libaudioutils",
+ ],
},
shared: {
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libFLAC",
+ "libaudioutils",
+ ],
},
shared_libs: [
diff --git a/media/libstagefright/flac/dec/FLACDecoder.cpp b/media/libstagefright/flac/dec/FLACDecoder.cpp
index dfdc41c..cef0bc6 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.cpp
+++ b/media/libstagefright/flac/dec/FLACDecoder.cpp
@@ -20,6 +20,7 @@
#include "FLACDecoder.h"
+#include <audio_utils/primitives.h> // float_from_i32
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaDefs.h>
@@ -117,104 +118,43 @@
mErrorStatus = status;
}
-// Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved.
+// Copy samples from FLAC native 32-bit non-interleaved to 16-bit signed
+// or 32-bit float interleaved.
+// TODO: Consider moving to audio_utils. See similar code at FLACExtractor.cpp
// These are candidates for optimization if needed.
-static void copyMono8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
+static void copyTo16Signed(
+ short *dst,
+ const int *const *src,
unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] << 8;
- }
-}
-
-static void copyStereo8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] << 8;
- *dst++ = src[1][i] << 8;
- }
-}
-
-static void copyMultiCh8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
- for (unsigned i = 0; i < nSamples; ++i) {
- for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i] << 8;
+ unsigned nChannels,
+ unsigned bitsPerSample) {
+ const int leftShift = 16 - (int)bitsPerSample; // cast to int to prevent unsigned overflow.
+ if (leftShift >= 0) {
+ for (unsigned i = 0; i < nSamples; ++i) {
+ for (unsigned c = 0; c < nChannels; ++c) {
+ *dst++ = src[c][i] << leftShift;
+ }
+ }
+ } else {
+ const int rightShift = -leftShift;
+ for (unsigned i = 0; i < nSamples; ++i) {
+ for (unsigned c = 0; c < nChannels; ++c) {
+ *dst++ = src[c][i] >> rightShift;
+ }
}
}
}
-static void copyMono16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
+static void copyToFloat(
+ float *dst,
+ const int *const *src,
unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i];
- }
-}
-
-static void copyStereo16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i];
- *dst++ = src[1][i];
- }
-}
-
-static void copyMultiCh16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
+ unsigned nChannels,
+ unsigned bitsPerSample) {
+ const unsigned leftShift = 32 - bitsPerSample;
for (unsigned i = 0; i < nSamples; ++i) {
for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i];
- }
- }
-}
-
-// TODO: 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger
-static void copyMono24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] >> 8;
- }
-}
-
-static void copyStereo24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] >> 8;
- *dst++ = src[1][i] >> 8;
- }
-}
-
-static void copyMultiCh24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
- for (unsigned i = 0; i < nSamples; ++i) {
- for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i] >> 8;
+ *dst++ = float_from_i32(src[c][i] << leftShift);
}
}
}
@@ -238,8 +178,7 @@
mStreamInfoValid(false),
mWriteRequested(false),
mWriteCompleted(false),
- mErrorStatus((FLAC__StreamDecoderErrorStatus) -1),
- mCopy(nullptr) {
+ mErrorStatus((FLAC__StreamDecoderErrorStatus) -1) {
ALOGV("ctor:");
memset(&mStreamInfo, 0, sizeof(mStreamInfo));
memset(&mWriteHeader, 0, sizeof(mWriteHeader));
@@ -379,6 +318,7 @@
case 8:
case 16:
case 24:
+ case 32: // generally rare, but is supported in the framework
break;
default:
@@ -387,31 +327,6 @@
return ERROR_MALFORMED;
}
- // configure the appropriate copy function, defaulting to trespass
- static const struct {
- unsigned mChannels;
- unsigned mBitsPerSample;
- void (*mCopy)(int16_t *dst, const int * src[kMaxChannels],
- unsigned nSamples, unsigned nChannels);
- } table[] = {
- { 1, 8, copyMono8 },
- { 2, 8, copyStereo8 },
- { 8, 8, copyMultiCh8 },
- { 1, 16, copyMono16 },
- { 2, 16, copyStereo16 },
- { 8, 16, copyMultiCh16 },
- { 1, 24, copyMono24 },
- { 2, 24, copyStereo24 },
- { 8, 24, copyMultiCh24 },
- };
- for (const auto &entry : table) {
- if (entry.mChannels >= getChannels() &&
- entry.mBitsPerSample == getBitsPerSample()) {
- mCopy = entry.mCopy;
- break;
- }
- }
-
// Now we have all metadata blocks.
mBufferPos = 0;
mBufferDataSize = 0;
@@ -420,7 +335,7 @@
}
status_t FLACDecoder::decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
- int16_t *outBuffer, size_t *outBufferLen) {
+ void *outBuffer, size_t *outBufferLen, bool outputFloat) {
ALOGV("decodeOneFrame: input size(%zu)", inBufferLen);
if (!mStreamInfoValid) {
@@ -469,21 +384,33 @@
return ERROR_MALFORMED;
}
- size_t bufferSize = blocksize * getChannels() * sizeof(int16_t);
+ const unsigned channels = getChannels();
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+ const size_t frameSize = channels * sampleSize;
+ size_t bufferSize = blocksize * frameSize;
if (bufferSize > *outBufferLen) {
ALOGW("decodeOneFrame: output buffer holds only partial frame %zu:%zu",
*outBufferLen, bufferSize);
- blocksize = *outBufferLen / (getChannels() * sizeof(int16_t));
- bufferSize = blocksize * getChannels() * sizeof(int16_t);
+ blocksize = *outBufferLen / frameSize;
+ bufferSize = blocksize * frameSize;
}
- if (mCopy == nullptr) {
- ALOGE("decodeOneFrame: format is not supported: channels(%d), BitsPerSample(%d)",
- getChannels(), getBitsPerSample());
- return ERROR_UNSUPPORTED;
- }
// copy PCM from FLAC write buffer to output buffer, with interleaving
- (*mCopy)(outBuffer, mWriteBuffer, blocksize, getChannels());
+
+ const unsigned bitsPerSample = getBitsPerSample();
+ if (outputFloat) {
+ copyToFloat(reinterpret_cast<float*>(outBuffer),
+ mWriteBuffer,
+ blocksize,
+ channels,
+ bitsPerSample);
+ } else {
+ copyTo16Signed(reinterpret_cast<short*>(outBuffer),
+ mWriteBuffer,
+ blocksize,
+ channels,
+ bitsPerSample);
+ }
*outBufferLen = bufferSize;
return OK;
}
diff --git a/media/libstagefright/flac/dec/FLACDecoder.h b/media/libstagefright/flac/dec/FLACDecoder.h
index af419a2..694fccb 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.h
+++ b/media/libstagefright/flac/dec/FLACDecoder.h
@@ -41,7 +41,7 @@
status_t parseMetadata(const uint8_t *inBuffer, size_t inBufferLen);
status_t decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
- int16_t *outBuffer, size_t *outBufferLen);
+ void *outBuffer, size_t *outBufferLen, bool outputFloat = false);
void flush();
virtual ~FLACDecoder();
@@ -89,8 +89,6 @@
// most recent error reported by libFLAC decoder
FLAC__StreamDecoderErrorStatus mErrorStatus;
- void (*mCopy)(int16_t *dst, const int *src[kMaxChannels], unsigned nSamples, unsigned nChannels);
-
status_t init();
// FLAC stream decoder callbacks as C++ instance methods
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 768cbd6..a276722 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -66,7 +66,7 @@
// static
int64_t ALooper::GetNowUs() {
- return systemTime(SYSTEM_TIME_MONOTONIC) / 1000ll;
+ return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
}
ALooper::ALooper()
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index aba44bb..9d1ec1f 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -23,6 +23,7 @@
const char *MEDIA_MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
+const char *MEDIA_MIMETYPE_VIDEO_AV1 = "video/av01";
const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
const char *MEDIA_MIMETYPE_VIDEO_HEVC = "video/hevc";
const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index 8edddcc..e68852d 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -25,6 +25,7 @@
extern const char *MEDIA_MIMETYPE_VIDEO_VP8;
extern const char *MEDIA_MIMETYPE_VIDEO_VP9;
+extern const char *MEDIA_MIMETYPE_VIDEO_AV1;
extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
extern const char *MEDIA_MIMETYPE_VIDEO_HEVC;
extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 86872c5..2ecfa43 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -44,10 +44,10 @@
// static
// Bandwidth Switch Mark Defaults
-const int64_t LiveSession::kUpSwitchMarkUs = 15000000ll;
-const int64_t LiveSession::kDownSwitchMarkUs = 20000000ll;
-const int64_t LiveSession::kUpSwitchMarginUs = 5000000ll;
-const int64_t LiveSession::kResumeThresholdUs = 100000ll;
+const int64_t LiveSession::kUpSwitchMarkUs = 15000000LL;
+const int64_t LiveSession::kDownSwitchMarkUs = 20000000LL;
+const int64_t LiveSession::kUpSwitchMarginUs = 5000000LL;
+const int64_t LiveSession::kResumeThresholdUs = 100000LL;
//TODO: redefine this mark to a fair value
// default buffer underflow mark
@@ -66,9 +66,9 @@
// Bandwidth estimation parameters
static const int32_t kShortTermBandwidthItems = 3;
static const int32_t kMinBandwidthHistoryItems = 20;
- static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec
- static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec
- static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec
+ static const int64_t kMinBandwidthHistoryWindowUs = 5000000LL; // 5 sec
+ static const int64_t kMaxBandwidthHistoryWindowUs = 30000000LL; // 30 sec
+ static const int64_t kMaxBandwidthHistoryAgeUs = 60000000LL; // 60 sec
struct BandwidthEntry {
int64_t mTimestampUs;
@@ -284,7 +284,7 @@
mPrevBufferPercentage(-1),
mCurBandwidthIndex(-1),
mOrigBandwidthIndex(-1),
- mLastBandwidthBps(-1ll),
+ mLastBandwidthBps(-1LL),
mLastBandwidthStable(false),
mBandwidthEstimator(new BandwidthEstimator()),
mMaxWidth(720),
@@ -294,8 +294,8 @@
mSwapMask(0),
mSwitchGeneration(0),
mSubtitleGeneration(0),
- mLastDequeuedTimeUs(0ll),
- mRealTimeBaseUs(0ll),
+ mLastDequeuedTimeUs(0LL),
+ mRealTimeBaseUs(0LL),
mReconfigurationInProgress(false),
mSwitchInProgress(false),
mUpSwitchMark(kUpSwitchMarkUs),
@@ -844,7 +844,7 @@
// (If we don't have that cushion we'd rather cancel and try again.)
int64_t delayUs =
switchUp ?
- (kUnderflowMarkMs * 1000ll + 1000000ll)
+ (kUnderflowMarkMs * 1000LL + 1000000LL)
: 0;
bool needResumeUntil = false;
sp<AMessage> stopParams = msg;
@@ -954,7 +954,7 @@
// static
bool LiveSession::isBandwidthValid(const BandwidthItem &item) {
- static const int64_t kBlacklistWindowUs = 300 * 1000000ll;
+ static const int64_t kBlacklistWindowUs = 300 * 1000000LL;
return item.mLastFailureUs < 0
|| ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs;
}
@@ -1060,7 +1060,7 @@
BandwidthItem item;
item.mPlaylistIndex = i;
- item.mLastFailureUs = -1ll;
+ item.mLastFailureUs = -1LL;
sp<AMessage> meta;
AString uri;
@@ -1114,7 +1114,7 @@
mPlaylist->pickRandomMediaItems();
changeConfiguration(
- 0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
+ 0LL /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
}
void LiveSession::finishDisconnect() {
@@ -1175,7 +1175,7 @@
FetcherInfo info;
info.mFetcher = new PlaylistFetcher(
notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
- info.mDurationUs = -1ll;
+ info.mDurationUs = -1LL;
info.mToBeRemoved = false;
info.mToBeResumed = false;
mFetcherLooper->registerHandler(info.mFetcher);
@@ -1466,7 +1466,7 @@
}
status_t LiveSession::getDuration(int64_t *durationUs) const {
- int64_t maxDurationUs = -1ll;
+ int64_t maxDurationUs = -1LL;
for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
@@ -1592,7 +1592,7 @@
// Delay fetcher removal if not picking tracks, AND old fetcher
// has stream mask that overlaps new variant. (Okay to discard
// old fetcher now, if completely no overlap.)
- if (discardFetcher && timeUs < 0ll && !pickTrack
+ if (discardFetcher && timeUs < 0LL && !pickTrack
&& (fetcher->getStreamTypeMask() & streamMask)) {
discardFetcher = false;
delayRemoval = true;
@@ -1604,7 +1604,7 @@
} else {
float threshold = 0.0f; // default to pause after current block (47Kbytes)
bool disconnect = false;
- if (timeUs >= 0ll) {
+ if (timeUs >= 0LL) {
// seeking, no need to finish fetching
disconnect = true;
} else if (delayRemoval) {
@@ -1620,7 +1620,7 @@
}
sp<AMessage> msg;
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
// skip onChangeConfiguration2 (decoder destruction) if not seeking.
msg = new AMessage(kWhatChangeConfiguration3, this);
} else {
@@ -1654,9 +1654,9 @@
if (!mReconfigurationInProgress) {
int32_t pickTrack = 0;
msg->findInt32("pickTrack", &pickTrack);
- changeConfiguration(-1ll /* timeUs */, -1, pickTrack);
+ changeConfiguration(-1LL /* timeUs */, -1, pickTrack);
} else {
- msg->post(1000000ll); // retry in 1 sec
+ msg->post(1000000LL); // retry in 1 sec
}
}
@@ -1788,7 +1788,7 @@
CHECK(msg->findInt64("timeUs", &timeUs));
CHECK(msg->findInt32("pickTrack", &pickTrack));
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
if (!pickTrack) {
// mSwapMask contains streams that are in both old and new variant,
// (in mNewStreamMask & mStreamMask) but with different URIs
@@ -2062,7 +2062,7 @@
void LiveSession::schedulePollBuffering() {
sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
msg->setInt32("generation", mPollBufferingGeneration);
- msg->post(1000000ll);
+ msg->post(1000000LL);
}
void LiveSession::cancelPollBuffering() {
@@ -2208,13 +2208,13 @@
int64_t readyMarkUs =
(mInPreparationPhase ?
mBufferingSettings.mInitialMarkMs :
- mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
+ mBufferingSettings.mResumePlaybackMarkMs) * 1000LL;
if (bufferedDurationUs > readyMarkUs
|| mPacketSources[i]->isFinished(0)) {
++readyCount;
}
if (!mPacketSources[i]->isFinished(0)) {
- if (bufferedDurationUs < kUnderflowMarkMs * 1000ll) {
+ if (bufferedDurationUs < kUnderflowMarkMs * 1000LL) {
++underflowCount;
}
if (bufferedDurationUs > mUpSwitchMark) {
@@ -2300,7 +2300,7 @@
ssize_t lowestValid = getLowestValidBandwidthIndex();
if (mCurBandwidthIndex > lowestValid) {
cancelBandwidthSwitch();
- changeConfiguration(-1ll, lowestValid);
+ changeConfiguration(-1LL, lowestValid);
return true;
}
}
@@ -2370,7 +2370,7 @@
// if not yet prepared, just restart again with new bw index.
// this is faster and playback experience is cleaner.
changeConfiguration(
- mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
+ mInPreparationPhase ? 0 : -1LL, bandwidthIndex);
return true;
}
}
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index d06d9f2..16179d3 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -258,7 +258,7 @@
mIsEvent(false),
mFirstSeqNumber(-1),
mLastSeqNumber(-1),
- mTargetDurationUs(-1ll),
+ mTargetDurationUs(-1LL),
mDiscontinuitySeq(0),
mDiscontinuityCount(0),
mSelectedIndex(-1) {
@@ -716,7 +716,7 @@
ALOGE("Media playlist missing #EXT-X-TARGETDURATION");
return ERROR_MALFORMED;
}
- mTargetDurationUs = targetDurationSecs * 1000000ll;
+ mTargetDurationUs = targetDurationSecs * 1000000LL;
mFirstSeqNumber = 0;
if (mMeta != NULL) {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 823f90e..562c625 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -50,8 +50,8 @@
namespace android {
// static
-const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll;
-const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
+const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000LL;
+const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000LL;
// LCM of 188 (size of a TS packet) & 1k works well
const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
@@ -152,25 +152,25 @@
mURI(uri),
mFetcherID(id),
mStreamTypeMask(0),
- mStartTimeUs(-1ll),
- mSegmentStartTimeUs(-1ll),
- mDiscontinuitySeq(-1ll),
+ mStartTimeUs(-1LL),
+ mSegmentStartTimeUs(-1LL),
+ mDiscontinuitySeq(-1LL),
mStartTimeUsRelative(false),
- mLastPlaylistFetchTimeUs(-1ll),
- mPlaylistTimeUs(-1ll),
+ mLastPlaylistFetchTimeUs(-1LL),
+ mPlaylistTimeUs(-1LL),
mSeqNumber(-1),
mNumRetries(0),
mStartup(true),
mIDRFound(false),
mSeekMode(LiveSession::kSeekModeExactPosition),
mTimeChangeSignaled(false),
- mNextPTSTimeUs(-1ll),
+ mNextPTSTimeUs(-1LL),
mMonitorQueueGeneration(0),
mSubtitleGeneration(subtitleGeneration),
- mLastDiscontinuitySeq(-1ll),
+ mLastDiscontinuitySeq(-1LL),
mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
mFirstPTSValid(false),
- mFirstTimeUs(-1ll),
+ mFirstTimeUs(-1LL),
mVideoBuffer(new AnotherPacketSource(NULL)),
mSampleAesKeyItemChanged(false),
mThresholdRatio(-1.0f),
@@ -200,7 +200,7 @@
CHECK_GE(seqNumber, firstSeqNumberInPlaylist);
CHECK_LE(seqNumber, lastSeqNumberInPlaylist);
- int64_t segmentStartUs = 0ll;
+ int64_t segmentStartUs = 0LL;
for (int32_t index = 0;
index < seqNumber - firstSeqNumberInPlaylist; ++index) {
sp<AMessage> itemMeta;
@@ -240,13 +240,13 @@
int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const {
int64_t nowUs = ALooper::GetNowUs();
- if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) {
+ if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0LL) {
CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
- return 0ll;
+ return 0LL;
}
if (mPlaylist->isComplete()) {
- return (~0llu >> 1);
+ return (~0LLU >> 1);
}
int64_t targetDurationUs = mPlaylist->getTargetDuration();
@@ -295,7 +295,7 @@
}
int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs;
- return delayUs > 0ll ? delayUs : 0ll;
+ return delayUs > 0LL ? delayUs : 0LL;
}
status_t PlaylistFetcher::decryptBuffer(
@@ -857,7 +857,7 @@
targetDurationUs = mPlaylist->getTargetDuration();
}
- int64_t bufferedDurationUs = 0ll;
+ int64_t bufferedDurationUs = 0LL;
status_t finalResult = OK;
if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
sp<AnotherPacketSource> packetSource =
@@ -870,7 +870,7 @@
// enqueued to prevent us from waiting on a non-existent stream;
// when we cannot make out from the manifest what streams are included in
// a playlist we might assume extra streams.
- bufferedDurationUs = -1ll;
+ bufferedDurationUs = -1LL;
for (size_t i = 0; i < mPacketSources.size(); ++i) {
if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
|| mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
@@ -882,13 +882,13 @@
FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
- if (bufferedDurationUs == -1ll
+ if (bufferedDurationUs == -1LL
|| bufferedStreamDurationUs < bufferedDurationUs) {
bufferedDurationUs = bufferedStreamDurationUs;
}
}
- if (bufferedDurationUs == -1ll) {
- bufferedDurationUs = 0ll;
+ if (bufferedDurationUs == -1LL) {
+ bufferedDurationUs = 0LL;
}
}
@@ -901,12 +901,12 @@
// onDownloadNext();
sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
msg->setInt32("generation", mMonitorQueueGeneration);
- msg->post(1000l);
+ msg->post(1000L);
} else {
// We'd like to maintain buffering above durationToBufferUs, so try
// again when buffer just about to go below durationToBufferUs
// (or after targetDurationUs / 2, whichever is smaller).
- int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
+ int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000LL;
if (delayUs > targetDurationUs / 2) {
delayUs = targetDurationUs / 2;
}
@@ -1073,10 +1073,10 @@
}
}
- mSegmentFirstPTS = -1ll;
+ mSegmentFirstPTS = -1LL;
if (mPlaylist != NULL && mSeqNumber < 0) {
- CHECK_GE(mStartTimeUs, 0ll);
+ CHECK_GE(mStartTimeUs, 0LL);
if (mSegmentStartTimeUs < 0) {
if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
@@ -1379,7 +1379,7 @@
& (LiveSession::STREAMTYPE_AUDIO
| LiveSession::STREAMTYPE_VIDEO))) {
mSession->addBandwidthMeasurement(bytesRead, delayUs);
- if (delayUs > 2000000ll) {
+ if (delayUs > 2000000LL) {
FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
bytesRead, (double)delayUs / 1.0e6);
}
@@ -1553,7 +1553,7 @@
// if the previous fetcher paused in the middle of a segment, we
// want to start at a segment that overlaps the last sample
minDiffUs = -mPlaylist->getTargetDuration();
- maxDiffUs = 0ll;
+ maxDiffUs = 0LL;
} else {
// if the previous fetcher paused at the end of a segment, ideally
// we want to start at the segment that's roughly aligned with its
@@ -1704,7 +1704,7 @@
mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
}
- if (mNextPTSTimeUs >= 0ll) {
+ if (mNextPTSTimeUs >= 0LL) {
sp<AMessage> extra = new AMessage;
// Since we are using absolute timestamps, signal an offset of 0 to prevent
// ATSParser from skewing the timestamps of access units.
@@ -1719,7 +1719,7 @@
mTSParser->signalDiscontinuity(
ATSParser::DISCONTINUITY_TIME, extra);
- mNextPTSTimeUs = -1ll;
+ mNextPTSTimeUs = -1LL;
}
if (mSampleAesKeyItemChanged) {
@@ -1740,7 +1740,7 @@
// setRange to indicate consumed bytes.
buffer->setRange(buffer->offset() + offset, buffer->size() - offset);
- if (mSegmentFirstPTS < 0ll) {
+ if (mSegmentFirstPTS < 0LL) {
// get the smallest first PTS from all streams present in this parser
for (size_t i = mPacketSources.size(); i > 0;) {
i--;
@@ -1764,12 +1764,12 @@
if (meta != NULL) {
int64_t timeUs;
CHECK(meta->findInt64("timeUs", &timeUs));
- if (mSegmentFirstPTS < 0ll || timeUs < mSegmentFirstPTS) {
+ if (mSegmentFirstPTS < 0LL || timeUs < mSegmentFirstPTS) {
mSegmentFirstPTS = timeUs;
}
}
}
- if (mSegmentFirstPTS < 0ll) {
+ if (mSegmentFirstPTS < 0LL) {
// didn't find any TS packet, can return early
return OK;
}
@@ -1988,8 +1988,8 @@
return OK;
}
- if (mNextPTSTimeUs >= 0ll) {
- mNextPTSTimeUs = -1ll;
+ if (mNextPTSTimeUs >= 0LL) {
+ mNextPTSTimeUs = -1LL;
}
// This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio
@@ -2088,17 +2088,17 @@
packetSource->setFormat(meta);
}
- int64_t numSamples = 0ll;
+ int64_t numSamples = 0LL;
int32_t sampleRate;
CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
- int64_t timeUs = (PTS * 100ll) / 9ll;
+ int64_t timeUs = (PTS * 100LL) / 9LL;
if (mStartup && !mFirstPTSValid) {
mFirstPTSValid = true;
mFirstTimeUs = timeUs;
}
- if (mSegmentFirstPTS < 0ll) {
+ if (mSegmentFirstPTS < 0LL) {
mSegmentFirstPTS = timeUs;
if (!mStartTimeUsRelative) {
// Duplicated logic from how we handle .ts playlists.
@@ -2148,7 +2148,7 @@
CHECK_LE(offset + aac_frame_length, buffer->size());
- int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate;
+ int64_t unitTimeUs = timeUs + numSamples * 1000000LL / sampleRate;
offset += aac_frame_length;
// Each AAC frame encodes 1024 samples.
@@ -2209,7 +2209,7 @@
}
void PlaylistFetcher::updateDuration() {
- int64_t durationUs = 0ll;
+ int64_t durationUs = 0LL;
for (size_t index = 0; index < mPlaylist->size(); ++index) {
sp<AMessage> itemMeta;
CHECK(mPlaylist->itemAt(
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index b489183..792a68a 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -43,7 +43,7 @@
}
virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
- off64_t available = (offset >= (off64_t)mSize) ? 0ll : mSize - offset;
+ off64_t available = (offset >= (off64_t)mSize) ? 0LL : mSize - offset;
size_t copy = (available > (off64_t)size) ? size : available;
memcpy(data, mData + offset, copy);
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 9b2853e..9d46d2d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -488,7 +488,8 @@
status_t setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels);
status_t setupFlacCodec(
- bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel);
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+ AudioEncoding encoding);
status_t setupRawAudioFormat(
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels,
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index 6d4c1bf..75b0d8e 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -90,6 +90,9 @@
status_t convertYUV420PlanarUseLibYUV(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertYUV420SemiPlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst);
+
status_t convertYUV420Planar16(
const BitmapParams &src, const BitmapParams &dst);
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index f18940d..1abef8c 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -110,6 +110,7 @@
uint32_t mInterleaveDurationUs;
int32_t mTimeScale;
int64_t mStartTimestampUs;
+ int32_t mStartTimeOffsetBFramesUs; // Start time offset when B Frames are present
int mLatitudex10000;
int mLongitudex10000;
bool mAreGeoTagsAvailable;
@@ -129,6 +130,7 @@
void setStartTimestampUs(int64_t timeUs);
int64_t getStartTimestampUs(); // Not const
+ int32_t getStartTimeOffsetBFramesUs();
status_t startTracks(MetaData *params);
size_t numTracks();
int64_t estimateMoovBoxSize(int32_t bitRate);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 704bfdd..984c23d 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -153,6 +153,35 @@
constexpr int32_t VP9Level61 = 0x1000;
constexpr int32_t VP9Level62 = 0x2000;
+constexpr int32_t AV1Profile0 = 0x01;
+constexpr int32_t AV1Profile1 = 0x02;
+constexpr int32_t AV1Profile2 = 0x04;
+
+constexpr int32_t AV1Level2 = 0x1;
+constexpr int32_t AV1Level21 = 0x2;
+constexpr int32_t AV1Level22 = 0x4;
+constexpr int32_t AV1Level23 = 0x8;
+constexpr int32_t AV1Level3 = 0x10;
+constexpr int32_t AV1Level31 = 0x20;
+constexpr int32_t AV1Level32 = 0x40;
+constexpr int32_t AV1Level33 = 0x80;
+constexpr int32_t AV1Level4 = 0x100;
+constexpr int32_t AV1Level41 = 0x200;
+constexpr int32_t AV1Level42 = 0x400;
+constexpr int32_t AV1Level43 = 0x800;
+constexpr int32_t AV1Level5 = 0x1000;
+constexpr int32_t AV1Level51 = 0x2000;
+constexpr int32_t AV1Level52 = 0x4000;
+constexpr int32_t AV1Level53 = 0x8000;
+constexpr int32_t AV1Level6 = 0x10000;
+constexpr int32_t AV1Level61 = 0x20000;
+constexpr int32_t AV1Level62 = 0x40000;
+constexpr int32_t AV1Level63 = 0x80000;
+constexpr int32_t AV1Level7 = 0x100000;
+constexpr int32_t AV1Level71 = 0x200000;
+constexpr int32_t AV1Level72 = 0x400000;
+constexpr int32_t AV1Level73 = 0x800000;
+
constexpr int32_t HEVCProfileMain = 0x01;
constexpr int32_t HEVCProfileMain10 = 0x02;
constexpr int32_t HEVCProfileMainStill = 0x04;
@@ -273,6 +302,7 @@
// from MediaFormat.java
constexpr char MIMETYPE_VIDEO_VP8[] = "video/x-vnd.on2.vp8";
constexpr char MIMETYPE_VIDEO_VP9[] = "video/x-vnd.on2.vp9";
+constexpr char MIMETYPE_VIDEO_AV1[] = "video/av01";
constexpr char MIMETYPE_VIDEO_AVC[] = "video/avc";
constexpr char MIMETYPE_VIDEO_HEVC[] = "video/hevc";
constexpr char MIMETYPE_VIDEO_MPEG4[] = "video/mp4v-es";
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 84e01f3..ba6631c 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -19,6 +19,7 @@
#define MEDIA_EXTRACTOR_FACTORY_H_
#include <stdio.h>
+#include <unordered_set>
#include <media/IMediaExtractor.h>
@@ -35,6 +36,7 @@
const sp<DataSource> &source, const char *mime = NULL);
static void LoadPlugins(const ::std::string& apkPath);
static status_t dump(int fd, const Vector<String16>& args);
+ static std::unordered_set<std::string> getSupportedTypes();
static void SetLinkedLibraries(const std::string& linkedLibraries);
private:
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 8dc8d38..f34f9b6 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -96,8 +96,7 @@
bool getCachedDuration(int64_t *durationUs, bool *eos) const;
- status_t getAudioPresentations(size_t trackIdx,
- AudioPresentationCollection *presentations) const;
+ status_t getAudioPresentations(size_t trackIdx, AudioPresentationCollection *presentations);
protected:
virtual ~NuMediaExtractor();
diff --git a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
index be911cc..891b9a0 100644
--- a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
+++ b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
@@ -34,8 +34,8 @@
private:
void updateVsync() override;
- long mAppVsyncOffset;
- long mSfVsyncOffset;
+ nsecs_t mAppVsyncOffset;
+ nsecs_t mSfVsyncOffset;
sp<VsyncTracker> mVsyncTracker;
sp<ChoreographerThread> mChoreographerThread;
Mutex mLock;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index e9baa1a..1482072 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -217,6 +217,9 @@
sp<IDescrambler> mDescrambler;
AudioPresentationCollection mAudioPresentations;
+ // Send audio presentations along with access units.
+ void addAudioPresentations(const sp<ABuffer> &buffer);
+
// Flush accumulated payload if necessary --- i.e. at EOS or at the start of
// another payload. event is set if the flushed payload is PES with a sync
// frame.
@@ -758,21 +761,21 @@
// reasonable amount of time. To handle the wrap-around, use fancy math
// to get an extended PTS that is within [-0xffffffff, 0xffffffff]
// of the latest recovered PTS.
- if (mLastRecoveredPTS < 0ll) {
+ if (mLastRecoveredPTS < 0LL) {
// Use the original 33bit number for 1st frame, the reason is that
// if 1st frame wraps to negative that's far away from 0, we could
// never start. Only start wrapping around from 2nd frame.
mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
} else {
mLastRecoveredPTS = static_cast<int64_t>(
- ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000ll)
+ ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000LL)
& 0xfffffffe00000000ull) | PTS_33bit);
// We start from 0, but recovered PTS could be slightly below 0.
// Clamp it to 0 as rest of the pipeline doesn't take negative pts.
// (eg. video is read first and starts at 0, but audio starts at 0xfffffff0)
- if (mLastRecoveredPTS < 0ll) {
+ if (mLastRecoveredPTS < 0LL) {
ALOGI("Clamping negative recovered PTS (%" PRId64 ") to 0", mLastRecoveredPTS);
- mLastRecoveredPTS = 0ll;
+ mLastRecoveredPTS = 0LL;
}
}
@@ -822,7 +825,7 @@
int64_t timeUs = (PTS * 100) / 9;
- if (mParser->mAbsoluteTimeAnchorUs >= 0ll) {
+ if (mParser->mAbsoluteTimeAnchorUs >= 0LL) {
timeUs += mParser->mAbsoluteTimeAnchorUs;
}
@@ -1610,9 +1613,9 @@
detailedError = _detailedError;
});
- if (!returnVoid.isOk()) {
- ALOGE("[stream %d] descramble failed, trans=%s",
- mElementaryPID, returnVoid.description().c_str());
+ if (!returnVoid.isOk() || status != Status::OK) {
+ ALOGE("[stream %d] descramble failed, trans=%s, status=%d",
+ mElementaryPID, returnVoid.description().c_str(), status);
return UNKNOWN_ERROR;
}
@@ -1708,6 +1711,13 @@
return err;
}
+void ATSParser::Stream::addAudioPresentations(const sp<ABuffer> &buffer) {
+ std::ostringstream outStream(std::ios::out);
+ serializeAudioPresentations(mAudioPresentations, &outStream);
+ sp<ABuffer> ap = ABuffer::CreateAsCopy(outStream.str().data(), outStream.str().size());
+ buffer->meta()->setBuffer("audio-presentation-info", ap);
+}
+
void ATSParser::Stream::onPayloadData(
unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */,
unsigned PES_scrambling_control,
@@ -1723,7 +1733,7 @@
ALOGV("onPayloadData mStreamType=0x%02x size: %zu", mStreamType, size);
- int64_t timeUs = 0ll; // no presentation timestamp available.
+ int64_t timeUs = 0LL; // no presentation timestamp available.
if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
timeUs = mProgram->convertPTSToTimestamp(PTS);
}
@@ -1758,8 +1768,10 @@
}
}
mSource = new AnotherPacketSource(meta);
+ if (mAudioPresentations.size() > 0) {
+ addAudioPresentations(accessUnit);
+ }
mSource->queueAccessUnit(accessUnit);
- mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
ALOGV("onPayloadData: created AnotherPacketSource PID 0x%08x of type 0x%02x",
mElementaryPID, mStreamType);
}
@@ -1771,8 +1783,10 @@
if (mSource->getFormat() == NULL) {
mSource->setFormat(mQueue->getFormat());
}
+ if (mAudioPresentations.size() > 0) {
+ addAudioPresentations(accessUnit);
+ }
mSource->queueAccessUnit(accessUnit);
- mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
}
// Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
@@ -1855,10 +1869,10 @@
ATSParser::ATSParser(uint32_t flags)
: mFlags(flags),
- mAbsoluteTimeAnchorUs(-1ll),
+ mAbsoluteTimeAnchorUs(-1LL),
mTimeOffsetValid(false),
- mTimeOffsetUs(0ll),
- mLastRecoveredPTS(-1ll),
+ mTimeOffsetUs(0LL),
+ mLastRecoveredPTS(-1LL),
mNumTSPacketsParsed(0),
mNumPCRs(0) {
mPSISections.add(0 /* PID */, new PSISection);
@@ -1900,7 +1914,7 @@
if ((mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)
&& extra->findInt64(
kATSParserKeyRecentMediaTimeUs, &mediaTimeUs)) {
- if (mAbsoluteTimeAnchorUs >= 0ll) {
+ if (mAbsoluteTimeAnchorUs >= 0LL) {
mediaTimeUs -= mAbsoluteTimeAnchorUs;
}
if (mTimeOffsetValid) {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index e2c5031..62e3a4b 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -35,7 +35,7 @@
namespace android {
-const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs
+const int64_t kNearEOSMarkUs = 2000000LL; // 2 secs
AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
: mIsAudio(false),
@@ -223,6 +223,12 @@
kKeyMpegUserData, 0, mpegUserData->data(), mpegUserData->size());
}
+ sp<ABuffer> ap;
+ if (buffer->meta()->findBuffer("audio-presentation-info", &ap) && ap != NULL) {
+ bufmeta.setData(
+ kKeyAudioPresentationInfo, 0, ap->data(), ap->size());
+ }
+
int32_t cryptoMode;
if (buffer->meta()->findInt32("cryptoMode", &cryptoMode)) {
int32_t cryptoKey;
@@ -293,7 +299,7 @@
if (buffer->meta()->findInt32("discontinuity", &discontinuity)){
ALOGV("queueing a discontinuity with queueAccessUnit");
- mLastQueuedTimeUs = 0ll;
+ mLastQueuedTimeUs = 0LL;
mEOSResult = OK;
mLatestEnqueuedMeta = NULL;
@@ -697,23 +703,4 @@
return firstMeta;
}
-void AnotherPacketSource::convertAudioPresentationInfoToMetadata(
- const AudioPresentationCollection& presentations) {
- sp<MetaData> meta = getFormat();
- if (meta == NULL) {
- return;
- }
- if (presentations.empty()) {
- // Clear audio presentation info in metadata.
- Mutex::Autolock autoLock(mLock);
- meta->remove(kKeyAudioPresentationInfo);
- } else {
- std::ostringstream outStream(std::ios::out);
- serializeAudioPresentations(presentations, &outStream);
- Mutex::Autolock autoLock(mLock);
- meta->setData(kKeyAudioPresentationInfo, MetaData::TYPE_NONE,
- outStream.str().data(), outStream.str().size());
- }
-}
-
} // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 57a6c33..f4a6acb 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -85,8 +85,6 @@
void trimBuffersAfterMeta(const sp<AMessage> &meta);
sp<AMessage> trimBuffersBeforeMeta(const sp<AMessage> &meta);
- void convertAudioPresentationInfoToMetadata(const AudioPresentationCollection &presentations);
-
protected:
virtual ~AnotherPacketSource();
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index fb8b9fd..b91edcd 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1111,7 +1111,7 @@
memcpy(accessUnit->data(), mBuffer->data() + 4, payloadSize);
int64_t timeUs = fetchTimestamp(payloadSize + 4);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1147,7 +1147,7 @@
return NULL;
}
- if (info.mTimestampUs < 0ll) {
+ if (info.mTimestampUs < 0LL) {
ALOGE("Negative info.mTimestampUs");
return NULL;
}
@@ -1317,7 +1317,7 @@
}
- if (timeUs == 0ll) {
+ if (timeUs == 0LL) {
ALOGV("Returning 0 timestamp");
}
@@ -1460,7 +1460,7 @@
mBuffer->setRange(0, mBuffer->size() - nextScan);
int64_t timeUs = fetchTimestamp(nextScan);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1545,7 +1545,7 @@
mBuffer->setRange(0, mBuffer->size() - frameSize);
int64_t timeUs = fetchTimestamp(frameSize);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1732,7 +1732,7 @@
mBuffer->setRange(0, mBuffer->size() - offset);
int64_t timeUs = fetchTimestamp(offset);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1929,7 +1929,7 @@
mBuffer->setRange(0, size);
int64_t timeUs = fetchTimestamp(offset);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeus");
return NULL;
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 68b375a..d7aacff 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -355,9 +355,9 @@
mQuirks(0),
mBufferIDCount(0),
mRestorePtsFailed(false),
- mMaxTimestampGapUs(0ll),
- mPrevOriginalTimeUs(-1ll),
- mPrevModifiedTimeUs(-1ll)
+ mMaxTimestampGapUs(0LL),
+ mPrevOriginalTimeUs(-1LL),
+ mPrevModifiedTimeUs(-1LL)
{
mName = ADebug::GetDebugName(name);
DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
@@ -1948,7 +1948,7 @@
int64_t OMXNodeInstance::getCodecTimestamp(OMX_TICKS timestamp) {
int64_t originalTimeUs = timestamp;
- if (mMaxTimestampGapUs > 0ll) {
+ if (mMaxTimestampGapUs > 0LL) {
/* Cap timestamp gap between adjacent frames to specified max
*
* In the scenario of cast mirroring, encoding could be suspended for
@@ -1956,7 +1956,7 @@
* where encoder's rate control logic produces huge frames after a
* long period of suspension.
*/
- if (mPrevOriginalTimeUs >= 0ll) {
+ if (mPrevOriginalTimeUs >= 0LL) {
int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
timestamp = (timestampGapUs < mMaxTimestampGapUs ?
timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
@@ -1964,7 +1964,7 @@
ALOGV("IN timestamp: %lld -> %lld",
static_cast<long long>(originalTimeUs),
static_cast<long long>(timestamp));
- } else if (mMaxTimestampGapUs < 0ll) {
+ } else if (mMaxTimestampGapUs < 0LL) {
/*
* Apply a fixed timestamp gap between adjacent frames.
*
@@ -1972,7 +1972,7 @@
* on frames could go forward or backward. Some encoders may silently
* drop frames when it goes backward (or even stay unchanged).
*/
- if (mPrevOriginalTimeUs >= 0ll) {
+ if (mPrevOriginalTimeUs >= 0LL) {
timestamp = mPrevModifiedTimeUs - mMaxTimestampGapUs;
}
ALOGV("IN timestamp: %lld -> %lld",
@@ -1983,7 +1983,7 @@
mPrevOriginalTimeUs = originalTimeUs;
mPrevModifiedTimeUs = timestamp;
- if (mMaxTimestampGapUs != 0ll && !mRestorePtsFailed) {
+ if (mMaxTimestampGapUs != 0LL && !mRestorePtsFailed) {
mOriginalTimeUs.add(timestamp, originalTimeUs);
}
@@ -2016,7 +2016,7 @@
void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
Mutex::Autolock autoLock(mLock);
- if (mMaxTimestampGapUs == 0ll || mRestorePtsFailed) {
+ if (mMaxTimestampGapUs == 0LL || mRestorePtsFailed) {
return;
}
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index b187035..1b8493a 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -150,6 +150,8 @@
"video_decoder.vp8", "video_encoder.vp8" },
{ MEDIA_MIMETYPE_VIDEO_VP9,
"video_decoder.vp9", "video_encoder.vp9" },
+ { MEDIA_MIMETYPE_VIDEO_AV1,
+ "video_decoder.av1", "video_encoder.av1" },
{ MEDIA_MIMETYPE_AUDIO_RAW,
"audio_decoder.raw", "audio_encoder.raw" },
{ MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 201a5df..b964bc0 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -417,7 +417,7 @@
if (sessionDesc->getDurationUs(&durationUs)) {
mFormat->setInt64(kKeyDuration, durationUs);
} else {
- mFormat->setInt64(kKeyDuration, -1ll);
+ mFormat->setInt64(kKeyDuration, -1LL);
}
mInitCheck = OK;
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
index c7a65c2..befc226 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.cpp
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -36,7 +36,7 @@
if (status == WRONG_SEQUENCE_NUMBER) {
if (mFirstFailureTimeUs >= 0) {
- if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000ll) {
+ if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000LL) {
mFirstFailureTimeUs = -1;
// LOG(VERBOSE) << "waited too long for packet.";
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index a86ab74..6a4706d 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -50,7 +50,7 @@
}
// static
-const int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTPConnection::kSelectTimeoutUs = 1000LL;
struct ARTPConnection::StreamInfo {
int mRTPSocket;
@@ -118,7 +118,7 @@
bumpSocketBufferSize(*rtcpSocket);
/* rand() * 1000 may overflow int type, use long long */
- unsigned start = (unsigned)((rand()* 1000ll)/RAND_MAX) + 15550;
+ unsigned start = (unsigned)((rand()* 1000LL)/RAND_MAX) + 15550;
start &= ~1;
for (unsigned port = start; port < 65536; port += 2) {
@@ -307,7 +307,7 @@
int64_t nowUs = ALooper::GetNowUs();
if (mLastReceiverReportTimeUs <= 0
- || mLastReceiverReportTimeUs + 5000000ll <= nowUs) {
+ || mLastReceiverReportTimeUs + 5000000LL <= nowUs) {
sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
List<StreamInfo>::iterator it = mStreams.begin();
while (it != mStreams.end()) {
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 4827cd2..4afa6f4 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -180,7 +180,7 @@
}
int64_t nowUs = ALooper::GetNowUs();
- if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000ll > nowUs) {
+ if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000LL > nowUs) {
// Send FIR requests at most every 5 secs.
return;
}
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 49e01c0..4f86773 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -420,10 +420,10 @@
uint64_t ARTPWriter::GetNowNTP() {
uint64_t nowUs = ALooper::GetNowUs();
- nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+ nowUs += ((70LL * 365 + 17) * 24) * 60 * 60 * 1000000LL;
- uint64_t hi = nowUs / 1000000ll;
- uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
+ uint64_t hi = nowUs / 1000000LL;
+ uint64_t lo = ((1LL << 32) * (nowUs % 1000000LL)) / 1000000LL;
return (hi << 32) | lo;
}
@@ -576,7 +576,7 @@
int64_t timeUs;
CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
- uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
const uint8_t *mediaData =
(const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
@@ -671,7 +671,7 @@
int64_t timeUs;
CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
- uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
const uint8_t *mediaData =
(const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 33c1c18..20cb415 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -39,7 +39,7 @@
namespace android {
// static
-const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTSPConnection::kSelectTimeoutUs = 1000LL;
// static
const AString ARTSPConnection::sUserAgent =
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 23269af..4b6f928 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -364,14 +364,14 @@
// adjust time-stamps after pause/resume
if (mResumed) {
int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
- CHECK_GE(durExcludingEarlierPausesUs, 0ll);
+ CHECK_GE(durExcludingEarlierPausesUs, 0LL);
int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
CHECK_GE(pausedDurationUs, lastDurationUs);
previousPausedDurationUs += pausedDurationUs - lastDurationUs;
mResumed = false;
}
timestampUs -= previousPausedDurationUs;
- CHECK_GE(timestampUs, 0ll);
+ CHECK_GE(timestampUs, 0LL);
int32_t isSync = false;
md.findInt32(kKeyIsSyncFrame, &isSync);
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index f7597db..1fbb85e 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -20,7 +20,7 @@
libmediaplayerservice \
libutils \
libbinder \
- libicuuc \
+ libandroidicu \
android.hardware.media.omx@1.0 \
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index b86ab42..1a0c3b1 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -357,8 +357,10 @@
it != mAcquiredImages.end(); it++) {
AImage* image = *it;
Mutex::Autolock _l(image->mLock);
- releaseImageLocked(image, /*releaseFenceFd*/-1);
+ // Do not alter mAcquiredImages while we are iterating on it
+ releaseImageLocked(image, /*releaseFenceFd*/-1, /*clearCache*/false);
}
+ mAcquiredImages.clear();
// Delete Buffer Items
for (auto it = mBuffers.begin();
@@ -497,7 +499,7 @@
}
void
-AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd) {
+AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache) {
BufferItem* buffer = image->mBuffer;
if (buffer == nullptr) {
// This should not happen, but is not fatal
@@ -521,6 +523,10 @@
image->mLockedBuffer = nullptr;
image->mIsClosed = true;
+ if (!clearCache) {
+ return;
+ }
+
bool found = false;
// cleanup acquired image list
for (auto it = mAcquiredImages.begin();
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 78152d2..e328cb1 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -88,7 +88,7 @@
media_status_t acquireImageLocked(/*out*/AImage** image, /*out*/int* fenceFd);
// Called by AImage/~AImageReader to close image. Caller is responsible to grab AImage::mLock
- void releaseImageLocked(AImage* image, int releaseFenceFd);
+ void releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache = true);
static int getBufferWidth(BufferItem* buffer);
static int getBufferHeight(BufferItem* buffer);
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index f697bd1..8296598 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -448,6 +448,16 @@
meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
}
+ const void *audioPresentationsPointer;
+ size_t audioPresentationsLength;
+ if (sampleMeta->findData(
+ kKeyAudioPresentationInfo, &dataType,
+ &audioPresentationsPointer, &audioPresentationsLength)) {
+ sp<ABuffer> audioPresentationsData = ABuffer::CreateAsCopy(
+ audioPresentationsPointer, audioPresentationsLength);
+ meta->setBuffer(AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, audioPresentationsData);
+ }
+
return AMEDIA_OK;
}
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 92d3aef..fcb706d 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -298,7 +298,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_IV = "crypto-iv";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_KEY = "crypto-key";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_MODE = "crypto-mode";
-EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-encrypted-sizes";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-plain-sizes";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK = "crypto-skip-byte-block";
EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
diff --git a/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl b/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
index 74897f7..433b12f 100644
--- a/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
+++ b/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
@@ -48,9 +48,9 @@
PendingIntent getLaunchPendingIntent();
long getFlags();
ParcelableVolumeInfo getVolumeAttributes();
- void adjustVolume(String packageName, ISessionControllerCallback caller,
+ void adjustVolume(String packageName, String opPackageName, ISessionControllerCallback caller,
boolean asSystemService, int direction, int flags);
- void setVolumeTo(String packageName, ISessionControllerCallback caller,
+ void setVolumeTo(String packageName, String opPackageName, ISessionControllerCallback caller,
int value, int flags);
// These commands are for the TransportControls
diff --git a/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl b/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
index 3578c16..d6c226f 100644
--- a/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
+++ b/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
@@ -17,7 +17,6 @@
import android.content.ComponentName;
import android.media.IRemoteVolumeController;
-import android.media.ISessionTokensListener;
import android.media.session.IActiveSessionsListener;
import android.media.session.ICallback;
import android.media.session.IOnMediaKeyListener;
@@ -36,9 +35,10 @@
List<IBinder> getSessions(in ComponentName compName, int userId);
void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
boolean needWakeLock);
- void dispatchVolumeKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
- int stream, boolean musicOnly);
- void dispatchAdjustVolume(String packageName, int suggestedStream, int delta, int flags);
+ void dispatchVolumeKeyEvent(String packageName, String opPackageName, boolean asSystemService,
+ in KeyEvent keyEvent, int stream, boolean musicOnly);
+ void dispatchAdjustVolume(String packageName, String opPackageName, int suggestedStream,
+ int delta, int flags);
void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
int userId);
void removeSessionsListener(in IActiveSessionsListener listener);
@@ -55,12 +55,4 @@
// MediaSession2
boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
- boolean createSession2(in Bundle sessionToken);
- void destroySession2(in Bundle sessionToken);
- List<Bundle> getSessionTokens(boolean activeSessionOnly, boolean sessionServiceOnly,
- String packageName);
-
- void addSessionTokensListener(in ISessionTokensListener listener, int userId,
- String packageName);
- void removeSessionTokensListener(in ISessionTokensListener listener, String packageName);
}
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaController.java b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
index 8c3a013..65682a8 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaController.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
@@ -153,9 +153,7 @@
return false;
}
try {
- //TODO(b/119748678): Resolve mContext.getOpPackageName() through this file.
- // Temporarilly it's replaced with "mContext.getOpPackageName()" for compiling.
- return mSessionBinder.sendMediaButton("mContext.getOpPackageName()", mCbStub,
+ return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
asSystemService, keyEvent);
} catch (RemoteException e) {
// System is dead. =(
@@ -188,8 +186,9 @@
break;
}
try {
- mSessionBinder.adjustVolume("mContext.getOpPackageName()", mCbStub, true,
- direction, AudioManager.FLAG_SHOW_UI);
+ mSessionBinder.adjustVolume(mContext.getPackageName(),
+ mContext.getOpPackageName(), mCbStub, true, direction,
+ AudioManager.FLAG_SHOW_UI);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
@@ -199,8 +198,8 @@
final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
| AudioManager.FLAG_FROM_KEY;
try {
- mSessionBinder.adjustVolume("mContext.getOpPackageName()", mCbStub, true, 0,
- flags);
+ mSessionBinder.adjustVolume(mContext.getPackageName(),
+ mContext.getOpPackageName(), mCbStub, true, 0, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
@@ -369,7 +368,8 @@
*/
public void setVolumeTo(int value, int flags) {
try {
- mSessionBinder.setVolumeTo("mContext.getOpPackageName()", mCbStub, value, flags);
+ mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(),
+ mCbStub, value, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling setVolumeTo.", e);
}
@@ -390,8 +390,8 @@
*/
public void adjustVolume(int direction, int flags) {
try {
- mSessionBinder.adjustVolume("mContext.getOpPackageName()", mCbStub, false, direction,
- flags);
+ mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
+ mCbStub, false, direction, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
}
@@ -457,7 +457,7 @@
throw new IllegalArgumentException("command cannot be null or empty");
}
try {
- mSessionBinder.sendCommand("mContext.getOpPackageName()", mCbStub, command, args, cb);
+ mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCommand.", e);
}
@@ -523,7 +523,7 @@
if (!mCbRegistered) {
try {
- mSessionBinder.registerCallbackListener("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
mCbRegistered = true;
} catch (RemoteException e) {
Log.e(TAG, "Dead object in registerCallback", e);
@@ -670,7 +670,7 @@
*/
public void prepare() {
try {
- mSessionBinder.prepare("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare.", e);
}
@@ -694,7 +694,7 @@
"You must specify a non-empty String for prepareFromMediaId.");
}
try {
- mSessionBinder.prepareFromMediaId("mContext.getOpPackageName()", mCbStub, mediaId,
+ mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
@@ -721,7 +721,7 @@
query = "";
}
try {
- mSessionBinder.prepareFromSearch("mContext.getOpPackageName()", mCbStub, query,
+ mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
@@ -746,7 +746,7 @@
"You must specify a non-empty Uri for prepareFromUri.");
}
try {
- mSessionBinder.prepareFromUri("mContext.getOpPackageName()", mCbStub, uri, extras);
+ mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
}
@@ -757,7 +757,7 @@
*/
public void play() {
try {
- mSessionBinder.play("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.play(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play.", e);
}
@@ -776,7 +776,7 @@
"You must specify a non-empty String for playFromMediaId.");
}
try {
- mSessionBinder.playFromMediaId("mContext.getOpPackageName()", mCbStub, mediaId,
+ mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
@@ -799,7 +799,7 @@
query = "";
}
try {
- mSessionBinder.playFromSearch("mContext.getOpPackageName()", mCbStub, query, extras);
+ mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + query + ").", e);
}
@@ -818,7 +818,7 @@
"You must specify a non-empty Uri for playFromUri.");
}
try {
- mSessionBinder.playFromUri("mContext.getOpPackageName()", mCbStub, uri, extras);
+ mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + uri + ").", e);
}
@@ -830,7 +830,7 @@
*/
public void skipToQueueItem(long id) {
try {
- mSessionBinder.skipToQueueItem("mContext.getOpPackageName()", mCbStub, id);
+ mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
}
@@ -842,7 +842,7 @@
*/
public void pause() {
try {
- mSessionBinder.pause("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.pause(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling pause.", e);
}
@@ -854,7 +854,7 @@
*/
public void stop() {
try {
- mSessionBinder.stop("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.stop(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling stop.", e);
}
@@ -867,7 +867,7 @@
*/
public void seekTo(long pos) {
try {
- mSessionBinder.seekTo("mContext.getOpPackageName()", mCbStub, pos);
+ mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling seekTo.", e);
}
@@ -879,7 +879,7 @@
*/
public void fastForward() {
try {
- mSessionBinder.fastForward("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling fastForward.", e);
}
@@ -890,7 +890,7 @@
*/
public void skipToNext() {
try {
- mSessionBinder.next("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.next(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling next.", e);
}
@@ -902,7 +902,7 @@
*/
public void rewind() {
try {
- mSessionBinder.rewind("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rewind.", e);
}
@@ -913,7 +913,7 @@
*/
public void skipToPrevious() {
try {
- mSessionBinder.previous("mContext.getOpPackageName()", mCbStub);
+ mSessionBinder.previous(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling previous.", e);
}
@@ -928,7 +928,7 @@
*/
public void setRating(Rating rating) {
try {
- mSessionBinder.rate("mContext.getOpPackageName()", mCbStub, rating);
+ mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rate.", e);
}
@@ -963,7 +963,7 @@
throw new IllegalArgumentException("CustomAction cannot be null.");
}
try {
- mSessionBinder.sendCustomAction("mContext.getOpPackageName()", mCbStub, action, args);
+ mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCustomAction.", e);
}
@@ -1142,8 +1142,7 @@
private boolean mRegistered = false;
public MessageHandler(Looper looper, MediaController.Callback cb) {
- //TODO:(b/119539849) Uncomment below line and resolve the error.
- // super(looper, null, true);
+ super(looper);
mCallback = cb;
}
@@ -1182,6 +1181,7 @@
public void post(int what, Object obj, Bundle data) {
Message msg = obtainMessage(what, obj);
+ msg.setAsynchronous(true);
msg.setData(data);
msg.sendToTarget();
}
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
index 943843d..73e16a6 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
@@ -1458,8 +1458,7 @@
private RemoteUserInfo mCurrentControllerInfo;
public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
- //TODO:(b/119539849) Uncomment below line and resolve the error.
- //super(looper, null, true);
+ super(looper);
mCallback = callback;
mCallback.mHandler = this;
}
@@ -1467,6 +1466,7 @@
public void post(RemoteUserInfo caller, int what, Object obj, Bundle data, long delayMs) {
Pair<RemoteUserInfo, Object> objWithCaller = Pair.create(caller, obj);
Message msg = obtainMessage(what, objWithCaller);
+ msg.setAsynchronous(true);
msg.setData(data);
if (delayMs > 0) {
sendMessageDelayed(msg, delayMs);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c6941c0..989e6eb 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3850,6 +3850,7 @@
type |= patch->sinks[i].ext.device.type;
}
+ audio_port_handle_t sinkPortId = patch->sinks[0].id;
#ifdef ADD_BATTERY_DATA
// when changing the audio output device, call addBatteryData to notify
// the change
@@ -3879,7 +3880,7 @@
// mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when
// the thread is created so that the first patch creation triggers an ioConfigChanged callback
- bool configChanged = mPrevOutDevice != type;
+ bool configChanged = (mPrevOutDevice != type) || (mDeviceId != sinkPortId);
mOutDevice = type;
mPatch = *patch;
@@ -3908,6 +3909,7 @@
}
if (configChanged) {
mPrevOutDevice = type;
+ mDeviceId = sinkPortId;
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
return status;
@@ -8145,6 +8147,7 @@
// store new device and send to effects
mInDevice = patch->sources[0].ext.device.type;
+ audio_port_handle_t deviceId = patch->sources[0].id;
mPatch = *patch;
for (size_t i = 0; i < mEffectChains.size(); i++) {
mEffectChains[i]->setDevice_l(mInDevice);
@@ -8186,9 +8189,10 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if (mInDevice != mPrevInDevice) {
+ if ((mInDevice != mPrevInDevice) || (mDeviceId != deviceId)) {
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
mPrevInDevice = mInDevice;
+ mDeviceId = deviceId;
}
return status;
@@ -8285,7 +8289,7 @@
audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
: ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
mSessionId(AUDIO_SESSION_NONE),
- mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
+ mPortId(AUDIO_PORT_HANDLE_NONE),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
mActiveTracks(&this->mLocalLog),
mHalVolFloat(-1.0f), // Initialize to illegal value so it always gets set properly later.
@@ -8769,7 +8773,7 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if (isOutput() && mPrevOutDevice != mOutDevice) {
+ if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
mPrevOutDevice = type;
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
sp<MmapStreamCallback> callback = mCallback.promote();
@@ -8780,7 +8784,7 @@
}
mDeviceId = deviceId;
}
- if (!isOutput() && mPrevInDevice != mInDevice) {
+ if (!isOutput() && (mPrevInDevice != mInDevice || mDeviceId != deviceId)) {
mPrevInDevice = type;
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
sp<MmapStreamCallback> callback = mCallback.promote();
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index e8b2158..5d06773 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -485,6 +485,10 @@
audio_devices_t mPrevOutDevice; // previous output device
audio_devices_t mPrevInDevice; // previous input device
struct audio_patch mPatch;
+ /**
+ * @brief mDeviceId current device port unique identifier
+ */
+ audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_source_t mAudioSource;
const audio_io_handle_t mId;
@@ -1704,7 +1708,6 @@
audio_attributes_t mAttr;
audio_session_t mSessionId;
- audio_port_handle_t mDeviceId;
audio_port_handle_t mPortId;
wp<MmapStreamCallback> mCallback;
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index bfa1b5e..ebb4f3b 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -51,6 +51,7 @@
libcutils \
libutils \
liblog \
+ libaudioclient \
libsoundtrigger
ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
@@ -85,7 +86,7 @@
LOCAL_SHARED_LIBRARIES += libmedia_helper
LOCAL_SHARED_LIBRARIES += libmediametrics
-LOCAL_SHARED_LIBRARIES += libhidlbase libicuuc libxml2
+LOCAL_SHARED_LIBRARIES += libhidlbase libxml2
ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index ad12a90..1c2b9d7 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -210,6 +210,10 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes) = 0;
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ = 0;
+ virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId,
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index d0b4973..e5ebab7 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -24,7 +24,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libicuuc",
"liblog",
"libmedia",
"libutils",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 96c00ea..955e87b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -80,6 +80,10 @@
status_t getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix);
+ status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+ status_t removeUidDeviceAffinities(uid_t uid);
+ status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
+
void dump(String8 *dst) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 3cf8014..776d98f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -340,6 +340,87 @@
return NO_ERROR;
}
+status_t AudioPolicyMixCollection::setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ // remove existing rules for this uid
+ removeUidDeviceAffinities(uid);
+
+ // for each player mix: add a rule to match or exclude the uid based on the device
+ for (size_t i = 0; i < size(); i++) {
+ const AudioMix *mix = valueAt(i)->getMix();
+ if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ continue;
+ }
+ // check if this mix goes to a device in the list of devices
+ bool deviceMatch = false;
+ for (size_t j = 0; j < devices.size(); j++) {
+ if (devices[j].mType == mix->mDeviceType
+ && devices[j].mAddress == mix->mDeviceAddress) {
+ deviceMatch = true;
+ break;
+ }
+ }
+ if (!deviceMatch) {
+ // this mix doesn't go to one of the listed devices for the given uid,
+ // modify its rules to exclude the uid
+ mix->excludeUid(uid);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::removeUidDeviceAffinities(uid_t uid) {
+ // for each player mix: remove existing rules that match or exclude this uid
+ for (size_t i = 0; i < size(); i++) {
+ bool foundUidRule = false;
+ AudioMix *mix = valueAt(i)->getMix();
+ if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ continue;
+ }
+ std::vector<size_t> criteriaToRemove;
+ for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+ const uint32_t rule = mix->mCriteria[j].mRule;
+ // is this rule affecting the uid?
+ if (rule == RULE_EXCLUDE_UID
+ && uid == mix->mCriteria[j].mValue.mUid) {
+ foundUidRule = true;
+ criteriaToRemove.push_back(j);
+ }
+ }
+ if (foundUidRule) {
+ for (size_t j = criteriaToRemove.size() - 1; j >= 0; j--) {
+ mix->mCriteria.removeAt(criteriaToRemove[j]);
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::getDevicesForUid(uid_t uid,
+ Vector<AudioDeviceTypeAddr>& devices) const {
+ // for each player mix: find rules that don't exclude this uid, and add the device to the list
+ for (size_t i = 0; i < size(); i++) {
+ bool ruleAllowsUid = true;
+ AudioMix *mix = valueAt(i)->getMix();
+ if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ continue;
+ }
+ for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+ const uint32_t rule = mix->mCriteria[j].mRule;
+ if (rule == RULE_EXCLUDE_UID
+ && uid == mix->mCriteria[j].mValue.mUid) {
+ ruleAllowsUid = false;
+ break;
+ }
+ }
+ if (ruleAllowsUid) {
+ devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress));
+ }
+ }
+ return NO_ERROR;
+}
+
void AudioPolicyMixCollection::dump(String8 *dst) const
{
dst->append("\nAudio Policy Mix:\n");
diff --git a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
index a597e87..efc69da 100644
--- a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
+++ b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
@@ -19,10 +19,8 @@
class AudioPolicyManagerInterface;
class AudioPolicyPluginInterface;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
class Engine;
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
index baaefd2..7631976 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
@@ -7,15 +7,19 @@
#
################################################################################################
-ifeq (1, 0)
-
LOCAL_PATH := $(call my-dir)
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
PFW_CORE := external/parameter-framework
-BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
+#@TODO: upstream new domain generator
+#BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
+
##################################################################
# CONFIGURATION FILES
##################################################################
@@ -25,7 +29,8 @@
LOCAL_MODULE := ParameterFrameworkConfigurationPolicy.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework
LOCAL_SRC_FILES := $(LOCAL_MODULE).in
AUDIO_PATTERN = @TUNING_ALLOWED@
@@ -46,7 +51,8 @@
LOCAL_MODULE := PolicyClass.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
@@ -54,12 +60,12 @@
LOCAL_MODULE := PolicySubsystem.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_REQUIRED_MODULES := \
PolicySubsystem-CommonTypes.xml \
- PolicySubsystem-Volume.xml \
- libpolicy-subsystem \
+ libpolicy-subsystem
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
@@ -67,7 +73,8 @@
LOCAL_MODULE := PolicySubsystem-CommonTypes.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
@@ -76,15 +83,16 @@
LOCAL_MODULE := parameter-framework.policy
LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
ifeq ($(pfw_rebuild_settings),true)
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
PFW_EDD_FILES := \
$(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
$(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -100,6 +108,17 @@
$(LOCAL_PATH)/Settings/device_for_input_source.pfw \
$(LOCAL_PATH)/Settings/volumes.pfw
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(PFW_EDD_FILES)
+
+
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
+
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+
include $(BUILD_PFW_SETTINGS)
else
# Use the existing file
@@ -107,19 +126,27 @@
include $(BUILD_PREBUILT)
endif # pfw_rebuild_settings
+endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 0)
+
######### Policy PFW Settings - No Output #########
+ifeq (0, 1)
+
include $(CLEAR_VARS)
LOCAL_MODULE := parameter-framework.policy.no-output
LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoOutputDevice.xml
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
PFW_EDD_FILES := \
$(LOCAL_PATH)/SettingsNoOutput/device_for_strategies.pfw \
$(LOCAL_PATH)/Settings/strategy_for_stream.pfw \
@@ -128,20 +155,26 @@
$(LOCAL_PATH)/Settings/volumes.pfw
include $(BUILD_PFW_SETTINGS)
-
+endif # ifeq (0, 1)
######### Policy PFW Settings - No Input #########
+ifeq (0, 1)
+
include $(CLEAR_VARS)
LOCAL_MODULE := parameter-framework.policy.no-input
LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoInputDevice.xml
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
PFW_EDD_FILES := \
$(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
$(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -160,3 +193,9 @@
include $(BUILD_PFW_SETTINGS)
endif # ifeq (1, 0)
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#######################################################################
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
index f5615cd..f80a07f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- SystemClassName="Policy" ServerPort="5019" TuningAllowed="@TUNING_ALLOWED@">
+ SystemClassName="Policy" ServerPort="/dev/socket/audioserver/policy_debug"
+ TuningAllowed="@TUNING_ALLOWED@">
<SubsystemPlugins>
<Location Folder="">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
index b43f83b..0710441 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
@@ -8472,7 +8472,7 @@
<Configurations>
<Configuration Name="Sonification">
<CompoundRule Type="All">
- <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="RingTone"/>
+ <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="Ringtone"/>
</CompoundRule>
</Configuration>
<Configuration Name="Phone">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
index b3115e7..fbea9e2 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
@@ -24,7 +24,7 @@
# In case of Ring or Alarm stream type active, switching to sonification
# @todo: handle this dynamic case. As a WA, using Ringtone mode...
#
- TelephonyMode Is RingTone
+ TelephonyMode Is Ringtone
/Policy/policy/usages/assistance_accessibility/applicable_strategy/strategy = sonification
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
index 917d4a7..f923610 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
@@ -9,7 +9,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -37,7 +37,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -65,7 +65,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -93,7 +93,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -121,7 +121,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -149,7 +149,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -177,7 +177,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -205,7 +205,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -233,7 +233,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
index 461e44a..daa7f68 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
@@ -37,6 +37,10 @@
<BitParameter Name="speaker_safe" Size="1" Pos="22"/>
<BitParameter Name="ip" Size="1" Pos="23"/>
<BitParameter Name="bus" Size="1" Pos="24"/>
+ <BitParameter Name="proxy" Size="1" Pos="25"/>
+ <BitParameter Name="usb_headset" Size="1" Pos="26"/>
+ <BitParameter Name="hearing_aid" Size="1" Pos="27"/>
+ <BitParameter Name="echo_canceller" Size="1" Pos="28"/>
<BitParameter Name="stub" Size="1" Pos="30"/>
</BitParameterBlock>
</ComponentType>
@@ -67,6 +71,9 @@
<BitParameter Name="loopback" Size="1" Pos="18"/>
<BitParameter Name="ip" Size="1" Pos="19"/>
<BitParameter Name="bus" Size="1" Pos="20"/>
+ <BitParameter Name="proxy" Size="1" Pos="21"/>
+ <BitParameter Name="usb_headset" Size="1" Pos="22"/>
+ <BitParameter Name="bluetooth_ble" Size="1" Pos="23"/>
<BitParameter Name="stub" Size="1" Pos="30"/>
</BitParameterBlock>
</ComponentType>
@@ -144,7 +151,7 @@
<!--#################### STRATEGY COMMON TYPES BEGIN ####################-->
- <ComponentType Name="StrategyConfig" Mapping="Strategy:'%1'">
+ <ComponentType Name="StrategyConfig" Mapping="Strategy">
<Component Name="selected_output_devices" Type="OutputDevicesMask"/>
</ComponentType>
@@ -170,7 +177,7 @@
</EnumParameter>
</ComponentType>
- <ComponentType Name="Stream">
+ <ComponentType Name="Stream" Mapping="Stream">
<Component Name="applicable_strategy" Type="Strategy"/>
<Component Name="applicable_volume_profile" Type="VolumeProfileType"
Description="Volume profile followed by a given stream type."/>
@@ -181,7 +188,7 @@
<!--#################### USAGE COMMON TYPES BEGIN ####################-->
<ComponentType Name="Usage">
- <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage:'%1'"/>
+ <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage"/>
</ComponentType>
<!--#################### USAGE COMMON TYPES END ####################-->
@@ -190,7 +197,7 @@
<ComponentType Name="InputSource">
<Component Name="applicable_input_device" Type="InputDevicesMask"
- Mapping="InputSource:'%1'" Description="Selected Input device"/>
+ Mapping="InputSource" Description="Selected Input device"/>
</ComponentType>
<!--#################### INPUT SOURCE COMMON TYPES END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
index ad9c356..45d1e8a 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
@@ -13,54 +13,40 @@
<!--#################### STRATEGY BEGIN ####################-->
- <ComponentType Name="Strategies" Description="Identifier must match the enum value to make
- the link between the PolicyManager and PFW">
- <Component Name="media" Type="StrategyConfig" Mapping="Amend1:Media,Identifier:0"/>
- <Component Name="phone" Type="StrategyConfig" Mapping="Amend1:Phone,Identifier:1"/>
- <Component Name="sonification" Type="StrategyConfig"
- Mapping="Amend1:Sonification,Identifier:2"/>
- <Component Name="sonification_respectful" Type="StrategyConfig"
- Mapping="Amend1:SonificationRespectful,Identifier:3"/>
- <Component Name="dtmf" Type="StrategyConfig" Mapping="Amend1:Dtmf,Identifier:4"/>
- <Component Name="enforced_audible" Type="StrategyConfig"
- Mapping="Amend1:EnforcedAudible,Identifier:5"/>
- <Component Name="transmitted_through_speaker" Type="StrategyConfig"
- Mapping="Amend1:TransmittedThroughSpeaker,Identifier:6"/>
- <Component Name="accessibility" Type="StrategyConfig"
- Mapping="Amend1:Accessibility,Identifier:7"/>
- <Component Name="rerouting" Type="StrategyConfig"
- Mapping="Amend1:Rerouting,Identifier:8"/>
+ <ComponentType Name="Strategies">
+ <Component Name="media" Type="StrategyConfig" Mapping="Name:STRATEGY_MEDIA"/>
+ <Component Name="phone" Type="StrategyConfig" Mapping="Name:STRATEGY_PHONE"/>
+ <Component Name="sonification" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION"/>
+ <Component Name="sonification_respectful" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION_RESPECTFUL"/>
+ <Component Name="dtmf" Type="StrategyConfig" Mapping="Name:STRATEGY_DTMF"/>
+ <Component Name="enforced_audible" Type="StrategyConfig" Mapping="Name:STRATEGY_ENFORCED_AUDIBLE"/>
+ <Component Name="transmitted_through_speaker" Type="StrategyConfig" Mapping="Name:STRATEGY_TRANSMITTED_THROUGH_SPEAKER"/>
+ <Component Name="accessibility" Type="StrategyConfig" Mapping="Name:STRATEGY_ACCESSIBILITY"/>
+ <Component Name="rerouting" Type="StrategyConfig" Mapping=",Name:STRATEGY_REROUTING"/>
</ComponentType>
<!--#################### STRATEGY END ####################-->
<!--#################### STREAM BEGIN ####################-->
- <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition,
- identifier mapping must match the value of the enum">
- <Component Name="voice_call" Type="Stream" Mapping="Stream:VoiceCall,Identifier:0"/>
- <Component Name="system" Type="Stream" Mapping="Stream:System,Identifier:1"/>
- <Component Name="ring" Type="Stream" Mapping="Stream:Ring,Identifier:2"/>
- <Component Name="music" Type="Stream" Mapping="Stream:Music,Identifier:3"/>
- <Component Name="alarm" Type="Stream" Mapping="Stream:Alarm,Identifier:4"/>
- <Component Name="notification" Type="Stream"
- Mapping="Stream:Notification,Identifier:5"/>
- <Component Name="bluetooth_sco" Type="Stream"
- Mapping="Stream:BluetoothSco,Identifier:6"/>
- <Component Name="enforced_audible" Type="Stream"
- Mapping="Stream:EnforceAudible,Identifier:7"
- Description="Sounds that cannot be muted by user and must
- be routed to speaker"/>
- <Component Name="dtmf" Type="Stream" Mapping="Stream:Dtmf,Identifier:8"/>
- <Component Name="tts" Type="Stream" Mapping="Stream:Tts,Identifier:9"
- Description="Transmitted Through Speaker.
- Plays over speaker only, silent on other devices"/>
- <Component Name="accessibility" Type="Stream"
- Mapping="Stream:Accessibility,Identifier:10"
+ <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
+ <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
+ <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
+ <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
+ <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
+ <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
+ <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
+ <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
+ <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
+ Description="Sounds that cannot be muted by user and must be routed to speaker"/>
+ <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
+ <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
+ Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
+ <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
Description="For accessibility talk back prompts"/>
- <Component Name="rerouting" Type="Stream" Mapping="Stream:Rerouting,Identifier:11"
+ <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
Description="For dynamic policy output mixes"/>
- <Component Name="patch" Type="Stream" Mapping="Stream:Patch,Identifier:12"
+ <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
Description="For internal audio flinger tracks. Fixed volume"/>
</ComponentType>
@@ -68,36 +54,34 @@
<!--#################### USAGE BEGIN ####################-->
- <ComponentType Name="Usages" Description="associated to audio_usage_t definition,
- identifier mapping must match the value of the enum">
- <Component Name="unknown" Type="Usage" Mapping="Amend1:Unknown,Identifier:0"/>
- <Component Name="media" Type="Usage" Mapping="Amend1:Media,Identifier:1"/>
+ <ComponentType Name="Usages" Description="associated to audio_usage_t definition">
+ <Component Name="unknown" Type="Usage" Mapping="Name:AUDIO_USAGE_UNKNOWN"/>
+ <Component Name="media" Type="Usage" Mapping="Name:AUDIO_USAGE_MEDIA"/>
<Component Name="voice_communication" Type="Usage"
- Mapping="Amend1:VoiceCommunication,Identifier:2"/>
+ Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION"/>
<Component Name="voice_communication_signalling" Type="Usage"
- Mapping="Amend1:VoiceCommunicationSignalling,Identifier:3"/>
- <Component Name="alarm" Type="Usage" Mapping="Amend1:Alarm,Identifier:4"/>
- <Component Name="notification" Type="Usage" Mapping="Amend1:Notification,Identifier:5"/>
+ Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/>
+ <Component Name="alarm" Type="Usage" Mapping="Name:AUDIO_USAGE_ALARM"/>
+ <Component Name="notification" Type="Usage" Mapping="Name:AUDIO_USAGE_NOTIFICATION"/>
<Component Name="notification_telephony_ringtone" Type="Usage"
- Mapping="Amend1:NotificationTelephonyRingtone,Identifier:6"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
<Component Name="notification_communication_request" Type="Usage"
- Mapping="Amend1:NotificationCommunicationRequest,Identifier:7"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
<Component Name="notification_communication_instant" Type="Usage"
- Mapping="Amend1:NotificationCommunicationInstant,Identifier:8"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
<Component Name="notification_communication_delayed" Type="Usage"
- Mapping="Amend1:NotificationCommunicationDelated,Identifier:9"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
<Component Name="notification_event" Type="Usage"
- Mapping="Amend1:NotificationEvent,Identifier:10"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_EVENT"/>
<Component Name="assistance_accessibility" Type="Usage"
- Mapping="Amend1:AssistanceAccessibility,Identifier:11"/>
+ Mapping="Name:AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
<Component Name="assistance_navigation_guidance" Type="Usage"
- Mapping="Amend1:AssistanceNavigationGuidance,Identifier:12"/>
+ Mapping="Name:AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<Component Name="assistance_sonification" Type="Usage"
- Mapping="Amend1:AssistanceSonification,Identifier:13"/>
- <Component Name="game" Type="Usage" Mapping="Amend1:BluetoothSco,Identifier:14"/>
- <Component Name="virtual_source" Type="Usage"
- Mapping="Amend1:VirtualSource,Identifier:15"/>
- <Component Name="assistant" Type="Usage" Mapping="Amend1:Assistant,Identifier:16"/>
+ Mapping="Name:AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+ <Component Name="game" Type="Usage" Mapping="Name:AUDIO_USAGE_GAME"/>
+ <Component Name="virtual_source" Type="Usage" Mapping="Name:AUDIO_USAGE_VIRTUAL_SOURCE"/>
+ <Component Name="assistant" Type="Usage" Mapping="Name:AUDIO_USAGE_ASSISTANT"/>
</ComponentType>
<!--#################### USAGE END ####################-->
@@ -106,25 +90,25 @@
<ComponentType Name="InputSources" Description="associated to audio_source_t definition,
identifier mapping must match the value of the enum">
- <Component Name="default" Type="InputSource" Mapping="Amend1:Default,Identifier:0"/>
- <Component Name="mic" Type="InputSource" Mapping="Amend1:Mic,Identifier:1"/>
+ <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
+ <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
<Component Name="voice_uplink" Type="InputSource"
- Mapping="Amend1:VoiceUplink,Identifier:2"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
<Component Name="voice_downlink" Type="InputSource"
- Mapping="Amend1:VoiceDownlink,Identifier:3"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
<Component Name="voice_call" Type="InputSource"
- Mapping="Amend1:VoiceCall,Identifier:4"/>
- <Component Name="camcorder" Type="InputSource" Mapping="Amend1:Camcorder,Identifier:5"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
+ <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
<Component Name="voice_recognition" Type="InputSource"
- Mapping="Amend1:VoiceRecognition,Identifier:6"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
<Component Name="voice_communication" Type="InputSource"
- Mapping="Amend1:VoiceCommunication,Identifier:7"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
<Component Name="remote_submix" Type="InputSource"
- Mapping="Amend1:RemoteSubmix,Identifier:8"/>
+ Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
<Component Name="unprocessed" Type="InputSource"
- Mapping="Amend1:Unprocessed,Identifier:9"/>
- <Component Name="fm_tuner" Type="InputSource" Mapping="Amend1:FmTuner,Identifier:1998"/>
- <Component Name="hotword" Type="InputSource" Mapping="Amend1:Hotword,Identifier:1999"/>
+ Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+ <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
+ <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
</ComponentType>
<!--#################### INPUT SOURCE END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt b/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
deleted file mode 100644
index 480cbe1..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-ExclusiveCriterion TelephonyMode : Normal RingTone InCall InCommunication
-InclusiveCriterion AvailableInputDevices : Communication Ambient BuiltinMic BluetoothScoHeadset WiredHeadset Hdmi TelephonyRx BackMic RemoteSubmix AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice FmTuner TvTuner Line Spdif BluetoothA2dp Loopback Ip Bus Stub
-InclusiveCriterion AvailableOutputDevices : Earpiece Speaker WiredSpeaker WiredHeadset WiredHeadphone BluetoothSco BluetoothScoHeadset BluetoothScoCarkit BluetoothA2dp BluetoothA2dpHeadphones BluetoothA2dpSpeaker Hdmi AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice RemoteSubmix TelephonyTx Line HdmiArc Spdif Fm AuxLine SpeakerSafe Ip Bus Stub
-ExclusiveCriterion ForceUseForCommunication : ForceNone ForceSpeaker ForceBtSco
-ExclusiveCriterion ForceUseForMedia : ForceNone ForceSpeaker ForceHeadphones ForceBtA2dp ForceWiredAccessory ForceAnalogDock ForceDigitalDock ForceNoBtA2dp ForceSystemEnforced
-ExclusiveCriterion ForceUseForRecord : ForceNone ForceBtSco ForceWiredAccessory
-ExclusiveCriterion ForceUseForDock : ForceNone ForceWiredAccessory ForceBtCarDock ForceBtDeskDock ForceAnalogDock ForceDigitalDock
-ExclusiveCriterion ForceUseForSystem : ForceNone ForceSystemEnforced
-ExclusiveCriterion ForceUseForHdmiSystemAudio : ForceNone ForceHdmiSystemEnforced
-ExclusiveCriterion ForceUseForEncodedSurround : ForceNone ForceEncodedSurroundNever ForceEncodedSurroundAlways
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index 3559cf1..db1f038 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -28,6 +28,7 @@
LOCAL_SHARED_LIBRARIES := \
libaudiopolicyengineconfigurable \
libparameter \
+ libmedia_helper \
liblog \
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
index eac4efe..f91f8d7 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
@@ -17,6 +17,7 @@
#include "InputSource.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
using std::string;
@@ -33,9 +34,13 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<audio_source_t>(context.getItemAsInteger(MappingKeyIdentifier));
+ std::string name(context.getItem(MappingKeyName));
+
+ if(not android::SourceTypeConverter::fromString(name, mId)) {
+ LOG_ALWAYS_FATAL("Invalid Input Source name: %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addInputSource(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addInputSource(name, mId);
}
bool InputSource::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index 98d10a9..7374fc3 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -65,22 +65,22 @@
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Stream>(
mStreamComponentName,
- (1 << MappingKeyIdentifier))
+ (1 << MappingKeyName))
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Strategy>(
mStrategyComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+ 0)
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Usage>(
mUsageComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+ (1 << MappingKeyName))
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<InputSource>(
mInputSourceComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+ (1 << MappingKeyName))
);
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
index 746c3a8..876bcb0 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
@@ -17,10 +17,38 @@
#include "Strategy.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <RoutingStrategy.h>
using std::string;
using android::routing_strategy;
+namespace detail {
+
+constexpr std::pair<routing_strategy, const char*> routingStrategyMap[] = {
+ {android::STRATEGY_MEDIA, "STRATEGY_MEDIA"},
+ {android::STRATEGY_PHONE, "STRATEGY_PHONE"},
+ {android::STRATEGY_SONIFICATION, "STRATEGY_SONIFICATION"},
+ {android::STRATEGY_SONIFICATION_RESPECTFUL, "STRATEGY_SONIFICATION_RESPECTFUL"},
+ {android::STRATEGY_DTMF, "STRATEGY_DTMF"},
+ {android::STRATEGY_ENFORCED_AUDIBLE, "STRATEGY_ENFORCED_AUDIBLE"},
+ {android::STRATEGY_TRANSMITTED_THROUGH_SPEAKER, "STRATEGY_TRANSMITTED_THROUGH_SPEAKER"},
+ {android::STRATEGY_ACCESSIBILITY, "STRATEGY_ACCESSIBILITY"},
+ {android::STRATEGY_REROUTING, "STRATEGY_REROUTING"},
+};
+
+bool fromString(const char *literalName, routing_strategy &type)
+{
+ for (auto& pair : routingStrategyMap) {
+ if (strcmp(pair.second, literalName) == 0) {
+ type = pair.first;
+ return true;
+ }
+ }
+ return false;
+}
+
+}
+
Strategy::Strategy(const string &mappingValue,
CInstanceConfigurableElement *instanceConfigurableElement,
const CMappingContext &context,
@@ -35,10 +63,12 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<routing_strategy>(context.getItemAsInteger(MappingKeyIdentifier));
-
+ std::string name(context.getItem(MappingKeyName));
+ if (not detail::fromString(name.c_str(), mId)) {
+ LOG_ALWAYS_FATAL("Invalid Strategy %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addStrategy(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addStrategy(instanceConfigurableElement->getName(), mId);
}
bool Strategy::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
index c642a23..46c9e1c 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
@@ -17,6 +17,7 @@
#include "Stream.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
using std::string;
using android::routing_strategy;
@@ -29,10 +30,14 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<audio_stream_type_t>(context.getItemAsInteger(MappingKeyIdentifier));
+ std::string name(context.getItem(MappingKeyName));
+
+ if (not android::StreamTypeConverter::fromString(name, mId)) {
+ LOG_ALWAYS_FATAL("Invalid Stream type name: %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addStream(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addStream(name, mId);
}
bool Stream::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
index 78199f8..925d631 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
@@ -17,6 +17,7 @@
#include "Usage.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
using std::string;
using android::routing_strategy;
@@ -34,10 +35,13 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<audio_usage_t>(context.getItemAsInteger(MappingKeyIdentifier));
+ std::string name(context.getItem(MappingKeyName));
+ if (not android::UsageTypeConverter::fromString(name, mId)) {
+ LOG_ALWAYS_FATAL("Invalid Usage name: %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addUsage(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addUsage(name, mId);
}
bool Usage::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
new file mode 100644
index 0000000..4d41d42
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
@@ -0,0 +1,4 @@
+userdebug_or_eng(`
+ allow audioserver audioserver_socket:dir rw_dir_perms;
+ allow audioserver audioserver_socket:sock_file create_file_perms;
+')
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file.te b/services/audiopolicy/engineconfigurable/sepolicy/file.te
new file mode 100644
index 0000000..7db1937
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file.te
@@ -0,0 +1,2 @@
+# Policy Engine remote connection for runtime debug of parameter framework
+type audioserver_socket, file_type, coredomain_socket;
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file_contexts b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
new file mode 100644
index 0000000..950fcce
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
@@ -0,0 +1 @@
+/dev/socket/audioserver(/.*)? u:object_r:audioserver_socket:s0
diff --git a/services/audiopolicy/engineconfigurable/src/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h
index b72ded8..1f8ed8d 100644
--- a/services/audiopolicy/engineconfigurable/src/Collection.h
+++ b/services/audiopolicy/engineconfigurable/src/Collection.h
@@ -28,10 +28,8 @@
#include <stdint.h>
#include <string>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* Collection of policy element as a map indexed with a their UID type.
diff --git a/services/audiopolicy/engineconfigurable/src/Element.h b/services/audiopolicy/engineconfigurable/src/Element.h
index 52e77e5..1b55c8c 100644
--- a/services/audiopolicy/engineconfigurable/src/Element.h
+++ b/services/audiopolicy/engineconfigurable/src/Element.h
@@ -22,10 +22,8 @@
#include <system/audio.h>
#include <utils/Log.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
template <typename Key>
class Element
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 0d18ffa..009cf90 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -35,10 +35,9 @@
using std::string;
using std::map;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
template <>
StrategyCollection &Engine::getCollection<routing_strategy>()
{
@@ -220,8 +219,10 @@
}
status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
- audio_policy_dev_state_t /*state*/)
+ audio_policy_dev_state_t state)
{
+ mPolicyParameterMgr->setDeviceConnectionState(devDesc, state);
+
if (audio_is_output_device(devDesc->type())) {
return mPolicyParameterMgr->setAvailableOutputDevices(
mApmObserver->getAvailableOutputDevices().types());
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 328d23d..ba4f889 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -21,12 +21,10 @@
#include <AudioPolicyPluginInterface.h>
#include "Collection.h"
-namespace android
-{
+namespace android {
class AudioPolicyManagerObserver;
-namespace audio_policy
-{
+namespace audio_policy {
class ParameterManagerWrapper;
class VolumeProfile;
diff --git a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
index 9aa89b2..2442590 100644
--- a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
+++ b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
@@ -21,10 +21,8 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
EngineInstance::EngineInstance()
{
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index ae39fef..b9a38d4 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -20,10 +20,9 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
status_t Element<audio_source_t>::setIdentifier(audio_source_t identifier)
{
if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD) {
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.h b/services/audiopolicy/engineconfigurable/src/InputSource.h
index 6c498dc..64b390e 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.h
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.h
@@ -18,10 +18,8 @@
#include "Element.h"
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* Specialization of policy base class element for audio_source_t
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.cpp b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
index a539914..310b35e 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
@@ -20,10 +20,8 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
status_t Element<routing_strategy>::setIdentifier(routing_strategy identifier)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.h b/services/audiopolicy/engineconfigurable/src/Strategy.h
index 1157d55..f2487fd 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.h
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.h
@@ -19,10 +19,8 @@
#include "Element.h"
#include <RoutingStrategy.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* @tparam audio_devices_t: Applicable output device(s) for this strategy.
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index 0ed364f..73fb94d 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -21,10 +21,8 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
status_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.h b/services/audiopolicy/engineconfigurable/src/Stream.h
index 6902003..2bf70b3 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.h
+++ b/services/audiopolicy/engineconfigurable/src/Stream.h
@@ -21,10 +21,9 @@
#include <RoutingStrategy.h>
#include <map>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
/**
* @tparam routing_strategy: Applicable strategy for this stream.
*/
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.cpp b/services/audiopolicy/engineconfigurable/src/Usage.cpp
index 5d20828..8c0dfba 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Usage.cpp
@@ -18,10 +18,8 @@
#include "Usage.h"
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
status_t Element<audio_usage_t>::setIdentifier(audio_usage_t identifier)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.h b/services/audiopolicy/engineconfigurable/src/Usage.h
index d69e0e0..72a452f 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.h
+++ b/services/audiopolicy/engineconfigurable/src/Usage.h
@@ -19,10 +19,8 @@
#include "Element.h"
#include <RoutingStrategy.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* @tparam routing_strategy: Applicable strategy for this usage.
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
new file mode 100644
index 0000000..d8f29dc
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2018 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.
+
+python_binary_host {
+ name: "buildPolicyCriterionTypes.py",
+ owner: "renault",
+ main: "buildPolicyCriterionTypes.py",
+ srcs: [
+ "buildPolicyCriterionTypes.py",
+ ],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+}
+
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
new file mode 100755
index 0000000..0fb70a6
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -0,0 +1,243 @@
+#!/usr/bin/python
+
+#
+# Copyright 2018, 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.
+#
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+import xml.etree.ElementInclude as EI
+import xml.dom.minidom as MINIDOM
+from collections import OrderedDict
+
+#
+# Helper script that helps to feed at build time the XML criterion types file used by
+# the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Device Types criterion types are fed from audio-base.h file with the option
+# --androidaudiobaseheader <path/to/android/audio/base/file/audio-base.h>
+#
+# The Device Addresses criterion types are fed from the audio policy configuration file
+# in order to discover all the devices for which the address matter.
+# --audiopolicyconfigurationfile <path/to/audio_policy_configuration.xml>
+#
+# The reference file of criterion types must also be set as an input of the script:
+# --criteriontypes <path/to/criterion/file/audio_criterion_types.xml.in>
+#
+# At last, the output of the script shall be set also:
+# --outputfile <path/to/out/vendor/etc/audio_criterion_types.xml>
+#
+
+def parseArgs():
+ argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+ audio criterion type file generator.\n\
+ Exit with the number of (recoverable or not) error that occured.")
+ argparser.add_argument('--androidaudiobaseheader',
+ help="Android Audio Base C header file, Mandatory.",
+ metavar="ANDROID_AUDIO_BASE_HEADER",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--audiopolicyconfigurationfile',
+ help="Android Audio Policy Configuration file, Mandatory.",
+ metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--criteriontypes',
+ help="Criterion types XML base file, in \
+ '<criterion_types> \
+ <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/>' \
+ format. Mandatory.",
+ metavar="CRITERION_TYPE_FILE",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--outputfile',
+ help="Criterion types outputfile file. Mandatory.",
+ metavar="CRITERION_TYPE_OUTPUT_FILE",
+ type=argparse.FileType('w'),
+ required=True)
+ argparser.add_argument('--verbose',
+ action='store_true')
+
+ return argparser.parse_args()
+
+
+def generateXmlCriterionTypesFile(criterionTypes, addressCriteria, criterionTypesFile, outputFile):
+
+ logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+ criterion_types_in_tree = ET.parse(criterionTypesFile)
+
+ criterion_types_root = criterion_types_in_tree.getroot()
+
+ for criterion_name, values_dict in criterionTypes.items():
+ for criterion_type in criterion_types_root.findall('criterion_type'):
+ if criterion_type.get('name') == criterion_name:
+ values_node = ET.SubElement(criterion_type, "values")
+ ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+ for key, value in ordered_values.items():
+ value_node = ET.SubElement(values_node, "value")
+ value_node.set('numerical', str(value))
+ value_node.set('literal', key)
+
+ if addressCriteria:
+ for criterion_name, values_list in addressCriteria.items():
+ for criterion_type in criterion_types_root.findall('criterion_type'):
+ if criterion_type.get('name') == criterion_name:
+ values_node = ET.SubElement(criterion_type, "values")
+ index = 0
+ for value in values_list:
+ value_node = ET.SubElement(values_node, "value", literal=value)
+ value_node.set('numerical', str(1 << index))
+ index += 1
+
+ xmlstr = ET.tostring(criterion_types_root, encoding='utf8', method='xml')
+ reparsed = MINIDOM.parseString(xmlstr)
+ prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
+ prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+ outputFile.write(prettyXmlStr.encode('utf-8'))
+
+def capitalizeLine(line):
+ return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyConfigurationFile(audiopolicyconfigurationfile):
+
+ logging.info("Checking Audio Policy Configuration file {}".format(audiopolicyconfigurationfile))
+ #
+ # extract all devices addresses from audio policy configuration file
+ #
+ address_criteria_mapping_table = {
+ 'sink' : "OutputDevicesAddressesType",
+ 'source' : "InputDevicesAddressesType" }
+
+ address_criteria = {
+ 'OutputDevicesAddressesType' : [],
+ 'InputDevicesAddressesType' : [] }
+
+ oldWorkingDir = os.getcwd()
+ print "Current working directory %s" % oldWorkingDir
+
+ newDir = os.path.join(oldWorkingDir , audiopolicyconfigurationfile.name)
+
+ policy_in_tree = ET.parse(audiopolicyconfigurationfile)
+ os.chdir(os.path.dirname(os.path.normpath(newDir)))
+
+ print "new working directory %s" % os.getcwd()
+
+ policy_root = policy_in_tree.getroot()
+ EI.include(policy_root)
+
+ os.chdir(oldWorkingDir)
+
+ for device in policy_root.iter('devicePort'):
+ for key in address_criteria_mapping_table.keys():
+ if device.get('role') == key and device.get('address') :
+ logging.info("{}: <{}>".format(key, device.get('address')))
+ address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
+
+ for criteria in address_criteria:
+ values = ','.join(address_criteria[criteria])
+ logging.info("{}: <{}>".format(criteria, values))
+
+ return address_criteria
+
+#
+# Parse the audio-base.h file and output a dictionary of android dependent criterion types:
+# -Android Mode
+# -Output devices type
+# -Input devices type
+#
+def parseAndroidAudioFile(androidaudiobaseheaderFile):
+ #
+ # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+ #
+ criterion_mapping_table = {
+ 'AUDIO_MODE' : "AndroidModeType",
+ 'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
+ 'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
+
+ all_criteria = {
+ 'AndroidModeType' : {},
+ 'OutputDevicesMaskType' : {},
+ 'InputDevicesMaskType' : {} }
+
+ #
+ # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+ #
+ ignored_values = [ 'CNT', 'MAX', 'ALL', 'NONE' ]
+
+ criteria_pattern = re.compile(
+ r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))\_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+ r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
+
+ logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+ for line_number, line in enumerate(androidaudiobaseheaderFile):
+ match = criteria_pattern.match(line)
+ if match:
+ logging.debug("The following line is VALID: {}:{}\n{}".format(
+ androidaudiobaseheaderFile.name, line_number, line))
+
+ criterion_name = criterion_mapping_table[match.groupdict()['type']]
+ literal = ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+ numerical_value = match.groupdict()['values']
+
+ # for AUDIO_DEVICE_IN: need to remove sign bit
+ if criterion_name == "InputDevicesMaskType":
+ numerical_value = str(int(numerical_value, 0) & ~2147483648)
+
+ # Remove duplicated numerical values
+ if int(numerical_value, 0) in all_criteria[criterion_name].values():
+ logging.info("criterion {} duplicated values:".format(criterion_name))
+ logging.info("{}:{}".format(numerical_value, literal))
+ logging.info("KEEPING LATEST")
+ for key in all_criteria[criterion_name].keys():
+ if all_criteria[criterion_name][key] == int(numerical_value, 0):
+ del all_criteria[criterion_name][key]
+
+ all_criteria[criterion_name][literal] = int(numerical_value, 0)
+
+ logging.debug("type:{},".format(criterion_name))
+ logging.debug("iteral:{},".format(literal))
+ logging.debug("values:{}.".format(numerical_value))
+
+ return all_criteria
+
+
+def main():
+ logging.root.setLevel(logging.INFO)
+ args = parseArgs()
+
+ all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader)
+
+ address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
+
+ criterion_types = args.criteriontypes
+
+ generateXmlCriterionTypesFile(all_criteria, address_criteria, criterion_types, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+ exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
new file mode 100644
index 0000000..2b86469
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
@@ -0,0 +1,35 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_TOOL := domainGeneratorPolicy.py
+$(LOCAL_BUILT_MODULE): MY_TOPLEVEL_FILE := $(PFW_TOPLEVEL_FILE)
+$(LOCAL_BUILT_MODULE): MY_CRITERIA_FILE := $(PFW_CRITERIA_FILE)
+$(LOCAL_BUILT_MODULE): MY_TUNING_FILE := $(PFW_TUNING_FILE)
+$(LOCAL_BUILT_MODULE): MY_EDD_FILES := $(PFW_EDD_FILES)
+$(LOCAL_BUILT_MODULE): MY_DOMAIN_FILES := $(PFW_DOMAIN_FILES)
+$(LOCAL_BUILT_MODULE): MY_SCHEMAS_DIR := $(PFW_SCHEMAS_DIR)
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) domainGeneratorPolicy.py
+
+ "$(MY_TOOL)" --validate \
+ --toplevel-config "$(MY_TOPLEVEL_FILE)" \
+ --criteria "$(MY_CRITERIA_FILE)" \
+ --criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
+ --initial-settings $(MY_TUNING_FILE) \
+ --add-edds $(MY_EDD_FILES) \
+ --add-domains $(MY_DOMAIN_FILES) \
+ --schemas-dir $(MY_SCHEMAS_DIR) > "$@"
+
+
+# Clear variables for further use
+PFW_TOPLEVEL_FILE :=
+PFW_STRUCTURE_FILES :=
+PFW_CRITERIA_FILE :=
+PFW_CRITERION_TYPES_FILE :=
+PFW_TUNING_FILE :=
+PFW_EDD_FILES :=
+PFW_DOMAIN_FILES :=
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
diff --git a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
new file mode 100755
index 0000000..7929402
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
@@ -0,0 +1,268 @@
+#!/usr/bin/python
+
+#
+# Copyright 2018, 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.
+#
+
+import EddParser
+from PFWScriptGenerator import PfwScriptTranslator
+import hostConfig
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+
+#
+# In order to build the XML Settings file at build time, an instance of the parameter-framework
+# shall be started and fed with all the criterion types/criteria that will be used by
+# the engineconfigurable.
+# This scripts allows generates the settings from the same audio_criterion_types.xml /
+# audio_criteria.xml files used at run time by the engineconfigurable
+#
+
+def parseArgs():
+ argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+ Settings file generator.\n\
+ Exit with the number of (recoverable or not) error that occured.")
+ argparser.add_argument('--toplevel-config',
+ help="Top-level parameter-framework configuration file. Mandatory.",
+ metavar="TOPLEVEL_CONFIG_FILE",
+ required=True)
+ argparser.add_argument('--criteria',
+ help="Criteria file, in XML format: \
+ in '<criteria> \
+ <criterion name="" type=""/> \
+ </criteria>' \
+ format. Mandatory.",
+ metavar="CRITERIA_FILE",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--criteriontypes',
+ help="Criterion types XML file, in \
+ '<criterion_types> \
+ <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/> \
+ </criterion_types>' \
+ format. Mandatory.",
+ metavar="CRITERION_TYPE_FILE",
+ type=argparse.FileType('r'),
+ required=False)
+ argparser.add_argument('--initial-settings',
+ help="Initial XML settings file (containing a \
+ <ConfigurableDomains> tag",
+ nargs='?',
+ default=None,
+ metavar="XML_SETTINGS_FILE")
+ argparser.add_argument('--add-domains',
+ help="List of single domain files (each containing a single \
+ <ConfigurableDomain> tag",
+ metavar="XML_DOMAIN_FILE",
+ nargs='*',
+ dest='xml_domain_files',
+ default=[])
+ argparser.add_argument('--add-edds',
+ help="List of files in EDD syntax (aka \".pfw\" files)",
+ metavar="EDD_FILE",
+ type=argparse.FileType('r'),
+ nargs='*',
+ default=[],
+ dest='edd_files')
+ argparser.add_argument('--schemas-dir',
+ help="Directory of parameter-framework XML Schemas for generation \
+ validation",
+ default=None)
+ argparser.add_argument('--target-schemas-dir',
+ help="Ignored. Kept for retro-compatibility")
+ argparser.add_argument('--validate',
+ help="Validate the settings against XML schemas",
+ action='store_true')
+ argparser.add_argument('--verbose',
+ action='store_true')
+
+ return argparser.parse_args()
+
+#
+# Parses audio_criterion_types.xml / audio_criteria.xml files used at run time by the
+# engineconfigurable and outputs a dictionnary of criteria.
+# For each criteria, the name, type (aka inclusive (bitfield) or exclusive (enum), the values
+# are provided.
+#
+def parseCriteriaAndCriterionTypes(criteriaFile, criterionTypesFile):
+ # Parse criteria and criterion types XML files
+ #
+ criteria_tree = ET.parse(criteriaFile)
+ logging.info("Importing criteriaFile {}".format(criteriaFile))
+ criterion_types_tree = ET.parse(criterionTypesFile)
+ logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+
+ criteria_root = criteria_tree.getroot()
+ criterion_types_root = criterion_types_tree.getroot()
+
+ all_criteria = []
+ for criterion in criteria_root.findall('criterion'):
+ criterion_name = criterion.get('name')
+ type_name = criterion.get('type')
+ logging.info("Importing criterion_name {}".format(criterion_name))
+ logging.info("Importing type_name {}".format(type_name))
+
+ for criterion_types in criterion_types_tree.findall('criterion_type'):
+ criterion_type_name = criterion_types.get('name')
+ if criterion_type_name == type_name:
+ criterion_inclusiveness = criterion_types.get('type')
+
+ criterion_values = []
+
+ values_node = criterion_types.find('values')
+ if values_node:
+ for value in values_node.findall('value'):
+ criterion_values.append(value.get('literal'))
+
+ if len(criterion_values) == 0:
+ criterion_values.append('')
+
+ logging.info("Importing criterion_type_name {}".format(criterion_type_name))
+ logging.info("Importing criterion_inclusiveness {}".format(criterion_inclusiveness))
+ logging.info("Importing criterion_values {}".format(criterion_values))
+
+ all_criteria.append({
+ "name" : criterion_name,
+ "inclusive" : criterion_inclusiveness,
+ "values" : criterion_values})
+ break
+
+ return all_criteria
+
+#
+# Parses the Edd files (aka .pfw extension file), which is a simplified language to write the
+# parameter framework settings.
+#
+def parseEdd(EDDFiles):
+ parsed_edds = []
+
+ for edd_file in EDDFiles:
+ try:
+ root = EddParser.Parser().parse(edd_file)
+ except EddParser.MySyntaxError as ex:
+ logging.critical(str(ex))
+ logging.info("EXIT ON FAILURE")
+ exit(2)
+
+ try:
+ root.propagate()
+ except EddParser.MyPropagationError, ex :
+ logging.critical(str(ex))
+ logging.info("EXIT ON FAILURE")
+ exit(1)
+
+ parsed_edds.append((edd_file.name, root))
+ return parsed_edds
+
+#
+# Generates all the required commands to be sent to the instance of parameter-framework launched
+# at runtime to generate the XML Settings file.
+# It takes as input the collection of criteria, the domains and the simplified settings read from
+# pfw.
+#
+def generateDomainCommands(logging, all_criteria, initial_settings, xml_domain_files, parsed_edds):
+ # create and inject all the criteria
+ logging.info("Creating all criteria")
+ for criterion in all_criteria:
+ yield ["createSelectionCriterion", criterion['inclusive'],
+ criterion['name']] + criterion['values']
+
+ yield ["start"]
+
+ # Import initial settings file
+ if initial_settings:
+ logging.info("Importing initial settings file {}".format(initial_settings))
+ yield ["importDomainsWithSettingsXML", initial_settings]
+
+ # Import each standalone domain files
+ for domain_file in xml_domain_files:
+ logging.info("Importing single domain file {}".format(domain_file))
+ yield ["importDomainWithSettingsXML", domain_file]
+
+ # Generate the script for each EDD file
+ for filename, parsed_edd in parsed_edds:
+ logging.info("Translating and injecting EDD file {}".format(filename))
+ translator = PfwScriptTranslator()
+ parsed_edd.translate(translator)
+ for command in translator.getScript():
+ yield command
+
+#
+# Entry point of the domain generator.
+# -Parses Criterion types and criteria files
+# -Parses settings written in simplified pfw language.
+# -Launches a parameter-framework
+# -Translates the settings into command that can be interpreted by parameter-framework.
+# -Use the exports command and output them in XML Settings file.
+#
+def main():
+ logging.root.setLevel(logging.INFO)
+ args = parseArgs()
+
+ all_criteria = parseCriteriaAndCriterionTypes(args.criteria, args.criteriontypes)
+
+ #
+ # EDD files (aka ".pfw" files)
+ #
+ parsed_edds = parseEdd(args.edd_files)
+
+ # We need to modify the toplevel configuration file to account for differences
+ # between development setup and target (installation) setup, in particular, the
+ # TuningMwith ode must be enforced, regardless of what will be allowed on the target
+ fake_toplevel_config = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".xml",
+ prefix="TMPdomainGeneratorPFConfig_")
+
+ install_path = os.path.dirname(os.path.realpath(args.toplevel_config))
+ hostConfig.configure(
+ infile=args.toplevel_config,
+ outfile=fake_toplevel_config,
+ structPath=install_path)
+ fake_toplevel_config.close()
+
+ # Create the connector. Pipe its input to us in order to write commands;
+ # connect its output to stdout in order to have it dump the domains
+ # there; connect its error output to stderr.
+ connector = subprocess.Popen(["domainGeneratorConnector",
+ fake_toplevel_config.name,
+ 'verbose' if args.verbose else 'no-verbose',
+ 'validate' if args.validate else 'no-validate',
+ args.schemas_dir],
+ stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
+
+ initial_settings = None
+ if args.initial_settings:
+ initial_settings = os.path.realpath(args.initial_settings)
+
+ for command in generateDomainCommands(logging, all_criteria, initial_settings,
+ args.xml_domain_files, parsed_edds):
+ connector.stdin.write('\0'.join(command))
+ connector.stdin.write("\n")
+
+ # Closing the connector's input triggers the domain generation
+ connector.stdin.close()
+ connector.wait()
+ os.remove(fake_toplevel_config.name)
+ return connector.returncode
+
+# If this file is directly executed
+if __name__ == "__main__":
+ exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
new file mode 100644
index 0000000..4814376
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
@@ -0,0 +1,24 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_ANDROID_AUDIO_BASE_HEADER_FILE := $(ANDROID_AUDIO_BASE_HEADER_FILE)
+$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_CONFIGURATION_FILE := $(AUDIO_POLICY_CONFIGURATION_FILE)
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TOOL := $(HOST_OUT)/bin/buildPolicyCriterionTypes.py
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) \
+ buildPolicyCriterionTypes.py \
+ $(CRITERION_TYPES_FILE) \
+ $(ANDROID_AUDIO_BASE_HEADER_FILE)
+
+ "$(MY_CRITERION_TOOL)" \
+ --androidaudiobaseheader "$(MY_ANDROID_AUDIO_BASE_HEADER_FILE)" \
+ --audiopolicyconfigurationfile "$(MY_AUDIO_POLICY_CONFIGURATION_FILE)" \
+ --criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
+ --outputfile "$(@)"
+
+# Clear variables for further use
+CRITERION_TYPES_FILE :=
+ANDROID_AUDIO_BASE_HEADER_FILE :=
+AUDIO_POLICY_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.mk b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
index b128a38..d19a364 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.mk
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
@@ -1,5 +1,8 @@
LOCAL_PATH:= $(call my-dir)
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+PROVISION_CRITERION_TYPES := $(TOOLS)/provision_criterion_types_from_android_headers.mk
+
##################################################################
# WRAPPER LIBRARY
##################################################################
@@ -10,12 +13,22 @@
$(LOCAL_PATH)/include \
frameworks/av/services/audiopolicy/engineconfigurable/include \
frameworks/av/services/audiopolicy/engineconfigurable/interface \
+ frameworks/av/services/audiopolicy/common/include \
+ external/libxml2/include \
+ external/icu/icu4c/source/common
-LOCAL_SRC_FILES:= ParameterManagerWrapper.cpp
+LOCAL_SRC_FILES:= \
+ ParameterManagerWrapper.cpp \
+ ParameterManagerWrapperConfig.cpp
LOCAL_SHARED_LIBRARIES := \
libparameter \
- libmedia_helper
+ libmedia_helper \
+ libicuuc \
+ libxml2
+
+LOCAL_STATIC_LIBRARIES := \
+ libaudiopolicycomponents
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
@@ -31,11 +44,35 @@
# CONFIGURATION FILE
##################################################################
-# specific management of audio_policy_criteria.conf
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_criteria.conf
+LOCAL_MODULE := policy_wrapper_configuration.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
+LOCAL_VENDOR_MODULE := true
LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criteria.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criterion_types.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+
+AUDIO_POLICY_CONFIGURATION_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+ANDROID_AUDIO_BASE_HEADER_FILE := system/media/audio/include/system/audio-base.h
+CRITERION_TYPES_FILE := $(LOCAL_PATH)/config/policy_criterion_types.xml.in
+
+include $(PROVISION_CRITERION_TYPES)
+
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 9b0442e..fc6c1e4 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#include "ParameterManagerWrapper.h"
-#include "audio_policy_criteria_conf.h"
+#include "ParameterManagerWrapperConfig.h"
#include <ParameterMgrPlatformConnector.h>
#include <SelectionCriterionTypeInterface.h>
#include <SelectionCriterionInterface.h>
@@ -38,6 +38,7 @@
using std::string;
using std::map;
using std::vector;
+using CriterionTypes = std::map<std::string, ISelectionCriterionTypeInterface *>;
/// PFW related definitions
// Logger
@@ -56,16 +57,36 @@
}
};
-namespace android
-{
+namespace android {
using utilities::convertTo;
-namespace audio_policy
-{
+namespace audio_policy {
+
const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
"/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
+static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
+static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
+static const char *const gPhoneStateCriterionName = "TelephonyMode";
+static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
+static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
+
+/**
+ * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
+ */
+static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
+{
+ [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
+ [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
+ [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
+ [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
+ [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
+ [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
+ [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
+ [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
+};
+
template <>
struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
template <>
@@ -80,15 +101,64 @@
// Logger
mPfwConnector->setLogger(mPfwConnectorLogger);
- // Load criteria file
- if ((loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaVendorConfFilePath) != NO_ERROR) &&
- (loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaConfFilePath) != NO_ERROR)) {
- ALOGE("%s: Neither vendor conf file (%s) nor system conf file (%s) could be found",
- __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath,
- gAudioPolicyCriteriaConfFilePath);
+ status_t loadResult = loadConfig();
+ if (loadResult < 0) {
+ ALOGE("Policy Wrapper configuration is partially invalid.");
}
}
+status_t ParameterManagerWrapper::loadConfig()
+{
+ auto result = wrapper_config::parse();
+ if (result.parsedConfig == nullptr) {
+ return -ENOENT;
+ }
+ ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+
+ CriterionTypes criterionTypes;
+ for (auto criterionType : result.parsedConfig->criterionTypes) {
+ ALOG_ASSERT(criterionTypes.find(criterionType.name) == criterionTypes.end(),
+ "CriterionType %s already added", criterionType.name.c_str());
+ ALOGV("%s: Adding new criterionType %s", __FUNCTION__, criterionType.name.c_str());
+
+ auto criterionTypePfw =
+ mPfwConnector->createSelectionCriterionType(criterionType.isInclusive);
+
+ for (auto pair : criterionType.valuePairs) {
+ std::string error;
+ ALOGV("%s: Adding pair %d,%s for criterionType %s", __FUNCTION__, pair.first,
+ pair.second.c_str(), criterionType.name.c_str());
+ criterionTypePfw->addValuePair(pair.first, pair.second, error);
+ }
+ criterionTypes[criterionType.name] = criterionTypePfw;
+ }
+
+ for (auto criterion : result.parsedConfig->criteria) {
+ ALOG_ASSERT(mPolicyCriteria.find(criterion.name) == mPolicyCriteria.end(),
+ "%s: Criterion %s already added", __FUNCTION__, criterion.name.c_str());
+
+ auto criterionType =
+ getElement<ISelectionCriterionTypeInterface>(criterion.typeName, criterionTypes);
+ ALOG_ASSERT(criterionType != nullptr, "No %s Criterion type found for criterion %s",
+ criterion.typeName.c_str(), criterion.name.c_str());
+
+ auto criterionPfw = mPfwConnector->createSelectionCriterion(criterion.name, criterionType);
+ mPolicyCriteria[criterion.name] = criterionPfw;
+
+ if (not criterion.defaultLiteralValue.empty()) {
+ int numericalValue = 0;
+ if (not criterionType->getNumericalValue(criterion.defaultLiteralValue.c_str(),
+ numericalValue)) {
+ ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
+ criterion.defaultLiteralValue.c_str());
+ continue;
+ }
+ criterionPfw->setCriterionState(numericalValue);
+ }
+ }
+ return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
+}
+
ParameterManagerWrapper::~ParameterManagerWrapper()
{
// Unset logger
@@ -112,112 +182,6 @@
return NO_ERROR;
}
-
-void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive)
-{
- ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(),
- "CriterionType %s already added", typeName.c_str());
- ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str());
-
- mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive);
-}
-
-void ParameterManagerWrapper::addCriterionTypeValuePair(
- const string &typeName,
- uint32_t numericValue,
- const string &literalValue)
-{
- ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(),
- "CriterionType %s not found", typeName.c_str());
- ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__,
- numericValue, literalValue.c_str(), typeName.c_str());
- ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName];
- std::string error;
- criterionType->addValuePair(numericValue, literalValue, error);
-}
-
-void ParameterManagerWrapper::loadCriterionType(cnode *root, bool isInclusive)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node;
- for (node = root->first_child; node != NULL; node = node->next) {
-
- ALOG_ASSERT(node != NULL, "error in parsing file");
- const char *typeName = node->name;
- char *valueNames = strndup(node->value, strlen(node->value));
-
- addCriterionType(typeName, isInclusive);
-
- uint32_t index = 0;
- char *ctx;
- char *valueName = strtok_r(valueNames, ",", &ctx);
- while (valueName != NULL) {
- if (strlen(valueName) != 0) {
-
- // Conf file may use or not pair, if no pair, use incremental index, else
- // use provided index.
- if (strchr(valueName, ':') != NULL) {
-
- char *first = strtok(valueName, ":");
- char *second = strtok(NULL, ":");
- ALOG_ASSERT((first != NULL) && (strlen(first) != 0) &&
- (second != NULL) && (strlen(second) != 0),
- "invalid value pair");
-
- if (!convertTo<string, uint32_t>(first, index)) {
- ALOGE("%s: Invalid index(%s) found", __FUNCTION__, first);
- }
- addCriterionTypeValuePair(typeName, index, second);
- } else {
-
- uint32_t pfwIndex = isInclusive ? 1 << index : index;
- addCriterionTypeValuePair(typeName, pfwIndex, valueName);
- index += 1;
- }
- }
- valueName = strtok_r(NULL, ",", &ctx);
- }
- free(valueNames);
- }
-}
-
-void ParameterManagerWrapper::loadInclusiveCriterionType(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gInclusiveCriterionTypeTag.c_str());
- if (node == NULL) {
- return;
- }
- loadCriterionType(node, true);
-}
-
-void ParameterManagerWrapper::loadExclusiveCriterionType(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gExclusiveCriterionTypeTag.c_str());
- if (node == NULL) {
- return;
- }
- loadCriterionType(node, false);
-}
-
-void ParameterManagerWrapper::parseChildren(cnode *root, string &defaultValue, string &type)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node;
- for (node = root->first_child; node != NULL; node = node->next) {
- ALOG_ASSERT(node != NULL, "error in parsing file");
-
- if (string(node->name) == gDefaultTag) {
- defaultValue = node->value;
- } else if (string(node->name) == gTypeTag) {
- type = node->value;
- } else {
- ALOGE("%s: Unrecognized %s %s node", __FUNCTION__, node->name, node->value);
- }
- }
-}
-
template <typename T>
T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
{
@@ -236,97 +200,6 @@
return it != elementsMap.end() ? it->second : NULL;
}
-void ParameterManagerWrapper::loadCriteria(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gCriterionTag.c_str());
-
- if (node == NULL) {
- ALOGW("%s: no inclusive criteria found", __FUNCTION__);
- return;
- }
- for (node = node->first_child; node != NULL; node = node->next) {
- loadCriterion(node);
- }
-}
-
-void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName,
- const string &defaultLiteralValue)
-{
- ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
- "Route Criterion %s already added", name.c_str());
-
- ISelectionCriterionTypeInterface *criterionType =
- getElement<ISelectionCriterionTypeInterface>(typeName, mPolicyCriterionTypes);
-
- ISelectionCriterionInterface *criterion =
- mPfwConnector->createSelectionCriterion(name, criterionType);
-
- mPolicyCriteria[name] = criterion;
- int numericalValue = 0;
- if (!criterionType->getNumericalValue(defaultLiteralValue.c_str(), numericalValue)) {
- ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
- defaultLiteralValue.c_str());
- }
- criterion->setCriterionState(numericalValue);
-}
-
-void ParameterManagerWrapper::loadCriterion(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- const char *criterionName = root->name;
-
- ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
- "Criterion %s already added", criterionName);
-
- string paramKeyName = "";
- string path = "";
- string typeName = "";
- string defaultValue = "";
-
- parseChildren(root, defaultValue, typeName);
-
- addCriterion(criterionName, typeName, defaultValue);
-}
-
-void ParameterManagerWrapper::loadConfig(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gPolicyConfTag.c_str());
- if (node == NULL) {
- ALOGW("%s: Could not find node for pfw", __FUNCTION__);
- return;
- }
- ALOGD("%s: Loading conf for pfw", __FUNCTION__);
- loadInclusiveCriterionType(node);
- loadExclusiveCriterionType(node);
- loadCriteria(node);
-}
-
-
-status_t ParameterManagerWrapper::loadAudioPolicyCriteriaConfig(const char *path)
-{
- ALOG_ASSERT(path != NULL, "error in parsing file: empty path");
- cnode *root;
- char *data;
- ALOGD("%s", __FUNCTION__);
- data = (char *)load_file(path, NULL);
- if (data == NULL) {
- return -ENODEV;
- }
- root = config_node("", "");
- ALOG_ASSERT(root != NULL, "Unable to allocate a configuration node");
- config_load(root, data);
-
- loadConfig(root);
-
- config_free(root);
- free(root);
- free(data);
- ALOGD("%s: loaded", __FUNCTION__);
- return NO_ERROR;
-}
-
bool ParameterManagerWrapper::isStarted()
{
return mPfwConnector && mPfwConnector->isStarted();
@@ -335,9 +208,9 @@
status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
{
ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
return BAD_VALUE;
}
if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
@@ -351,9 +224,9 @@
audio_mode_t ParameterManagerWrapper::getPhoneState() const
{
const ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
return AUDIO_MODE_NORMAL;
}
return static_cast<audio_mode_t>(criterion->getCriterionState());
@@ -370,7 +243,7 @@
ISelectionCriterionInterface *criterion =
getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
return BAD_VALUE;
}
if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
@@ -390,7 +263,7 @@
const ISelectionCriterionInterface *criterion =
getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
return AUDIO_POLICY_FORCE_NONE;
}
return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
@@ -404,12 +277,45 @@
return interface->getLiteralValue(valueToCheck, literalValue);
}
+status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state)
+{
+ std::string criterionName = audio_is_output_device(devDesc->type()) ?
+ gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
+
+ ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->mAddress.string(),
+ state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
+ ISelectionCriterionInterface *criterion =
+ getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
+
+ if (criterion == NULL) {
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, criterionName.c_str());
+ return DEAD_OBJECT;
+ }
+
+ auto criterionType = criterion->getCriterionType();
+ int deviceAddressId;
+ if (not criterionType->getNumericalValue(devDesc->mAddress.string(), deviceAddressId)) {
+ ALOGE("%s: unknown device address reported (%s)", __FUNCTION__, devDesc->mAddress.c_str());
+ return BAD_TYPE;
+ }
+ int currentValueMask = criterion->getCriterionState();
+ if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ currentValueMask |= deviceAddressId;
+ }
+ else {
+ currentValueMask &= ~deviceAddressId;
+ }
+ criterion->setCriterionState(currentValueMask);
+ return NO_ERROR;
+}
+
status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
{
ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gInputDeviceCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionName);
return DEAD_OBJECT;
}
criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
@@ -420,9 +326,9 @@
status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
{
ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionName);
return DEAD_OBJECT;
}
criterion->setCriterionState(outputDevices);
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
new file mode 100644
index 0000000..bc6d046
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::AudioPolicyEngine/PFWWrapperConfig"
+#define LOG_NDEBUG 0
+
+#include "ParameterManagerWrapperConfig.h"
+
+#include <media/convert.h>
+#include <utils/Log.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <istream>
+
+
+namespace android {
+
+using utilities::convertTo;
+
+namespace audio_policy {
+namespace wrapper_config {
+namespace detail {
+
+std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
+{
+ xmlChar *xmlValue = xmlGetProp(cur, (const xmlChar *)attribute);
+ if (xmlValue == NULL) {
+ return "";
+ }
+ std::string value((const char *)xmlValue);
+ xmlFree(xmlValue);
+ return value;
+}
+
+template <class Trait>
+static status_t deserializeCollection(_xmlDoc *doc, const _xmlNode *cur,
+ typename Trait::Collection &collection,
+ size_t &nbSkippedElement)
+{
+ const xmlNode *root = cur->xmlChildrenNode;
+ while (root != NULL) {
+ if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) &&
+ xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ root = root->next;
+ continue;
+ }
+ const xmlNode *child = root;
+ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {
+ child = child->xmlChildrenNode;
+ }
+ while (child != NULL) {
+ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::tag)) {
+ status_t status = Trait::deserialize(doc, child, collection);
+ if (status == NO_ERROR) {
+ nbSkippedElement += 1;
+ }
+ }
+ child = child->next;
+ }
+ if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ return NO_ERROR;
+ }
+ root = root->next;
+ }
+ return NO_ERROR;
+}
+
+const char *const ValueTraits::tag = "value";
+const char *const ValueTraits::collectionTag = "values";
+
+const char ValueTraits::Attributes::literal[] = "literal";
+const char ValueTraits::Attributes::numerical[] = "numerical";
+
+status_t ValueTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &values)
+{
+ std::string literal = getXmlAttribute(child, Attributes::literal);
+ if (literal.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+ return BAD_VALUE;
+ }
+ uint32_t numerical = 0;
+ std::string numericalTag = getXmlAttribute(child, Attributes::numerical);
+ if (numericalTag.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+ return BAD_VALUE;
+ }
+ if (!convertTo(numericalTag, numerical)) {
+ ALOGE("%s: : Invalid value(%s)", __FUNCTION__, numericalTag.c_str());
+ return BAD_VALUE;
+ }
+ values.push_back({numerical, literal});
+ return NO_ERROR;
+}
+
+const char *const CriterionTypeTraits::tag = "criterion_type";
+const char *const CriterionTypeTraits::collectionTag = "criterion_types";
+
+const char CriterionTypeTraits::Attributes::name[] = "name";
+const char CriterionTypeTraits::Attributes::type[] = "type";
+
+status_t CriterionTypeTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
+ Collection &criterionTypes)
+{
+ std::string name = getXmlAttribute(child, Attributes::name);
+ if (name.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::name, name.c_str());
+
+ std::string type = getXmlAttribute(child, Attributes::type);
+ if (type.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::type);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::type, type.c_str());
+ bool isInclusive(type == "inclusive");
+
+ ValuePairs pairs;
+ size_t nbSkippedElements = 0;
+ detail::deserializeCollection<detail::ValueTraits>(doc, child, pairs, nbSkippedElements);
+
+ criterionTypes.push_back({name, isInclusive, pairs});
+ return NO_ERROR;
+}
+
+const char *const CriterionTraits::tag = "criterion";
+const char *const CriterionTraits::collectionTag = "criteria";
+
+const char CriterionTraits::Attributes::name[] = "name";
+const char CriterionTraits::Attributes::type[] = "type";
+const char CriterionTraits::Attributes::defaultVal[] = "default";
+
+status_t CriterionTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &criteria)
+{
+ std::string name = getXmlAttribute(child, Attributes::name);
+ if (name.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
+
+ std::string defaultValue = getXmlAttribute(child, Attributes::defaultVal);
+ if (defaultValue.empty()) {
+ // Not mandatory to provide a default value for a criterion, even it is recommanded...
+ ALOGV("%s: No attribute %s found", __FUNCTION__, Attributes::defaultVal);
+ }
+ ALOGV("%s: %s = %s", __FUNCTION__, Attributes::defaultVal, defaultValue.c_str());
+
+ std::string typeName = getXmlAttribute(child, Attributes::type);
+ if (typeName.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s = %s", __FUNCTION__, Attributes::type, typeName.c_str());
+
+ criteria.push_back({name, typeName, defaultValue});
+ return NO_ERROR;
+}
+} // namespace detail
+
+ParsingResult parse(const char* path) {
+ xmlDocPtr doc;
+ doc = xmlParseFile(path);
+ if (doc == NULL) {
+ ALOGE("%s: Could not parse document %s", __FUNCTION__, path);
+ return {nullptr, 0};
+ }
+ xmlNodePtr cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ ALOGE("%s: Could not parse: empty document %s", __FUNCTION__, path);
+ xmlFreeDoc(doc);
+ return {nullptr, 0};
+ }
+ if (xmlXIncludeProcess(doc) < 0) {
+ ALOGE("%s: libxml failed to resolve XIncludes on document %s", __FUNCTION__, path);
+ return {nullptr, 0};
+ }
+ size_t nbSkippedElements = 0;
+ auto config = std::make_unique<Config>();
+
+ detail::deserializeCollection<detail::CriterionTraits>(
+ doc, cur, config->criteria, nbSkippedElements);
+ detail::deserializeCollection<detail::CriterionTypeTraits>(
+ doc, cur, config->criterionTypes, nbSkippedElements);
+
+ return {std::move(config), nbSkippedElements};
+}
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
new file mode 100644
index 0000000..467d0e1
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <utils/Errors.h>
+
+struct _xmlNode;
+struct _xmlDoc;
+
+namespace android {
+namespace audio_policy {
+namespace wrapper_config {
+
+/** Default path of audio policy usages configuration file. */
+constexpr char DEFAULT_PATH[] = "/vendor/etc/policy_wrapper_configuration.xml";
+
+/** Directories where the effect libraries will be search for. */
+constexpr const char* POLICY_USAGE_LIBRARY_PATH[] = {"/odm/etc/", "/vendor/etc/", "/system/etc/"};
+
+using ValuePair = std::pair<uint32_t, std::string>;
+using ValuePairs = std::vector<ValuePair>;
+
+struct CriterionType
+{
+ std::string name;
+ bool isInclusive;
+ ValuePairs valuePairs;
+};
+
+using CriterionTypes = std::vector<CriterionType>;
+
+struct Criterion
+{
+ std::string name;
+ std::string typeName;
+ std::string defaultLiteralValue;
+};
+
+using Criteria = std::vector<Criterion>;
+
+struct Config {
+ float version;
+ Criteria criteria;
+ CriterionTypes criterionTypes;
+};
+
+namespace detail
+{
+struct ValueTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char literal[];
+ static const char numerical[];
+ };
+
+ typedef ValuePair Element;
+ typedef ValuePair *PtrElement;
+ typedef ValuePairs Collection;
+
+ static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+ Collection &collection);
+};
+
+struct CriterionTypeTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char name[];
+ static const char type[];
+ };
+
+ typedef CriterionType Element;
+ typedef CriterionType *PtrElement;
+ typedef CriterionTypes Collection;
+
+ static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+ Collection &collection);
+};
+
+struct CriterionTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char name[];
+ static const char type[];
+ static const char defaultVal[];
+ };
+
+ typedef Criterion Element;
+ typedef Criterion *PtrElement;
+ typedef Criteria Collection;
+
+ static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+ Collection &collection);
+};
+} // namespace detail
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+ /** Parsed config, nullptr if the xml lib could not load the file */
+ std::unique_ptr<Config> parsedConfig;
+ size_t nbSkippedElement; //< Number of skipped invalid product strategies
+};
+
+/** Parses the provided audio policy usage configuration.
+ * @return audio policy usage @see Config
+ */
+ParsingResult parse(const char* path = DEFAULT_PATH);
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h b/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
deleted file mode 100644
index e4fd176..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#pragma once
-
-#include <string>
-#include <system/audio_policy.h>
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-// Definitions for audio policy criteria configuration file (audio_policy_criteria.conf) //
-// //
-// @TODO: scripted from audio.h & audio_policy,h //
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static const char *const gAudioPolicyCriteriaConfFilePath =
- "/system/etc/audio_policy_criteria.conf";
-static const char *const gAudioPolicyCriteriaVendorConfFilePath =
- "/vendor/etc/audio_policy_criteria.conf";
-
-/**
- * PFW instances tags
- */
-static const std::string &gPolicyConfTag = "Policy";
-static const std::string &gDefaultTag = "Default";
-static const std::string &gTypeTag = "Type";
-
-/**
- * PFW elements tags
- */
-static const std::string &gInclusiveCriterionTypeTag = "InclusiveCriterionType";
-static const std::string &gExclusiveCriterionTypeTag = "ExclusiveCriterionType";
-static const std::string &gCriterionTag = "Criterion";
-
-/**
- * PFW known criterion tags
- */
-static const std::string &gInputDeviceCriterionTag = "AvailableInputDevices";
-static const std::string &gOutputDeviceCriterionTag = "AvailableOutputDevices";
-static const std::string &gPhoneStateCriterionTag = "TelephonyMode";
-
-/**
- * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
- */
-static const std::string gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
-{
- [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
- [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
- [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
- [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
- [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
- [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
- [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
- [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
-};
-
-
-
-
-
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf b/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
deleted file mode 100644
index 043d5a6..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
+++ /dev/null
@@ -1,146 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Criteria file example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-#########################################################
-# Criterion type Example:
-# For each criterion, a couple of numerical, literal values must be provided to the PFW.
-# The numerical part is not mandatory. If not filled by the user, a default numerical value will be
-# automatically provided by audio HAL using the following logic:
-# - Exclusive criterion:
-# * 0 -> first literal value,
-# * 1 -> second literal value,
-# ...
-# * N -> (N+1)th literal value.
-# - Inclusive criterion:
-# * 1 << 0 -> first literal value,
-# * 1 << 1 -> second literal value,
-# ...
-# * 1 << N -> (N+1)th literal value,
-#
-#########################################################
-# Policy {
-# InclusiveCriterionType|ExclusiveCriterionType {
-# <Criterion Name> [numerical value 1:]<literal value 1>,[numerical value 2:]<literal value 2>,<literal value 3>,...
-# }
-# }
-
-#########################################################
-# Criterion:
-#########################################################
-# Policy {
-# Criterion {
-# <Criterion Name> {
-# Type <Criterion type name>
-# Default <default value of the criterion>
-# }
-# }
-# }
-
-Policy {
- InclusiveCriterionType {
- #
- # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
- # AUDIO_DEVICE_OUT_* within <system/audio.h> file of android.
- #
- OutputDevicesMaskType Earpiece,Speaker,WiredHeadset,WiredHeadphone,BluetoothSco,BluetoothScoHeadset,BluetoothScoCarkit,BluetoothA2dp,BluetoothA2dpHeadphones,BluetoothA2dpSpeaker,Hdmi,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,RemoteSubmix,TelephonyTx,Line,HdmiArc,Spdif,Fm,AuxLine,SpeakerSafe
- #
- # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
- # AUDIO_DEVICE_IN_* within <system/audio.h> file of android.
- # Note also that direction bit will be decimated by AudioHAL in order to allow using a mask
- # with the cardinality of 1 between a bit and an input device.
- #
- InputDevicesMaskType Communication,Ambient,BuiltinMic,BluetoothScoHeadset,WiredHeadset,Hdmi,TelephonyRx,BackMic,RemoteSubmix,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,FmTuner,TvTune,Line,Spdif,BluetoothA2dp,Loopback
- }
- ExclusiveCriterionType {
- #
- # The values of the mode MUST be aligned with the definition of the audio_mode_t
- # from system/audio.h
- #
- AndroidModeType 0:Normal,1:RingTone,2:InCall,3:InCommunication
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForCommunicationType 0:ForceNone,1:ForceSpeaker,3:ForceBtSco
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForMediaType 0:ForceNone,1:ForceSpeaker,2:ForceHeadphones,4:ForceBtA2dp,5:ForceWiredAccessory,8:ForceAnalogDock,9:ForceDigitalDock,10:ForceNoBtA2dp
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForRecordType 0:ForceNone,3:ForceBtSco,5:ForceWiredAccessory
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForDockType 0:ForceNone,5:ForceWiredAccessory,6:ForceBtCarDock,7:ForceBtDeskDock,8:ForceAnalogDock,9:ForceDigitalDock
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForSystemType 0:ForceNone,11:ForceSystemEnforced
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForHdmiSystemAudioType 0:ForceNone,12:ForceHdmiSystemEnforced
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio_policy.h
- #
- ForceUseForEncodedSurroundType 0:ForceNone,13:ForceEncodedSurroundNever,14:ForceEncodedSurroundAlways
- }
-
- Criterion {
- AvailableInputDevices {
- Type InputDevicesMaskType
- Default none
- }
- AvailableOutputDevices {
- Type OutputDevicesMaskType
- Default none
- }
- TelephonyMode {
- Type AndroidModeType
- Default Normal
- }
- ForceUseForCommunication {
- Type ForceUseForCommunicationType
- Default ForceNone
- }
- ForceUseForMedia {
- Type ForceUseForMediaType
- Default ForceNone
- }
- ForceUseForRecord {
- Type ForceUseForRecordType
- Default ForceNone
- }
- ForceUseForDock {
- Type ForceUseForDockType
- Default ForceNone
- }
- ForceUseForSystem {
- Type ForceUseForSystemType
- Default ForceNone
- }
- ForceUseForHdmiSystemAudio {
- Type ForceUseForHdmiSystemAudioType
- Default ForceNone
- }
- ForceUseForEncodedSurround {
- Type ForceUseForEncodedSurroundType
- Default ForceNone
- }
- }
-}
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
new file mode 100644
index 0000000..ec82b2e
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
@@ -0,0 +1,30 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 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.
+-->
+<criteria>
+ <criterion name="AvailableInputDevices" type="InputDevicesMaskType" default="none"/>
+ <criterion name="AvailableOutputDevices" type="OutputDevicesMaskType" default="none"/>
+ <criterion name="AvailableOutputDevicesAddresses" type="OutputDevicesAddressesType" default="none"/>
+ <criterion name="AvailableInputDevicesAddresses" type="InputDevicesAddressesType" default="none"/>
+ <criterion name="TelephonyMode" type="AndroidModeType" default="Normal"/>
+ <criterion name="ForceUseForCommunication" type="ForceUseForCommunicationType" default="ForceNone"/>
+ <criterion name="ForceUseForMedia" type="ForceUseForMediaType" default="ForceNone"/>
+ <criterion name="ForceUseForRecord" type="ForceUseForRecordType" default="ForceNone"/>
+ <criterion name="ForceUseForDock" type="ForceUseForDockType" default="ForceNone"/>
+ <criterion name="ForceUseForSystem" type="ForceUseForSystemType" default="ForceNone"/>
+ <criterion name="ForceUseForHdmiSystemAudio" type="ForceUseForHdmiSystemAudioType" default="ForceNone"/>
+ <criterion name="ForceUseForEncodedSurround" type="ForceUseForEncodedSurroundType" default="ForceNone"/>
+ <criterion name="ForceUseForVibrateRinging" type="ForceUseForVibrateRingingType" default="ForceNone"/>
+</criteria>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
new file mode 100644
index 0000000..6cb799f
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
@@ -0,0 +1,91 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 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.
+-->
+<criterion_types>
+ <criterion_type name="OutputDevicesMaskType" type="inclusive"/>
+ <criterion_type name="InputDevicesMaskType" type="inclusive"/>
+ <criterion_type name="OutputDevicesAddressesType" type="inclusive"/>
+ <criterion_type name="InputDevicesAddressesType" type="inclusive"/>
+ <criterion_type name="AndroidModeType" type="exclusive"/>
+ <criterion_type name="BooleanType" type="exclusive">
+ <values>
+ <value literal="False" numerical="0"/>
+ <value literal="True" numerical="1"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForCommunicationType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceSpeaker" numerical="1"/>
+ <value literal="ForceBtSco" numerical="3"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForMediaType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceSpeaker" numerical="1"/>
+ <value literal="ForceHeadphones" numerical="2"/>
+ <value literal="ForceBtA2dp" numerical="4"/>
+ <value literal="ForceWiredAccessory" numerical="5"/>
+ <value literal="ForceAnalogDock" numerical="8"/>
+ <value literal="ForceDigitalDock" numerical="9"/>
+ <value literal="ForceNoBtA2dp" numerical="10"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForRecordType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceBtSco" numerical="3"/>
+ <value literal="ForceWiredAccessory" numerical="5"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForDockType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceWiredAccessory" numerical="5"/>
+ <value literal="ForceBtCarDock" numerical="6"/>
+ <value literal="ForceBtDeskDock" numerical="7"/>
+ <value literal="ForceAnalogDock" numerical="8"/>
+ <value literal="ForceDigitalDock" numerical="9"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForSystemType" type="exclusive" >
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceSystemEnforced" numerical="11"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForHdmiSystemAudioType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceHdmiSystemEnforced" numerical="12"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForEncodedSurroundType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceEncodedSurroundNever" numerical="13"/>
+ <value literal="ForceEncodedSurroundAlways" numerical="14"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForVibrateRingingType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceBtSco" numerical="3"/>
+ </values>
+ </criterion_type>
+</criterion_types>
+
+
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
new file mode 100644
index 0000000..5d9193b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2018 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.
+-->
+<!--
+ These are the minimum required criteria to be used by Audio HAL to ensure a basic
+ user experience on an Android device
+-->
+<configuration name="audio_policy_wrapper_configuration" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <xi:include href="policy_criterion_types.xml"/>
+ <xi:include href="policy_criteria.xml"/>
+
+</configuration>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index 4c1acfe..1a634a1 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,10 +16,15 @@
#pragma once
+#include <AudioGain.h>
+#include <AudioPort.h>
+#include <HwModule.h>
+#include <DeviceDescriptor.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <utils/Errors.h>
#include <utils/RWLock.h>
+#include <utils/RefBase.h>
#include <list>
#include <map>
#include <string>
@@ -27,27 +32,17 @@
class CParameterMgrPlatformConnector;
class ISelectionCriterionInterface;
-class ISelectionCriterionTypeInterface;
struct cnode;
class ParameterMgrPlatformConnectorLogger;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
class ParameterManagerWrapper
{
private:
- typedef std::pair<int, const char *> CriterionTypeValuePair;
-
- typedef std::map<std::string, ISelectionCriterionInterface *> CriterionCollection;
- typedef std::map<std::string, ISelectionCriterionTypeInterface *> CriterionTypeCollection;
- typedef CriterionCollection::iterator CriterionMapIterator;
- typedef CriterionCollection::const_iterator CriterionMapConstIterator;
- typedef CriterionTypeCollection::iterator CriterionTypeMapIterator;
- typedef CriterionTypeCollection::const_iterator CriteriaTypeMapConstIterator;
+ using Criteria = std::map<std::string, ISelectionCriterionInterface *>;
public:
ParameterManagerWrapper();
@@ -120,6 +115,9 @@
*/
status_t setAvailableOutputDevices(audio_devices_t outputDevices);
+ status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state);
+
private:
/**
* Apply the configuration of the platform on the policy parameter manager.
@@ -136,93 +134,11 @@
/**
* Load the criterion configuration file.
*
- * @param[in] path Criterion conf file path.
- *
* @return NO_ERROR is parsing successful, error code otherwise.
*/
- status_t loadAudioPolicyCriteriaConfig(const char *path);
+ status_t loadConfig();
- /**
- * Add a criterion type to AudioPolicyPfw.
- *
- * @param[in] typeName of the PFW criterion type.
- * @param[in] isInclusive attribute of the criterion type.
- */
- void addCriterionType(const std::string &typeName, bool isInclusive);
-
- /**
- * Add a criterion type value pair to AudioPolicyPfw.
- *
- * @param[in] typeName criterion type name to which this value pair is added to.
- * @param[in] numeric part of the value pair.
- * @param[in] literal part of the value pair.
- */
- void addCriterionTypeValuePair(const std::string &typeName, uint32_t numeric,
- const std::string &literal);
-
- /**
- * Add a criterion to AudioPolicyPfw.
- *
- * @param[in] name of the PFW criterion.
- * @param[in] typeName criterion type name to which this criterion is associated to.
- * @param[in] defaultLiteralValue of the PFW criterion.
- */
- void addCriterion(const std::string &name,
- const std::string &typeName,
- const std::string &defaultLiteralValue);
- /**
- * Parse and load the inclusive criterion type from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadInclusiveCriterionType(cnode *root);
-
- /**
- * Parse and load the exclusive criterion type from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadExclusiveCriterionType(cnode *root);
-
- /**
- * Parse and load the criteria from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadCriteria(cnode *root);
-
- /**
- * Parse and load a criterion from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadCriterion(cnode *root);
-
- /**
- * Parse and load the criterion types from configuration file.
- *
- * @param[in] root node of the configuration file
- * @param[in] isInclusive true if inclusive, false is exclusive.
- */
- void loadCriterionType(cnode *root, bool isInclusive);
-
- /**
- * Load the configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadConfig(cnode *root);
-
- /**
- * Parse and load the chidren node from a given root node.
- *
- * @param[in] root node of the configuration file
- * @param[out] defaultValue of the parameter manager element to retrieve.
- * @param[out] type of the parameter manager element to retrieve.
- */
- void parseChildren(cnode *root, std::string &defaultValue, std::string &type);
-
- /**
+ /**
* Retrieve an element from a map by its name.
*
* @tparam T type of element to search.
@@ -266,8 +182,7 @@
bool isValueValidForCriterion(ISelectionCriterionInterface *criterion, int valueToCheck);
- CriterionTypeCollection mPolicyCriterionTypes; /**< Policy Criterion Type map. */
- CriterionCollection mPolicyCriteria; /**< Policy Criterion Map. */
+ Criteria mPolicyCriteria; /**< Policy Criterion Map. */
CParameterMgrPlatformConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
ParameterMgrPlatformConnectorLogger *mPfwConnectorLogger; /**< Policy PFW logger. */
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index aa205f0..5544821 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2674,6 +2674,59 @@
}
}
+status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
+ // uid/device affinity is only for output devices
+ for (size_t i = 0; i < devices.size(); i++) {
+ if (!audio_is_output_device(devices[i].mType)) {
+ ALOGE("setUidDeviceAffinities() device=%08x is NOT an output device",
+ devices[i].mType);
+ return BAD_VALUE;
+ }
+ }
+ status_t res = mPolicyMixes.setUidDeviceAffinities(uid, devices);
+ if (res == NO_ERROR) {
+ // reevaluate outputs for all given devices
+ for (size_t i = 0; i < devices.size(); i++) {
+ sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+ devices[i].mType, devices[i].mAddress, String8());
+ SortedVector<audio_io_handle_t> outputs;
+ if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ outputs,
+ devDesc->address()) != NO_ERROR) {
+ ALOGE("setUidDeviceAffinities() error in checkOutputsForDevice for device=%08x"
+ " addr=%s", devices[i].mType, devices[i].mAddress.string());
+ return INVALID_OPERATION;
+ }
+ }
+ }
+ return res;
+}
+
+status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
+ ALOGV("%s() uid=%d", __FUNCTION__, uid);
+ Vector<AudioDeviceTypeAddr> devices;
+ status_t res = mPolicyMixes.getDevicesForUid(uid, devices);
+ if (res == NO_ERROR) {
+ // reevaluate outputs for all found devices
+ for (size_t i = 0; i < devices.size(); i++) {
+ sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+ devices[i].mType, devices[i].mAddress, String8());
+ SortedVector<audio_io_handle_t> outputs;
+ if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ outputs,
+ devDesc->address()) != NO_ERROR) {
+ ALOGE("%s() error in checkOutputsForDevice for device=%08x addr=%s",
+ __FUNCTION__, devices[i].mType, devices[i].mAddress.string());
+ return INVALID_OPERATION;
+ }
+ }
+ }
+
+ return res;
+}
+
void AudioPolicyManager::dump(String8 *dst) const
{
dst->appendFormat("\nAudioPolicyManager Dump: %p\n", this);
@@ -4089,9 +4142,9 @@
for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
if (mAvailableInputDevices[i]->address().isEmpty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
- mAvailableInputDevices[i]->address() = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ mAvailableInputDevices[i]->setAddress(String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS));
} else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
- mAvailableInputDevices[i]->address() = String8(AUDIO_BACK_MICROPHONE_ADDRESS);
+ mAvailableInputDevices[i]->setAddress(String8(AUDIO_BACK_MICROPHONE_ADDRESS));
}
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 35dd87c..9eb1dcf 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -218,6 +218,9 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes);
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
+ virtual status_t setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices);
+ virtual status_t removeUidDeviceAffinities(uid_t uid);
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 439764b..80503fd 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1037,6 +1037,31 @@
}
}
+status_t AudioPolicyService::setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ Mutex::Autolock _l(mLock);
+ if(!modifyAudioRoutingAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ AutoCallerClear acc;
+ return mAudioPolicyManager->setUidDeviceAffinities(uid, devices);
+}
+
+status_t AudioPolicyService::removeUidDeviceAffinities(uid_t uid) {
+ Mutex::Autolock _l(mLock);
+ if(!modifyAudioRoutingAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ AutoCallerClear acc;
+ return mAudioPolicyManager->removeUidDeviceAffinities(uid);
+}
+
status_t AudioPolicyService::startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId)
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c44d816..959e757 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -199,6 +199,10 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+
+ virtual status_t removeUidDeviceAffinities(uid_t uid);
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId);
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 025f0b2..851dd69 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -83,6 +83,7 @@
"libhidltransport",
"libjpeg",
"libmemunreachable",
+ "libsensorprivacy",
"libstagefright_foundation",
"android.frameworks.cameraservice.common@2.0",
"android.frameworks.cameraservice.service@2.0",
@@ -100,6 +101,7 @@
"libbinder",
"libcamera_client",
"libfmq",
+ "libsensorprivacy",
],
include_dirs: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6003607..c3113bf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -54,6 +54,7 @@
#include <media/IMediaHTTPService.h>
#include <media/mediaplayer.h>
#include <mediautils/BatteryNotifier.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
@@ -145,6 +146,8 @@
mUidPolicy = new UidPolicy(this);
mUidPolicy->registerSelf();
+ mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
+ mSensorPrivacyPolicy->registerSelf();
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
@@ -230,6 +233,7 @@
CameraService::~CameraService() {
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
mUidPolicy->unregisterSelf();
+ mSensorPrivacyPolicy->unregisterSelf();
}
void CameraService::onNewProviderRegistered() {
@@ -951,6 +955,14 @@
clientName8.string(), clientUid, clientPid, cameraId.string());
}
+ // If sensor privacy is enabled then prevent access to the camera
+ if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
+ ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled");
+ return STATUS_ERROR_FMT(ERROR_DISABLED,
+ "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy "
+ "is enabled", clientName8.string(), clientUid, clientPid, cameraId.string());
+ }
+
// Only use passed in clientPid to check permission. Use calling PID as the client PID that's
// connected to camera service directly.
originalClientPid = clientPid;
@@ -1603,9 +1615,10 @@
switch(eventId) {
case ICameraService::EVENT_USER_SWITCHED: {
- // Try to register for UID policy updates, in case we're recovering
+ // Try to register for UID and sensor privacy policy updates, in case we're recovering
// from a system server crash
mUidPolicy->registerSelf();
+ mSensorPrivacyPolicy->registerSelf();
doUserSwitch(/*newUserIds*/ args);
break;
}
@@ -2577,6 +2590,59 @@
}
// ----------------------------------------------------------------------------
+// SensorPrivacyPolicy
+// ----------------------------------------------------------------------------
+void CameraService::SensorPrivacyPolicy::registerSelf() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ if (mRegistered) {
+ return;
+ }
+ SensorPrivacyManager spm;
+ spm.addSensorPrivacyListener(this);
+ mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
+ status_t res = spm.linkToDeath(this);
+ if (res == OK) {
+ mRegistered = true;
+ ALOGV("SensorPrivacyPolicy: Registered with SensorPrivacyManager");
+ }
+}
+
+void CameraService::SensorPrivacyPolicy::unregisterSelf() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ SensorPrivacyManager spm;
+ spm.removeSensorPrivacyListener(this);
+ spm.unlinkToDeath(this);
+ mRegistered = false;
+ ALOGV("SensorPrivacyPolicy: Unregistered with SensorPrivacyManager");
+}
+
+bool CameraService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ return mSensorPrivacyEnabled;
+}
+
+binder::Status CameraService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) {
+ {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ mSensorPrivacyEnabled = enabled;
+ }
+ // if sensor privacy is enabled then block all clients from accessing the camera
+ if (enabled) {
+ sp<CameraService> service = mService.promote();
+ if (service != nullptr) {
+ service->blockAllClients();
+ }
+ }
+ return binder::Status::ok();
+}
+
+void CameraService::SensorPrivacyPolicy::binderDied(const wp<IBinder>& /*who*/) {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ ALOGV("SensorPrivacyPolicy: SensorPrivacyManager has died");
+ mRegistered = false;
+}
+
+// ----------------------------------------------------------------------------
// CameraState
// ----------------------------------------------------------------------------
@@ -3062,6 +3128,18 @@
}
}
+void CameraService::blockAllClients() {
+ const auto clients = mActiveClientManager.getAll();
+ for (auto& current : clients) {
+ if (current != nullptr) {
+ const auto basicClient = current->getValue();
+ if (basicClient.get() != nullptr) {
+ basicClient->block();
+ }
+ }
+ }
+}
+
// NOTE: This is a remote API - make sure all args are validated
status_t CameraService::shellCommand(int in, int out, int err, const Vector<String16>& args) {
if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d332f6e..a296198 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#include <android/hardware/BnCameraService.h>
+#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/hardware/ICameraServiceListener.h>
#include <android/hardware/ICameraServiceProxy.h>
@@ -554,8 +555,35 @@
std::unordered_map<uid_t, bool> mOverrideUids;
}; // class UidPolicy
+ // If sensor privacy is enabled then all apps, including those that are active, should be
+ // prevented from accessing the camera.
+ class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener,
+ public virtual IBinder::DeathRecipient {
+ public:
+ explicit SensorPrivacyPolicy(wp<CameraService> service)
+ : mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {}
+
+ void registerSelf();
+ void unregisterSelf();
+
+ bool isSensorPrivacyEnabled();
+
+ binder::Status onSensorPrivacyChanged(bool enabled);
+
+ // IBinder::DeathRecipient implementation
+ virtual void binderDied(const wp<IBinder> &who);
+
+ private:
+ wp<CameraService> mService;
+ Mutex mSensorPrivacyLock;
+ bool mSensorPrivacyEnabled;
+ bool mRegistered;
+ };
+
sp<UidPolicy> mUidPolicy;
+ sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
// Delay-load the Camera HAL module
virtual void onFirstRef();
@@ -825,6 +853,9 @@
// Blocks all clients from the UID
void blockClientsForUid(uid_t uid);
+ // Blocks all active clients.
+ void blockAllClients();
+
// Overrides the UID state as if it is idle
status_t handleSetUidState(const Vector<String16>& args, int err);
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
index e5e5024..f063506 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
@@ -139,18 +139,18 @@
}
CameraMetadataNative &result = resultWrapper->mResult;
auto resultExtras = resultWrapper->mResultExtras;
- auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos;
HCaptureResultExtras hResultExtras =
hardware::cameraservice::utils::conversion::convertToHidl(resultExtras);
- hidl_vec<HPhysicalCaptureResultInfo> hPhysicalCaptureResultInfos =
- hardware::cameraservice::utils::conversion::convertToHidl(
- physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue);
// Convert Metadata into HCameraMetadata;
FmqSizeOrMetadata hResult;
const camera_metadata_t *rawMetadata = result.getAndLock();
converter->convertResultMetadataToHidl(rawMetadata, &hResult);
result.unlock(rawMetadata);
+ auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos;
+ hidl_vec<HPhysicalCaptureResultInfo> hPhysicalCaptureResultInfos =
+ hardware::cameraservice::utils::conversion::convertToHidl(
+ physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue);
auto ret = converter->mBase->onResultReceived(hResult, hResultExtras,
hPhysicalCaptureResultInfos);
if (!ret.isOk()) {
diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp
index 582ce34..a87812b 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -89,8 +89,9 @@
for (auto &handle : windowHandles) {
iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(handle)));
}
+ String16 physicalCameraId16(hOutputConfiguration.physicalCameraId.c_str());
hardware::camera2::params::OutputConfiguration outputConfiguration(
- iGBPs, convertFromHidl(hOutputConfiguration.rotation),
+ iGBPs, convertFromHidl(hOutputConfiguration.rotation), physicalCameraId16,
hOutputConfiguration.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0,
(windowHandles.size() > 1));
return outputConfiguration;
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index 653317b..8c40ad1 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -1,5 +1,6 @@
cc_library_shared {
name: "libmedia_codecserviceregistrant",
+ vendor_available: true,
srcs: [
"CodecServiceRegistrant.cpp",
],
@@ -39,6 +40,7 @@
"libcodec2_soft_opusdec",
"libcodec2_soft_vp8dec",
"libcodec2_soft_vp9dec",
+ "libcodec2_soft_av1dec",
"libcodec2_soft_vp8enc",
"libcodec2_soft_vp9enc",
"libcodec2_soft_rawdec",
diff --git a/services/mediadrm/tests/Android.mk b/services/mediadrm/tests/Android.mk
deleted file mode 100644
index e2f7399..0000000
--- a/services/mediadrm/tests/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := DrmSessionManager_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- DrmSessionManager_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libmediaplayerservice \
- libutils \
-
-LOCAL_C_INCLUDES := \
- frameworks/av/include \
- frameworks/av/media/libmediaplayerservice \
-
-LOCAL_CFLAGS += -Werror -Wall
-
-LOCAL_32_BIT_ONLY := true
-
-include $(BUILD_NATIVE_TEST)
-
diff --git a/services/mediadrm/tests/DrmSessionManager_test.cpp b/services/mediadrm/tests/DrmSessionManager_test.cpp
deleted file mode 100644
index de350a1..0000000
--- a/services/mediadrm/tests/DrmSessionManager_test.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "DrmSessionManager_test"
-#include <utils/Log.h>
-
-#include <gtest/gtest.h>
-
-#include "Drm.h"
-#include "DrmSessionClientInterface.h"
-#include "DrmSessionManager.h"
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ProcessInfoInterface.h>
-
-namespace android {
-
-struct FakeProcessInfo : public ProcessInfoInterface {
- FakeProcessInfo() {}
- virtual ~FakeProcessInfo() {}
-
- virtual bool getPriority(int pid, int* priority) {
- // For testing, use pid as priority.
- // Lower the value higher the priority.
- *priority = pid;
- return true;
- }
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
-};
-
-struct FakeDrm : public DrmSessionClientInterface {
- FakeDrm() {}
- virtual ~FakeDrm() {}
-
- virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
- mReclaimedSessions.push_back(sessionId);
- return true;
- }
-
- const Vector<Vector<uint8_t> >& reclaimedSessions() const {
- return mReclaimedSessions;
- }
-
-private:
- Vector<Vector<uint8_t> > mReclaimedSessions;
-
- DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
-};
-
-static const int kTestPid1 = 30;
-static const int kTestPid2 = 20;
-static const uint8_t kTestSessionId1[] = {1, 2, 3};
-static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
-static const uint8_t kTestSessionId3[] = {9, 0};
-
-class DrmSessionManagerTest : public ::testing::Test {
-public:
- DrmSessionManagerTest()
- : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())),
- mTestDrm1(new FakeDrm()),
- mTestDrm2(new FakeDrm()) {
- GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1);
- GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2);
- GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3);
- }
-
-protected:
- static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) {
- for (size_t i = 0; i < num; ++i) {
- sessionId->push_back(ids[i]);
- }
- }
-
- static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm,
- const Vector<uint8_t>& sessionId, int64_t timeStamp) {
- EXPECT_EQ(drm, info.drm);
- EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId));
- EXPECT_EQ(timeStamp, info.timeStamp);
- }
-
- void addSession() {
- mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3);
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- ssize_t index1 = map.indexOfKey(kTestPid1);
- ASSERT_GE(index1, 0);
- const SessionInfos& infos1 = map[index1];
- EXPECT_EQ(1u, infos1.size());
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0);
-
- ssize_t index2 = map.indexOfKey(kTestPid2);
- ASSERT_GE(index2, 0);
- const SessionInfos& infos2 = map[index2];
- EXPECT_EQ(2u, infos2.size());
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2);
- }
-
- const PidSessionInfosMap& sessionMap() {
- return mDrmSessionManager->mSessionMap;
- }
-
- void testGetLowestPriority() {
- int pid;
- int priority;
- EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- addSession();
- EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- EXPECT_EQ(kTestPid1, pid);
- FakeProcessInfo processInfo;
- int priority1;
- processInfo.getPriority(kTestPid1, &priority1);
- EXPECT_EQ(priority1, priority);
- }
-
- void testGetLeastUsedSession() {
- sp<DrmSessionClientInterface> drm;
- Vector<uint8_t> sessionId;
- EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-
- addSession();
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
- EXPECT_EQ(mTestDrm1, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId));
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId));
-
- // mSessionId2 is no longer the least used session.
- mDrmSessionManager->useSession(mSessionId2);
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId));
- }
-
- sp<DrmSessionManager> mDrmSessionManager;
- sp<FakeDrm> mTestDrm1;
- sp<FakeDrm> mTestDrm2;
- Vector<uint8_t> mSessionId1;
- Vector<uint8_t> mSessionId2;
- Vector<uint8_t> mSessionId3;
-};
-
-TEST_F(DrmSessionManagerTest, addSession) {
- addSession();
-}
-
-TEST_F(DrmSessionManagerTest, useSession) {
- addSession();
-
- mDrmSessionManager->useSession(mSessionId1);
- mDrmSessionManager->useSession(mSessionId3);
-
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4);
-}
-
-TEST_F(DrmSessionManagerTest, removeSession) {
- addSession();
-
- mDrmSessionManager->removeSession(mSessionId2);
-
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos1.size());
- EXPECT_EQ(1u, infos2.size());
- // mSessionId2 has been removed.
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2);
-}
-
-TEST_F(DrmSessionManagerTest, removeDrm) {
- addSession();
-
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {123};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(kTestPid2, drm, sessionId);
-
- mDrmSessionManager->removeDrm(mTestDrm2);
-
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos2.size());
- // mTestDrm2 has been removed.
- ExpectEqSessionInfo(infos2[0], drm, sessionId, 3);
-}
-
-TEST_F(DrmSessionManagerTest, reclaimSession) {
- EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
- addSession();
-
- // calling pid priority is too low
- EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
-
- EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
- EXPECT_EQ(1u, mTestDrm1->reclaimedSessions().size());
- EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
-
- mDrmSessionManager->removeSession(mSessionId1);
-
- // add a session from a higher priority process.
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {1, 3, 5};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(15, drm, sessionId);
-
- EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
- EXPECT_EQ(1u, mTestDrm2->reclaimedSessions().size());
- // mSessionId2 is reclaimed.
- EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
-}
-
-TEST_F(DrmSessionManagerTest, getLowestPriority) {
- testGetLowestPriority();
-}
-
-TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) {
- testGetLeastUsedSession();
-}
-
-} // namespace android
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index e31eadc..6101c8a 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -40,7 +40,7 @@
LOCAL_SRC_FILES := main_extractorservice.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
- liblog libbase libicuuc libavservices_minijail
+ liblog libbase libandroidicu libavservices_minijail
LOCAL_STATIC_LIBRARIES := libicuandroid_utils
LOCAL_MODULE:= mediaextractor
LOCAL_INIT_RC := mediaextractor.rc
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 8b26178..0665930 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -59,6 +59,10 @@
return CreateIDataSourceFromDataSource(source);
}
+std::unordered_set<std::string> MediaExtractorService::getSupportedTypes() {
+ return MediaExtractorFactory::getSupportedTypes();
+}
+
status_t MediaExtractorService::dump(int fd, const Vector<String16>& args) {
return MediaExtractorFactory::dump(fd, args) || dumpExtractors(fd, args);
}
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 6007004..c9cebcf 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -37,6 +37,8 @@
virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length);
+ virtual std::unordered_set<std::string> getSupportedTypes();
+
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
index 6d9ed6f..35ac458 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
@@ -21,6 +21,7 @@
getuid: 1
setpriority: 1
sigaltstack: 1
+fstat: 1
fstatfs: 1
newfstatat: 1
restart_syscall: 1
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 944abcc..fe2ccf2 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -765,10 +765,7 @@
}
recognitionEvent->capture_session = model->mCaptureSession;
- // Don't reset the model state if this recognition event is a get-state response
- if (recognitionEvent->status != RECOGNITION_STATUS_GET_STATE_RESPONSE) {
- model->mState = Model::STATE_IDLE;
- }
+ model->mState = Model::STATE_IDLE;
clients.add(model->mModuleClient);
}
} break;