summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/ICameraService.cpp3
-rw-r--r--camera/ICameraServiceListener.cpp14
-rw-r--r--camera/camera2/ICameraDeviceUser.cpp8
-rw-r--r--camera/camera2/OutputConfiguration.cpp5
-rw-r--r--camera/tests/Android.mk3
-rw-r--r--camera/tests/CameraBinderTests.cpp484
-rw-r--r--camera/tests/VendorTagDescriptorTests.cpp9
-rw-r--r--include/camera/camera2/OutputConfiguration.h2
-rw-r--r--include/media/stagefright/MediaCodecSource.h3
-rw-r--r--include/media/stagefright/MetaData.h4
-rw-r--r--media/libstagefright/ACodec.cpp17
-rw-r--r--media/libstagefright/CameraSource.cpp10
-rw-r--r--media/libstagefright/MediaCodec.cpp22
-rw-r--r--media/libstagefright/MediaCodecList.cpp3
-rw-r--r--media/libstagefright/MediaCodecSource.cpp29
-rw-r--r--media/libstagefright/MediaSync.cpp14
-rw-r--r--media/libstagefright/codecs/mp3dec/SoftMP3.cpp8
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.cpp17
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.h1
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp34
-rw-r--r--media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp11
-rw-r--r--services/audioflinger/PatchPanel.cpp15
-rw-r--r--services/audioflinger/Threads.cpp2
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h8
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.cpp7
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp1
-rw-r--r--services/camera/libcameraservice/CameraService.cpp2
-rw-r--r--services/camera/libcameraservice/common/CameraModule.cpp19
-rw-r--r--services/camera/libcameraservice/common/CameraModule.h2
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp29
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h3
31 files changed, 719 insertions, 70 deletions
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 7bb24ee..7c9720f 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -285,6 +285,7 @@ public:
}
Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeInt32(cameraId);
remote()->transact(BnCameraService::GET_LEGACY_PARAMETERS, data, &reply);
@@ -304,6 +305,7 @@ public:
virtual status_t supportsCameraApi(int cameraId, int apiVersion) {
Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeInt32(cameraId);
data.writeInt32(apiVersion);
remote()->transact(BnCameraService::SUPPORTS_CAMERA_API, data, &reply);
@@ -315,6 +317,7 @@ public:
virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {
Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeInt32(eventId);
data.writeInt32Array(len, args);
remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp
index 90a8bc2..0010325 100644
--- a/camera/ICameraServiceListener.cpp
+++ b/camera/ICameraServiceListener.cpp
@@ -45,8 +45,7 @@ public:
virtual void onStatusChanged(Status status, int32_t cameraId)
{
Parcel data, reply;
- data.writeInterfaceToken(
- ICameraServiceListener::getInterfaceDescriptor());
+ data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
data.writeInt32(static_cast<int32_t>(status));
data.writeInt32(cameraId);
@@ -60,8 +59,7 @@ public:
virtual void onTorchStatusChanged(TorchStatus status, const String16 &cameraId)
{
Parcel data, reply;
- data.writeInterfaceToken(
- ICameraServiceListener::getInterfaceDescriptor());
+ data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
data.writeInt32(static_cast<int32_t>(status));
data.writeString16(cameraId);
@@ -73,14 +71,12 @@ public:
}
};
-IMPLEMENT_META_INTERFACE(CameraServiceListener,
- "android.hardware.ICameraServiceListener");
+IMPLEMENT_META_INTERFACE(CameraServiceListener, "android.hardware.ICameraServiceListener");
// ----------------------------------------------------------------------
-status_t BnCameraServiceListener::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
+status_t BnCameraServiceListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
switch(code) {
case STATUS_CHANGED: {
CHECK_INTERFACE(ICameraServiceListener, data, reply);
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index a7549f2..ffe974b 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -82,7 +82,7 @@ public:
reply.readExceptionCode();
}
- virtual status_t submitRequest(sp<CaptureRequest> request, bool repeating,
+ virtual int submitRequest(sp<CaptureRequest> request, bool repeating,
int64_t *lastFrameNumber)
{
Parcel data, reply;
@@ -111,13 +111,13 @@ public:
}
}
- if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if (res < 0 || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
}
- virtual status_t submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
+ virtual int submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
int64_t *lastFrameNumber)
{
Parcel data, reply;
@@ -151,7 +151,7 @@ public:
resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
- if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if (res < 0 || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 24acaa0..20a23e0 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -65,6 +65,11 @@ OutputConfiguration::OutputConfiguration(const Parcel& parcel) {
gbp.get(), String8(name).string());
}
+OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation) {
+ mGbp = gbp;
+ mRotation = rotation;
+}
+
status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {
parcel.writeInt32(mRotation);
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index 5d37f9e..3777d94 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -17,7 +17,8 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SRC_FILES:= \
- VendorTagDescriptorTests.cpp
+ VendorTagDescriptorTests.cpp \
+ CameraBinderTests.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
new file mode 100644
index 0000000..572fb72
--- /dev/null
+++ b/camera/tests/CameraBinderTests.cpp
@@ -0,0 +1,484 @@
+/*
+ * 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 "CameraBinderTests"
+
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/List.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <system/graphics.h>
+#include <hardware/gralloc.h>
+
+#include <camera/CameraMetadata.h>
+#include <camera/ICameraService.h>
+#include <camera/ICameraServiceListener.h>
+#include <camera/camera2/CaptureRequest.h>
+#include <camera/camera2/ICameraDeviceUser.h>
+#include <camera/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/OutputConfiguration.h>
+
+#include <gui/BufferItemConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <utility>
+#include <vector>
+#include <map>
+#include <algorithm>
+
+using namespace android;
+
+#define ASSERT_NOT_NULL(x) \
+ ASSERT_TRUE((x) != nullptr)
+
+#define SETUP_TIMEOUT 2000000000 // ns
+#define IDLE_TIMEOUT 2000000000 // ns
+
+// Stub listener implementation
+class TestCameraServiceListener : public BnCameraServiceListener {
+ std::map<String16, TorchStatus> mCameraTorchStatuses;
+ std::map<int32_t, Status> mCameraStatuses;
+ mutable Mutex mLock;
+ mutable Condition mCondition;
+ mutable Condition mTorchCondition;
+public:
+ virtual ~TestCameraServiceListener() {};
+
+ virtual void onStatusChanged(Status status, int32_t cameraId) {
+ Mutex::Autolock l(mLock);
+ mCameraStatuses[cameraId] = status;
+ mCondition.broadcast();
+ };
+
+ virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
+ Mutex::Autolock l(mLock);
+ mCameraTorchStatuses[cameraId] = status;
+ mTorchCondition.broadcast();
+ };
+
+ bool waitForNumCameras(size_t num) const {
+ Mutex::Autolock l(mLock);
+
+ if (mCameraStatuses.size() == num) {
+ return true;
+ }
+
+ while (mCameraStatuses.size() < num) {
+ if (mCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ bool waitForTorchState(TorchStatus status, int32_t cameraId) const {
+ Mutex::Autolock l(mLock);
+
+ const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+ if (iter != mCameraTorchStatuses.end() && iter->second == status) {
+ return true;
+ }
+
+ bool foundStatus = false;
+ while (!foundStatus) {
+ if (mTorchCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
+ return false;
+ }
+ const auto& iter =
+ mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+ foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status);
+ }
+ return true;
+ };
+
+ TorchStatus getTorchStatus(int32_t cameraId) const {
+ Mutex::Autolock l(mLock);
+ const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+ if (iter == mCameraTorchStatuses.end()) {
+ return ICameraServiceListener::TORCH_STATUS_UNKNOWN;
+ }
+ return iter->second;
+ };
+
+ Status getStatus(int32_t cameraId) const {
+ Mutex::Autolock l(mLock);
+ const auto& iter = mCameraStatuses.find(cameraId);
+ if (iter == mCameraStatuses.end()) {
+ return ICameraServiceListener::STATUS_UNKNOWN;
+ }
+ return iter->second;
+ };
+};
+
+// Callback implementation
+class TestCameraDeviceCallbacks : public BnCameraDeviceCallbacks {
+public:
+ enum Status {
+ IDLE,
+ ERROR,
+ PREPARED,
+ RUNNING,
+ SENT_RESULT,
+ UNINITIALIZED
+ };
+
+protected:
+ bool mError;
+ Status mLastStatus;
+ mutable std::vector<Status> mStatusesHit;
+ mutable Mutex mLock;
+ mutable Condition mStatusCondition;
+public:
+ TestCameraDeviceCallbacks() : mError(false), mLastStatus(UNINITIALIZED) {}
+
+ virtual ~TestCameraDeviceCallbacks() {}
+
+ virtual void onDeviceError(CameraErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) {
+ ALOGE("%s: onDeviceError occurred with: %d", __FUNCTION__, static_cast<int>(errorCode));
+ Mutex::Autolock l(mLock);
+ mError = true;
+ mLastStatus = ERROR;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ virtual void onDeviceIdle() {
+ Mutex::Autolock l(mLock);
+ mLastStatus = IDLE;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ virtual void onCaptureStarted(const CaptureResultExtras& resultExtras,
+ int64_t timestamp) {
+ Mutex::Autolock l(mLock);
+ mLastStatus = RUNNING;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+
+ virtual void onResultReceived(const CameraMetadata& metadata,
+ const CaptureResultExtras& resultExtras) {
+ Mutex::Autolock l(mLock);
+ mLastStatus = SENT_RESULT;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ virtual void onPrepared(int streamId) {
+ Mutex::Autolock l(mLock);
+ mLastStatus = PREPARED;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ // Test helper functions:
+
+ bool hadError() const {
+ Mutex::Autolock l(mLock);
+ return mError;
+ }
+
+ bool waitForStatus(Status status) const {
+ Mutex::Autolock l(mLock);
+ if (mLastStatus == status) {
+ return true;
+ }
+
+ while (std::find(mStatusesHit.begin(), mStatusesHit.end(), status)
+ == mStatusesHit.end()) {
+
+ if (mStatusCondition.waitRelative(mLock, IDLE_TIMEOUT) != OK) {
+ mStatusesHit.clear();
+ return false;
+ }
+ }
+ mStatusesHit.clear();
+
+ return true;
+
+ }
+
+ void clearStatus() const {
+ Mutex::Autolock l(mLock);
+ mStatusesHit.clear();
+ }
+
+ bool waitForIdle() const {
+ return waitForStatus(IDLE);
+ }
+
+};
+
+// Exercise basic binder calls for the camera service
+TEST(CameraServiceBinderTest, CheckBinderCameraService) {
+ ProcessState::self()->startThreadPool();
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.camera"));
+ ASSERT_NOT_NULL(binder);
+ sp<ICameraService> service = interface_cast<ICameraService>(binder);
+
+
+ int32_t numCameras = service->getNumberOfCameras();
+ EXPECT_LE(0, numCameras);
+
+ // Check listener binder calls
+ sp<TestCameraServiceListener> listener(new TestCameraServiceListener());
+ EXPECT_EQ(OK, service->addListener(listener));
+
+ EXPECT_TRUE(listener->waitForNumCameras(numCameras));
+
+ for (int32_t i = 0; i < numCameras; i++) {
+ // We only care about binder calls for the Camera2 API. Camera1 is deprecated.
+ status_t camera2Support = service->supportsCameraApi(i, ICameraService::API_VERSION_2);
+ if (camera2Support != OK) {
+ EXPECT_EQ(-EOPNOTSUPP, camera2Support);
+ continue;
+ }
+
+ // Check metadata binder call
+ CameraMetadata metadata;
+ EXPECT_EQ(OK, service->getCameraCharacteristics(i, &metadata));
+ EXPECT_FALSE(metadata.isEmpty());
+
+ // Make sure we're available, or skip device tests otherwise
+ ICameraServiceListener::Status s = listener->getStatus(i);
+ EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
+ if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+ continue;
+ }
+
+ // Check connect binder calls
+ sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
+ sp<ICameraDeviceUser> device;
+ EXPECT_EQ(OK, service->connectDevice(callbacks, i, String16("meeeeeeeee!"),
+ ICameraService::USE_CALLING_UID, /*out*/device));
+ ASSERT_NE(nullptr, device.get());
+ device->disconnect();
+ EXPECT_FALSE(callbacks->hadError());
+
+ ICameraServiceListener::TorchStatus torchStatus = listener->getTorchStatus(i);
+ if (torchStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) {
+ // Check torch calls
+ EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
+ /*enabled*/true, callbacks));
+ EXPECT_TRUE(listener->waitForTorchState(
+ ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i));
+ EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
+ /*enabled*/false, callbacks));
+ EXPECT_TRUE(listener->waitForTorchState(
+ ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i));
+ }
+ }
+
+ EXPECT_EQ(OK, service->removeListener(listener));
+}
+
+// Test fixture for client focused binder tests
+class CameraClientBinderTest : public testing::Test {
+protected:
+ sp<ICameraService> service;
+ int32_t numCameras;
+ std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>> openDeviceList;
+ sp<TestCameraServiceListener> serviceListener;
+
+ std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>> openNewDevice(int deviceId) {
+
+ sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
+ sp<ICameraDeviceUser> device;
+ {
+ SCOPED_TRACE("openNewDevice");
+ EXPECT_EQ(OK, service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
+ ICameraService::USE_CALLING_UID, /*out*/device));
+ }
+ auto p = std::make_pair(callbacks, device);
+ openDeviceList.push_back(p);
+ return p;
+ }
+
+ void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>& p) {
+ if (p.second.get() != nullptr) {
+ p.second->disconnect();
+ {
+ SCOPED_TRACE("closeDevice");
+ EXPECT_FALSE(p.first->hadError());
+ }
+ }
+ auto iter = std::find(openDeviceList.begin(), openDeviceList.end(), p);
+ if (iter != openDeviceList.end()) {
+ openDeviceList.erase(iter);
+ }
+ }
+
+ virtual void SetUp() {
+ ProcessState::self()->startThreadPool();
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.camera"));
+ service = interface_cast<ICameraService>(binder);
+ serviceListener = new TestCameraServiceListener();
+ service->addListener(serviceListener);
+ numCameras = service->getNumberOfCameras();
+ }
+
+ virtual void TearDown() {
+ service = nullptr;
+ numCameras = 0;
+ for (auto& p : openDeviceList) {
+ closeDevice(p);
+ }
+ }
+
+};
+
+TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
+ ASSERT_NOT_NULL(service);
+
+ EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
+ for (int32_t i = 0; i < numCameras; i++) {
+ // Make sure we're available, or skip device tests otherwise
+ ICameraServiceListener::Status s = serviceListener->getStatus(i);
+ EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
+ if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+ continue;
+ }
+
+ auto p = openNewDevice(i);
+ sp<TestCameraDeviceCallbacks> callbacks = p.first;
+ sp<ICameraDeviceUser> device = p.second;
+
+ // Setup a buffer queue; I'm just using the vendor opaque format here as that is
+ // guaranteed to be present
+ sp<IGraphicBufferProducer> gbProducer;
+ sp<IGraphicBufferConsumer> gbConsumer;
+ BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
+ sp<BufferItemConsumer> opaqueConsumer = new BufferItemConsumer(gbConsumer,
+ GRALLOC_USAGE_SW_READ_NEVER, /*maxImages*/2, /*controlledByApp*/true);
+ EXPECT_TRUE(opaqueConsumer.get() != nullptr);
+ opaqueConsumer->setName(String8("nom nom nom"));
+
+ // Set to VGA dimens for default, as that is guaranteed to be present
+ EXPECT_EQ(OK, gbConsumer->setDefaultBufferSize(640, 480));
+ EXPECT_EQ(OK, gbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED));
+
+ sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
+
+ OutputConfiguration output(gbProducer, /*rotation*/0);
+
+ // Can we configure?
+ EXPECT_EQ(OK, device->beginConfigure());
+ status_t streamId = device->createStream(output);
+ EXPECT_LE(0, streamId);
+ EXPECT_EQ(OK, device->endConfigure());
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we make requests?
+ CameraMetadata requestTemplate;
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate));
+ sp<CaptureRequest> request(new CaptureRequest());
+ request->mMetadata = requestTemplate;
+ request->mSurfaceList.add(surface);
+ request->mIsReprocess = false;
+ int64_t lastFrameNumber = 0;
+ int64_t lastFrameNumberPrev = 0;
+ callbacks->clearStatus();
+ int requestId = device->submitRequest(request, /*streaming*/true, /*out*/&lastFrameNumber);
+ EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+ EXPECT_LE(0, requestId);
+
+ // Can we stop requests?
+ EXPECT_EQ(OK, device->cancelRequest(requestId, /*out*/&lastFrameNumber));
+ EXPECT_TRUE(callbacks->waitForIdle());
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we do it again?
+ lastFrameNumberPrev = lastFrameNumber;
+ lastFrameNumber = 0;
+ requestTemplate.clear();
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate));
+ sp<CaptureRequest> request2(new CaptureRequest());
+ request2->mMetadata = requestTemplate;
+ request2->mSurfaceList.add(surface);
+ request2->mIsReprocess = false;
+ callbacks->clearStatus();
+ int requestId2 = device->submitRequest(request2, /*streaming*/true,
+ /*out*/&lastFrameNumber);
+ EXPECT_EQ(-1, lastFrameNumber);
+ lastFrameNumber = 0;
+ EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+ EXPECT_LE(0, requestId2);
+ EXPECT_EQ(OK, device->cancelRequest(requestId2, /*out*/&lastFrameNumber));
+ EXPECT_TRUE(callbacks->waitForIdle());
+ EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
+ sleep(/*second*/1); // allow some time for errors to show up, if any
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we do it with a request list?
+ lastFrameNumberPrev = lastFrameNumber;
+ lastFrameNumber = 0;
+ requestTemplate.clear();
+ CameraMetadata requestTemplate2;
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate));
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate2));
+ sp<CaptureRequest> request3(new CaptureRequest());
+ sp<CaptureRequest> request4(new CaptureRequest());
+ request3->mMetadata = requestTemplate;
+ request3->mSurfaceList.add(surface);
+ request3->mIsReprocess = false;
+ request4->mMetadata = requestTemplate2;
+ request4->mSurfaceList.add(surface);
+ request4->mIsReprocess = false;
+ List<sp<CaptureRequest>> requestList;
+ requestList.push_back(request3);
+ requestList.push_back(request4);
+
+ callbacks->clearStatus();
+ int requestId3 = device->submitRequestList(requestList, /*streaming*/false,
+ /*out*/&lastFrameNumber);
+ EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+ EXPECT_TRUE(callbacks->waitForIdle());
+ EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
+ sleep(/*second*/1); // allow some time for errors to show up, if any
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we unconfigure?
+ EXPECT_EQ(OK, device->beginConfigure());
+ EXPECT_EQ(OK, device->deleteStream(streamId));
+ EXPECT_EQ(OK, device->endConfigure());
+ sleep(/*second*/1); // allow some time for errors to show up, if any
+ EXPECT_FALSE(callbacks->hadError());
+
+ closeDevice(p);
+ }
+
+};
diff --git a/camera/tests/VendorTagDescriptorTests.cpp b/camera/tests/VendorTagDescriptorTests.cpp
index 6624e79..9082dbf 100644
--- a/camera/tests/VendorTagDescriptorTests.cpp
+++ b/camera/tests/VendorTagDescriptorTests.cpp
@@ -53,6 +53,10 @@ static bool ContainsTag(uint32_t* tagArray, size_t size, uint32_t tag) {
extern "C" {
+static int zero_get_tag_count(const vendor_tag_ops_t* vOps) {
+ return 0;
+}
+
static int default_get_tag_count(const vendor_tag_ops_t* vOps) {
return VENDOR_TAG_COUNT_ERR;
}
@@ -173,10 +177,13 @@ TEST(VendorTagDescriptorTest, ErrorConditions) {
vendor_tag_ops_t vOps;
FillWithDefaults(&vOps);
+ // Make empty tag count
+ vOps.get_tag_count = zero_get_tag_count;
+
// Ensure create fails when using null vOps
EXPECT_EQ(BAD_VALUE, VendorTagDescriptor::createDescriptorFromOps(/*vOps*/NULL, vDesc));
- // Ensure create works when there are no vtags defined in a well-formed vOps
+ // Ensure creat succeeds for empty vendor tag ops
ASSERT_EQ(OK, VendorTagDescriptor::createDescriptorFromOps(&vOps, vDesc));
// Ensure defaults are returned when no vtags are defined, or tag is unknown
diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h
index e6b679f..5bcbe15 100644
--- a/include/camera/camera2/OutputConfiguration.h
+++ b/include/camera/camera2/OutputConfiguration.h
@@ -39,6 +39,8 @@ public:
// getRotation will be INVALID_ROTATION if error occurred
OutputConfiguration(const Parcel& parcel);
+ OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation);
+
private:
sp<IGraphicBufferProducer> mGbp;
int mRotation;
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index a991b02..71f58a9 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -108,6 +108,9 @@ private:
bool mStarted;
bool mStopping;
bool mDoMoreWorkPending;
+ bool mSetEncoderFormat;
+ int mEncoderFormat;
+ int mEncoderDataSpace;
sp<AMessage> mEncoderActivityNotify;
sp<IGraphicBufferProducer> mGraphicBufferProducer;
sp<IGraphicBufferConsumer> mGraphicBufferConsumer;
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index ca80123..726b197 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -70,7 +70,9 @@ enum {
kKeyDriftTime = 'dftT', // int64_t (usecs)
kKeyAnchorTime = 'ancT', // int64_t (usecs)
kKeyDuration = 'dura', // int64_t (usecs)
- kKeyColorFormat = 'colf',
+ kKeyPixelFormat = 'pixf', // int32_t
+ kKeyColorFormat = 'colf', // int32_t
+ kKeyColorSpace = 'cols', // int32_t
kKeyPlatformPrivate = 'priv', // pointer
kKeyDecoderComponent = 'decC', // cstring
kKeyBufferID = 'bfID',
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index bb53ce6..7452e4b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1639,6 +1639,14 @@ status_t ACodec::configureCodec(
if (mInputMetadataType == kMetadataBufferTypeGrallocSource) {
mInputMetadataType = kMetadataBufferTypeCameraSource;
}
+
+ uint32_t usageBits;
+ if (mOMX->getParameter(
+ mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ &usageBits, sizeof(usageBits)) == OK) {
+ inputFormat->setInt32(
+ "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
+ }
}
int32_t prependSPSPPS = 0;
@@ -5234,6 +5242,7 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
if (err == OK) {
info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
} else {
+ ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
info->mStatus = BufferInfo::OWNED_BY_US;
// keeping read fence as write fence to avoid clobbering
@@ -5748,6 +5757,14 @@ status_t ACodec::LoadedState::setupInputSurface() {
}
}
+ uint32_t usageBits;
+ if (mCodec->mOMX->getParameter(
+ mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ &usageBits, sizeof(usageBits)) == OK) {
+ mCodec->mInputFormat->setInt32(
+ "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
+ }
+
return OK;
}
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 2606e44..bc34bcf 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -670,9 +670,13 @@ status_t CameraSource::start(MetaData *meta) {
mNumInputBuffers = nBuffers;
}
- // TODO: Read in format/dataspace from somewhere
- // Uncomment to test SW encoders until TODO is resolved
- // mEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+ // apply encoder color format if specified
+ if (meta->findInt32(kKeyPixelFormat, &mEncoderFormat)) {
+ ALOGV("Using encoder format: %#x", mEncoderFormat);
+ }
+ if (meta->findInt32(kKeyColorSpace, &mEncoderDataSpace)) {
+ ALOGV("Using encoder data space: %#x", mEncoderDataSpace);
+ }
}
status_t err;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b576cd9..69f44ed 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2528,7 +2528,25 @@ status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
if (err == BAD_VALUE) {
ALOGI("native window already connected. Assuming no change of surface");
- } else if (err != OK) {
+ } else if (err == OK) {
+ // Require a fresh set of buffers after each connect by using a unique generation
+ // number. Rely on the fact that max supported process id by Linux is 2^22.
+ // PID is never 0 so we don't have to worry that we use the default generation of 0.
+ // TODO: come up with a unique scheme if other producers also set the generation number.
+ static uint32_t mSurfaceGeneration = 0;
+ uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
+ surface->setGenerationNumber(generation);
+ ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
+
+ // HACK: clear any free buffers. Remove when connect will automatically do this.
+ // This is needed as the consumer may be holding onto stale frames that it can reattach
+ // to this surface after disconnect/connect, and those free frames would inherit the new
+ // generation number. Disconnecting after setting a unique generation prevents this.
+ native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+ err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+ }
+
+ if (err != OK) {
ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
}
}
@@ -2538,6 +2556,8 @@ status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
status_t MediaCodec::disconnectFromSurface() {
status_t err = OK;
if (mSurface != NULL) {
+ // Resetting generation is not technically needed, but there is no need to keep it either
+ mSurface->setGenerationNumber(0);
err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
if (err != OK) {
ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index ab49c11..7ea5cbd 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -175,6 +175,7 @@ MediaCodecList::MediaCodecList()
mUpdate(false),
mGlobalSettings(new AMessage()) {
parseTopLevelXMLFile("/etc/media_codecs.xml");
+ parseTopLevelXMLFile("/etc/media_codecs_performance.xml", true/* ignore_errors */);
parseTopLevelXMLFile(kProfilingResults, true/* ignore_errors */);
}
@@ -935,7 +936,7 @@ status_t MediaCodecList::addLimit(const char **attrs) {
if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
|| name == "blocks-per-second" || name == "complexity"
|| name == "frame-rate" || name == "quality" || name == "size"
- || name == "measured-blocks-per-second" || name == "measured-frame-rate") {
+ || name == "measured-blocks-per-second" || name.startsWith("measured-frame-rate-")) {
AString min, max;
if (msg->findString("min", &min) && msg->findString("max", &max)) {
min.append("-");
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index e089c46..7f9f824 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -39,6 +39,9 @@
namespace android {
+const int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+const int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709;
+
struct MediaCodecSource::Puller : public AHandler {
Puller(const sp<MediaSource> &source);
@@ -341,6 +344,9 @@ MediaCodecSource::MediaCodecSource(
mStarted(false),
mStopping(false),
mDoMoreWorkPending(false),
+ mSetEncoderFormat(false),
+ mEncoderFormat(0),
+ mEncoderDataSpace(0),
mGraphicBufferConsumer(consumer),
mFirstSampleTimeUs(-1ll),
mEncoderReachedEOS(false),
@@ -438,6 +444,18 @@ status_t MediaCodecSource::initEncoder() {
}
}
+ sp<AMessage> inputFormat;
+ int32_t usingSwReadOften;
+ mSetEncoderFormat = false;
+ if (mEncoder->getInputFormat(&inputFormat) == OK
+ && inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
+ && usingSwReadOften) {
+ // this is a SW encoder; signal source to allocate SW readable buffers
+ mSetEncoderFormat = true;
+ mEncoderFormat = kDefaultSwVideoEncoderFormat;
+ mEncoderDataSpace = kDefaultSwVideoEncoderDataSpace;
+ }
+
err = mEncoder->start();
if (err != OK) {
@@ -632,8 +650,17 @@ status_t MediaCodecSource::onStart(MetaData *params) {
resume(startTimeUs);
} else {
CHECK(mPuller != NULL);
+ sp<MetaData> meta = params;
+ if (mSetEncoderFormat) {
+ if (meta == NULL) {
+ meta = new MetaData;
+ }
+ meta->setInt32(kKeyPixelFormat, mEncoderFormat);
+ meta->setInt32(kKeyColorSpace, mEncoderDataSpace);
+ }
+
sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
- err = mPuller->start(params, notify);
+ err = mPuller->start(meta.get(), notify);
if (err != OK) {
return err;
}
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index b402e48..52077a7 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -558,7 +558,6 @@ void MediaSync::onFrameAvailableFromInput() {
return;
}
}
- ++mNumOutstandingBuffers;
// Acquire and detach the buffer from the input.
BufferItem bufferItem;
@@ -567,6 +566,7 @@ void MediaSync::onFrameAvailableFromInput() {
ALOGE("acquiring buffer from input failed (%d)", status);
return;
}
+ ++mNumOutstandingBuffers;
ALOGV("acquired buffer %#llx from input", (long long)bufferItem.mGraphicBuffer->getId());
@@ -608,6 +608,7 @@ void MediaSync::renderOneBufferItem_l( const BufferItem &bufferItem) {
// Attach and queue the buffer to the output.
int slot;
+ mOutput->setGenerationNumber(bufferItem.mGraphicBuffer->getGenerationNumber());
status_t status = mOutput->attachBuffer(&slot, bufferItem.mGraphicBuffer);
ALOGE_IF(status != NO_ERROR, "attaching buffer to output failed (%d)", status);
if (status == NO_ERROR) {
@@ -695,16 +696,13 @@ void MediaSync::returnBufferToInput_l(
ALOGE_IF(status != NO_ERROR, "releasing buffer to input failed (%d)", status);
}
- if (status != NO_ERROR) {
- // TODO: do we need to try to return this buffer later?
- return;
- }
-
- ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
-
// Notify any waiting onFrameAvailable calls.
--mNumOutstandingBuffers;
mReleaseCondition.signal();
+
+ if (status == NO_ERROR) {
+ ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
+ }
}
void MediaSync::onAbandoned_l(bool isInput) {
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 5396022..f743b1c 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -283,6 +283,11 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
} else {
// This is recoverable, just ignore the current frame and
// play silence instead.
+
+ // TODO: should we skip silence (and consume input data)
+ // if mIsFirst is true as we may not have a valid
+ // mConfig->samplingRate and mConfig->num_channels?
+ ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence");
memset(outHeader->pBuffer,
0,
mConfig->outputFrameSize * sizeof(int16_t));
@@ -317,8 +322,7 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
}
outHeader->nTimeStamp =
- mAnchorTimeUs
- + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate;
+ mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
if (inHeader) {
CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 31c6975..1a7dc9d 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -23,6 +23,7 @@
#include "GraphicBufferSource.h"
#include <OMX_Core.h>
+#include <OMX_IndexExt.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -110,6 +111,7 @@ GraphicBufferSource::GraphicBufferSource(
uint32_t bufferWidth,
uint32_t bufferHeight,
uint32_t bufferCount,
+ uint32_t consumerUsage,
const sp<IGraphicBufferConsumer> &consumer) :
mInitCheck(UNKNOWN_ERROR),
mNodeInstance(nodeInstance),
@@ -152,7 +154,12 @@ GraphicBufferSource::GraphicBufferSource(
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mConsumer->setConsumerName(name);
- mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
+
+ // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
+ // for backward compatibility.
+ consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+ mConsumer->setConsumerUsageBits(consumerUsage);
+
mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
if (mInitCheck != NO_ERROR) {
ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
@@ -836,13 +843,15 @@ void GraphicBufferSource::releaseBuffer(
mConsumer->detachBuffer(id);
mBufferSlot[id] = NULL;
- mConsumer->attachBuffer(&id, buffer);
- mConsumer->releaseBuffer(
- id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
+ if (mConsumer->attachBuffer(&id, buffer) == OK) {
+ mConsumer->releaseBuffer(
+ id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
+ }
} else {
mConsumer->releaseBuffer(
id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
}
+ id = -1; // invalidate id
mNumBufferAcquired--;
}
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 3f64088..2f929d9 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -55,6 +55,7 @@ public:
uint32_t bufferWidth,
uint32_t bufferHeight,
uint32_t bufferCount,
+ uint32_t consumerUsage,
const sp<IGraphicBufferConsumer> &consumer = NULL
);
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 147aae7..9f1c5d8 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -834,7 +834,8 @@ status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
}
CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
- portString(portIndex), portIndex, buffer, graphicBuffer->handle);
+ portString(portIndex), portIndex, buffer,
+ graphicBuffer == NULL ? NULL : graphicBuffer->handle);
return OK;
}
@@ -885,10 +886,18 @@ status_t OMXNodeInstance::createGraphicBufferSource(
return INVALID_OPERATION;
}
+ uint32_t usageBits;
+ oerr = OMX_GetParameter(
+ mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
+ if (oerr != OMX_ErrorNone) {
+ usageBits = 0;
+ }
+
sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this,
def.format.video.nFrameWidth,
def.format.video.nFrameHeight,
def.nBufferCountActual,
+ usageBits,
bufferConsumer);
if ((err = bufferSource->initCheck()) != OK) {
@@ -1607,7 +1616,12 @@ OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
return NULL;
}
Mutex::Autolock autoLock(mBufferIDLock);
- return mBufferIDToBufferHeader.valueFor(buffer);
+ ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
+ if (index < 0) {
+ CLOGW("findBufferHeader: buffer %u not found", buffer);
+ return NULL;
+ }
+ return mBufferIDToBufferHeader.valueAt(index);
}
OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
@@ -1615,7 +1629,12 @@ OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader)
return 0;
}
Mutex::Autolock autoLock(mBufferIDLock);
- return mBufferHeaderToBufferID.valueFor(bufferHeader);
+ ssize_t index = mBufferHeaderToBufferID.indexOfKey(bufferHeader);
+ if (index < 0) {
+ CLOGW("findBufferID: bufferHeader %p not found", bufferHeader);
+ return 0;
+ }
+ return mBufferHeaderToBufferID.valueAt(index);
}
void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
@@ -1623,8 +1642,13 @@ void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
return;
}
Mutex::Autolock autoLock(mBufferIDLock);
- mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer));
- mBufferIDToBufferHeader.removeItem(buffer);
+ ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
+ if (index < 0) {
+ CLOGW("invalidateBufferID: buffer %u not found", buffer);
+ return;
+ }
+ mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueAt(index));
+ mBufferIDToBufferHeader.removeItemsAt(index);
}
} // namespace android
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 9dd26fb..8ea7a6e 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -34,6 +34,8 @@
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBufferMapper.h>
+#include <OMX_IndexExt.h>
+
namespace android {
const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = {
@@ -293,7 +295,7 @@ OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetParameter(
OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter(
OMX_INDEXTYPE index, OMX_PTR param) {
- switch (index) {
+ switch ((int)index) {
case OMX_IndexParamVideoErrorCorrection:
{
return OMX_ErrorNotImplemented;
@@ -343,6 +345,13 @@ OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter(
return OMX_ErrorNone;
}
+ case OMX_IndexParamConsumerUsageBits:
+ {
+ OMX_U32 *usageBits = (OMX_U32 *)param;
+ *usageBits = GRALLOC_USAGE_SW_READ_OFTEN;
+ return OMX_ErrorNone;
+ }
+
default:
return SimpleSoftOMXComponent::internalGetParameter(index, param);
}
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 9248bba..f6078a2 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -481,22 +481,31 @@ void AudioFlinger::PatchPanel::clearPatchConnections(Patch *patch)
if (patch->mRecordThread != 0) {
if (patch->mPatchRecord != 0) {
patch->mRecordThread->deletePatchRecord(patch->mPatchRecord);
- patch->mPatchRecord.clear();
}
audioflinger->closeInputInternal_l(patch->mRecordThread);
- patch->mRecordThread.clear();
}
if (patch->mPlaybackThread != 0) {
if (patch->mPatchTrack != 0) {
patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack);
- patch->mPatchTrack.clear();
}
// if num sources == 2 we are reusing an existing playback thread so we do not close it
if (patch->mAudioPatch.num_sources != 2) {
audioflinger->closeOutputInternal_l(patch->mPlaybackThread);
}
+ }
+ if (patch->mRecordThread != 0) {
+ if (patch->mPatchRecord != 0) {
+ patch->mPatchRecord.clear();
+ }
+ patch->mRecordThread.clear();
+ }
+ if (patch->mPlaybackThread != 0) {
+ if (patch->mPatchTrack != 0) {
+ patch->mPatchTrack.clear();
+ }
patch->mPlaybackThread.clear();
}
+
}
/* Disconnect a patch */
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c8f9be0..d3ea9d8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -375,6 +375,7 @@ String8 devicesToString(audio_devices_t devices)
AUDIO_DEVICE_OUT_FM, "FM",
AUDIO_DEVICE_OUT_AUX_LINE, "AUX_LINE",
AUDIO_DEVICE_OUT_SPEAKER_SAFE, "SPEAKER_SAFE",
+ AUDIO_DEVICE_OUT_IP, "IP",
AUDIO_DEVICE_NONE, "NONE", // must be last
}, mappingsIn[] = {
AUDIO_DEVICE_IN_COMMUNICATION, "COMMUNICATION",
@@ -397,6 +398,7 @@ String8 devicesToString(audio_devices_t devices)
AUDIO_DEVICE_IN_SPDIF, "SPDIF",
AUDIO_DEVICE_IN_BLUETOOTH_A2DP, "BLUETOOTH_A2DP",
AUDIO_DEVICE_IN_LOOPBACK, "LOOPBACK",
+ AUDIO_DEVICE_IN_IP, "IP",
AUDIO_DEVICE_NONE, "NONE", // must be last
};
String8 result;
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index a39006e..78d2cdf 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -73,6 +73,7 @@ const StringToEnum sDeviceTypeToEnumTable[] = {
STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF),
STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM),
STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_IP),
STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT),
STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -94,6 +95,7 @@ const StringToEnum sDeviceTypeToEnumTable[] = {
STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF),
STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_IP),
};
const StringToEnum sDeviceNameToEnumTable[] = {
@@ -124,6 +126,7 @@ const StringToEnum sDeviceNameToEnumTable[] = {
NAME_TO_ENUM("S/PDIF Out", AUDIO_DEVICE_OUT_SPDIF),
NAME_TO_ENUM("FM transceiver Out", AUDIO_DEVICE_OUT_FM),
NAME_TO_ENUM("Aux Line Out", AUDIO_DEVICE_OUT_AUX_LINE),
+ NAME_TO_ENUM("IP Out", AUDIO_DEVICE_OUT_IP),
NAME_TO_ENUM("Ambient Mic", AUDIO_DEVICE_IN_AMBIENT),
NAME_TO_ENUM("Built-In Mic", AUDIO_DEVICE_IN_BUILTIN_MIC),
NAME_TO_ENUM("BT SCO Headset Mic", AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -145,6 +148,7 @@ const StringToEnum sDeviceNameToEnumTable[] = {
NAME_TO_ENUM("S/PDIF In", AUDIO_DEVICE_IN_SPDIF),
NAME_TO_ENUM("BT A2DP In", AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
NAME_TO_ENUM("Loopback In", AUDIO_DEVICE_IN_LOOPBACK),
+ NAME_TO_ENUM("IP In", AUDIO_DEVICE_IN_IP),
};
const StringToEnum sOutputFlagNameToEnumTable[] = {
@@ -156,11 +160,15 @@ const StringToEnum sOutputFlagNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TTS),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
};
const StringToEnum sInputFlagNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_RAW),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_SYNC),
};
const StringToEnum sFormatNameToEnumTable[] = {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ee25b71..6983b5c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -427,7 +427,7 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
/// Opens: can these line be executed after the switch of volume curves???
// if leaving call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
- if (isInCall()) {
+ if (isStateInCall(oldState)) {
ALOGV("setPhoneState() in call state management: new state is %d", state);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
if (stream == AUDIO_STREAM_PATCH) {
@@ -436,7 +436,7 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
handleIncallSonification((audio_stream_type_t)stream, false, true);
}
- // force reevaluating accessibility routing when call starts
+ // force reevaluating accessibility routing when call stops
mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
}
@@ -514,6 +514,9 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
}
handleIncallSonification((audio_stream_type_t)stream, true, true);
}
+
+ // force reevaluating accessibility routing when call starts
+ mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
}
// Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index fbe4f18..eefff3d 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -930,6 +930,7 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& c
patch2 = ((CreateAudioPatchData *)command2->mParam.get())->mPatch;
} else {
handle2 = ((ReleaseAudioPatchData *)command2->mParam.get())->mHandle;
+ memset(&patch2, 0, sizeof(patch2));
}
if (handle != handle2) break;
/* Filter CREATE_AUDIO_PATCH commands only when they are issued for
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f42fada..92df4e3 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1292,7 +1292,7 @@ void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size
status_t CameraService::addListener(const sp<ICameraServiceListener>& listener) {
ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
- if (listener == 0) {
+ if (listener == nullptr) {
ALOGE("%s: Listener must not be null", __FUNCTION__);
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
index 85d4488..1ae01ae 100644
--- a/services/camera/libcameraservice/common/CameraModule.cpp
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -154,6 +154,18 @@ CameraModule::CameraModule(camera_module_t *module) {
mCameraInfoMap.setCapacity(getNumberOfCameras());
}
+CameraModule::~CameraModule()
+{
+ while (mCameraInfoMap.size() > 0) {
+ camera_info cameraInfo = mCameraInfoMap.editValueAt(0);
+ if (cameraInfo.static_camera_characteristics != NULL) {
+ free_camera_metadata(
+ const_cast<camera_metadata_t*>(cameraInfo.static_camera_characteristics));
+ }
+ mCameraInfoMap.removeItemsAt(0);
+ }
+}
+
int CameraModule::init() {
if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
mModule->init != NULL) {
@@ -192,12 +204,9 @@ int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
CameraMetadata m;
m = rawInfo.static_camera_characteristics;
deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
- mCameraCharacteristicsMap.add(cameraId, m);
cameraInfo = rawInfo;
- cameraInfo.static_camera_characteristics =
- mCameraCharacteristicsMap.valueFor(cameraId).getAndLock();
- mCameraInfoMap.add(cameraId, cameraInfo);
- index = mCameraInfoMap.indexOfKey(cameraId);
+ cameraInfo.static_camera_characteristics = m.release();
+ index = mCameraInfoMap.add(cameraId, cameraInfo);
}
assert(index != NAME_NOT_FOUND);
diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h
index c21092e..36822c7 100644
--- a/services/camera/libcameraservice/common/CameraModule.h
+++ b/services/camera/libcameraservice/common/CameraModule.h
@@ -33,6 +33,7 @@ namespace android {
class CameraModule {
public:
CameraModule(camera_module_t *module);
+ virtual ~CameraModule();
// Must be called after construction
// Returns OK on success, NO_INIT on failure
@@ -60,7 +61,6 @@ private:
camera_module_t *mModule;
KeyedVector<int, camera_info> mCameraInfoMap;
- KeyedVector<int, CameraMetadata> mCameraCharacteristicsMap;
Mutex mCameraInfoLock;
};
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4b55dad..9e73b5c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -164,9 +164,17 @@ status_t Camera3Device::initialize(CameraModule *module)
return res;
}
- /** Start up request queue thread */
+ bool aeLockAvailable = false;
+ camera_metadata_ro_entry aeLockAvailableEntry;
+ res = find_camera_metadata_ro_entry(info.static_camera_characteristics,
+ ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailableEntry);
+ if (res == OK && aeLockAvailableEntry.count > 0) {
+ aeLockAvailable = (aeLockAvailableEntry.data.u8[0] ==
+ ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
+ }
- mRequestThread = new RequestThread(this, mStatusTracker, device);
+ /** Start up request queue thread */
+ mRequestThread = new RequestThread(this, mStatusTracker, device, aeLockAvailable);
res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string());
if (res != OK) {
SET_ERR_L("Unable to start request queue thread: %s (%d)",
@@ -2472,7 +2480,8 @@ CameraMetadata Camera3Device::getLatestRequestLocked() {
Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
sp<StatusTracker> statusTracker,
- camera3_device_t *hal3Device) :
+ camera3_device_t *hal3Device,
+ bool aeLockAvailable) :
Thread(/*canCallJava*/false),
mParent(parent),
mStatusTracker(statusTracker),
@@ -2485,19 +2494,9 @@ Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
mLatestRequestId(NAME_NOT_FOUND),
mCurrentAfTriggerId(0),
mCurrentPreCaptureTriggerId(0),
- mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) {
+ mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES),
+ mAeLockAvailable(aeLockAvailable) {
mStatusId = statusTracker->addComponent();
-
- mAeLockAvailable = false;
- sp<Camera3Device> p = parent.promote();
- if (p != NULL) {
- camera_metadata_ro_entry aeLockAvailable =
- p->info().find(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
- if (aeLockAvailable.count > 0) {
- mAeLockAvailable = (aeLockAvailable.data.u8[0] ==
- ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
- }
- }
}
void Camera3Device::RequestThread::setNotificationListener(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index bb4bcc4..31b6132 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -389,7 +389,8 @@ class Camera3Device :
RequestThread(wp<Camera3Device> parent,
sp<camera3::StatusTracker> statusTracker,
- camera3_device_t *hal3Device);
+ camera3_device_t *hal3Device,
+ bool aeLockAvailable);
void setNotificationListener(NotificationListener *listener);