summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/Android.mk3
-rw-r--r--camera/CameraBase.cpp2
-rw-r--r--camera/ICameraService.cpp60
-rw-r--r--camera/IProCameraCallbacks.cpp125
-rw-r--r--camera/IProCameraUser.cpp324
-rw-r--r--camera/ProCamera.cpp436
-rw-r--r--camera/tests/Android.mk1
-rw-r--r--camera/tests/ProCameraTests.cpp1284
-rw-r--r--include/camera/ICameraService.h10
-rw-r--r--include/camera/IProCameraCallbacks.h71
-rw-r--r--include/camera/IProCameraUser.h100
-rw-r--r--include/camera/ProCamera.h319
-rw-r--r--include/media/stagefright/ACodec.h2
-rw-r--r--include/media/stagefright/OMXCodec.h2
-rw-r--r--media/libstagefright/ACodec.cpp10
-rw-r--r--media/libstagefright/OMXCodec.cpp10
-rw-r--r--media/libstagefright/codecs/g711/dec/SoftG711.cpp7
-rw-r--r--media/libstagefright/codecs/g711/dec/SoftG711.h3
-rw-r--r--media/libstagefright/data/media_codecs_google_audio.xml4
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp412
-rw-r--r--media/libstagefright/httplive/LiveSession.h44
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.cpp354
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.h30
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.h3
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.cpp16
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.h4
-rw-r--r--services/camera/libcameraservice/Android.mk1
-rw-r--r--services/camera/libcameraservice/CameraService.cpp39
-rw-r--r--services/camera/libcameraservice/CameraService.h54
-rw-r--r--services/camera/libcameraservice/api2/CameraDeviceClient.cpp3
-rw-r--r--services/camera/libcameraservice/api_pro/ProCamera2Client.cpp445
-rw-r--r--services/camera/libcameraservice/api_pro/ProCamera2Client.h124
-rw-r--r--services/camera/libcameraservice/common/Camera2ClientBase.cpp1
-rw-r--r--services/camera/libcameraservice/common/Camera2ClientBase.h2
34 files changed, 621 insertions, 3684 deletions
diff --git a/camera/Android.mk b/camera/Android.mk
index df7279f..4c4700b 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -30,13 +30,10 @@ LOCAL_SRC_FILES:= \
ICameraServiceListener.cpp \
ICameraRecordingProxy.cpp \
ICameraRecordingProxyListener.cpp \
- IProCameraUser.cpp \
- IProCameraCallbacks.cpp \
camera2/ICameraDeviceUser.cpp \
camera2/ICameraDeviceCallbacks.cpp \
camera2/CaptureRequest.cpp \
camera2/OutputConfiguration.cpp \
- ProCamera.cpp \
CameraBase.cpp \
CameraUtils.cpp \
VendorTagDescriptor.cpp
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 65a1a47..5d50aa8 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -29,7 +29,6 @@
#include <camera/ICameraService.h>
// needed to instantiate
-#include <camera/ProCamera.h>
#include <camera/Camera.h>
#include <system/camera_metadata.h>
@@ -217,7 +216,6 @@ status_t CameraBase<TCam, TCamTraits>::removeServiceListener(
return cs->removeListener(listener);
}
-template class CameraBase<ProCamera>;
template class CameraBase<Camera>;
} // namespace android
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index a75cb48..63c82cc 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -2,16 +2,16 @@
**
** Copyright 2008, 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
+** 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
+** 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
+** 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.
*/
@@ -29,8 +29,6 @@
#include <camera/ICameraService.h>
#include <camera/ICameraServiceListener.h>
-#include <camera/IProCameraUser.h>
-#include <camera/IProCameraCallbacks.h>
#include <camera/ICamera.h>
#include <camera/ICameraClient.h>
#include <camera/camera2/ICameraDeviceUser.h>
@@ -223,28 +221,6 @@ public:
return reply.readInt32();
}
- // connect to camera service (pro client)
- virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb, int cameraId,
- const String16 &clientPackageName, int clientUid,
- /*out*/
- sp<IProCameraUser>& device)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(cameraCb));
- data.writeInt32(cameraId);
- data.writeString16(clientPackageName);
- data.writeInt32(clientUid);
- remote()->transact(BnCameraService::CONNECT_PRO, data, &reply);
-
- if (readExceptionCode(reply)) return -EPROTO;
- status_t status = reply.readInt32();
- if (reply.readInt32() != 0) {
- device = interface_cast<IProCameraUser>(reply.readStrongBinder());
- }
- return status;
- }
-
// connect to camera service (android.hardware.camera2.CameraDevice)
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
@@ -404,26 +380,6 @@ status_t BnCameraService::onTransact(
}
return NO_ERROR;
} break;
- case CONNECT_PRO: {
- CHECK_INTERFACE(ICameraService, data, reply);
- sp<IProCameraCallbacks> cameraClient =
- interface_cast<IProCameraCallbacks>(data.readStrongBinder());
- int32_t cameraId = data.readInt32();
- const String16 clientName = data.readString16();
- int32_t clientUid = data.readInt32();
- sp<IProCameraUser> camera;
- status_t status = connectPro(cameraClient, cameraId,
- clientName, clientUid, /*out*/camera);
- reply->writeNoException();
- reply->writeInt32(status);
- if (camera != NULL) {
- reply->writeInt32(1);
- reply->writeStrongBinder(IInterface::asBinder(camera));
- } else {
- reply->writeInt32(0);
- }
- return NO_ERROR;
- } break;
case CONNECT_DEVICE: {
CHECK_INTERFACE(ICameraService, data, reply);
sp<ICameraDeviceCallbacks> cameraClient =
diff --git a/camera/IProCameraCallbacks.cpp b/camera/IProCameraCallbacks.cpp
deleted file mode 100644
index bd3d420..0000000
--- a/camera/IProCameraCallbacks.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-**
-** Copyright 2013, 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 "IProCameraCallbacks"
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/Surface.h>
-#include <utils/Mutex.h>
-
-#include <camera/IProCameraCallbacks.h>
-
-#include "camera/CameraMetadata.h"
-
-namespace android {
-
-enum {
- NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
- LOCK_STATUS_CHANGED,
- RESULT_RECEIVED,
-};
-
-class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks>
-{
-public:
- BpProCameraCallbacks(const sp<IBinder>& impl)
- : BpInterface<IProCameraCallbacks>(impl)
- {
- }
-
- // generic callback from camera service to app
- void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
- {
- ALOGV("notifyCallback");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt32(msgType);
- data.writeInt32(ext1);
- data.writeInt32(ext2);
- remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- void onLockStatusChanged(LockStatus newLockStatus) {
- ALOGV("onLockStatusChanged");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt32(newLockStatus);
- remote()->transact(LOCK_STATUS_CHANGED, data, &reply,
- IBinder::FLAG_ONEWAY);
- }
-
- void onResultReceived(int32_t requestId, camera_metadata* result) {
- ALOGV("onResultReceived");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt32(requestId);
- CameraMetadata::writeToParcel(data, result);
- remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(ProCameraCallbacks,
- "android.hardware.IProCameraCallbacks");
-
-// ----------------------------------------------------------------------
-
-status_t BnProCameraCallbacks::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- ALOGV("onTransact - code = %d", code);
- switch(code) {
- case NOTIFY_CALLBACK: {
- ALOGV("NOTIFY_CALLBACK");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- int32_t msgType = data.readInt32();
- int32_t ext1 = data.readInt32();
- int32_t ext2 = data.readInt32();
- notifyCallback(msgType, ext1, ext2);
- return NO_ERROR;
- } break;
- case LOCK_STATUS_CHANGED: {
- ALOGV("LOCK_STATUS_CHANGED");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- LockStatus newLockStatus
- = static_cast<LockStatus>(data.readInt32());
- onLockStatusChanged(newLockStatus);
- return NO_ERROR;
- } break;
- case RESULT_RECEIVED: {
- ALOGV("RESULT_RECEIVED");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- int32_t requestId = data.readInt32();
- camera_metadata_t *result = NULL;
- CameraMetadata::readFromParcel(data, &result);
- onResultReceived(requestId, result);
- return NO_ERROR;
- break;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
diff --git a/camera/IProCameraUser.cpp b/camera/IProCameraUser.cpp
deleted file mode 100644
index 9bd7597..0000000
--- a/camera/IProCameraUser.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-**
-** Copyright 2013, 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 "IProCameraUser"
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <camera/IProCameraUser.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/Surface.h>
-#include "camera/CameraMetadata.h"
-
-namespace android {
-
-enum {
- DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
- CONNECT,
- EXCLUSIVE_TRY_LOCK,
- EXCLUSIVE_LOCK,
- EXCLUSIVE_UNLOCK,
- HAS_EXCLUSIVE_LOCK,
- SUBMIT_REQUEST,
- CANCEL_REQUEST,
- DELETE_STREAM,
- CREATE_STREAM,
- CREATE_DEFAULT_REQUEST,
- GET_CAMERA_INFO,
-};
-
-class BpProCameraUser: public BpInterface<IProCameraUser>
-{
-public:
- BpProCameraUser(const sp<IBinder>& impl)
- : BpInterface<IProCameraUser>(impl)
- {
- }
-
- // disconnect from camera service
- void disconnect()
- {
- ALOGV("disconnect");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(DISCONNECT, data, &reply);
- reply.readExceptionCode();
- }
-
- virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(cameraClient));
- remote()->transact(CONNECT, data, &reply);
- return reply.readInt32();
- }
-
- /* Shared ProCameraUser */
-
- virtual status_t exclusiveTryLock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
- return reply.readInt32();
- }
- virtual status_t exclusiveLock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(EXCLUSIVE_LOCK, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t exclusiveUnlock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
- return reply.readInt32();
- }
-
- virtual bool hasExclusiveLock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
- return !!reply.readInt32();
- }
-
- virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
- {
-
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
-
- // arg0+arg1
- CameraMetadata::writeToParcel(data, metadata);
-
- // arg2 = streaming (bool)
- data.writeInt32(streaming);
-
- remote()->transact(SUBMIT_REQUEST, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t cancelRequest(int requestId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(requestId);
-
- remote()->transact(CANCEL_REQUEST, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t deleteStream(int streamId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(streamId);
-
- remote()->transact(DELETE_STREAM, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(width);
- data.writeInt32(height);
- data.writeInt32(format);
-
- sp<IBinder> b(IInterface::asBinder(bufferProducer));
- data.writeStrongBinder(b);
-
- remote()->transact(CREATE_STREAM, data, &reply);
-
- int sId = reply.readInt32();
- if (streamId) {
- *streamId = sId;
- }
- return reply.readInt32();
- }
-
- // Create a request object from a template.
- virtual status_t createDefaultRequest(int templateId,
- /*out*/
- camera_metadata** request)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(templateId);
- remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
- CameraMetadata::readFromParcel(reply, /*out*/request);
- return reply.readInt32();
- }
-
-
- virtual status_t getCameraInfo(int cameraId, camera_metadata** info)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(cameraId);
- remote()->transact(GET_CAMERA_INFO, data, &reply);
- CameraMetadata::readFromParcel(reply, /*out*/info);
- return reply.readInt32();
- }
-
-
-private:
-
-
-};
-
-IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
-
-// ----------------------------------------------------------------------
-
-status_t BnProCameraUser::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case DISCONNECT: {
- ALOGV("DISCONNECT");
- CHECK_INTERFACE(IProCameraUser, data, reply);
- disconnect();
- reply->writeNoException();
- return NO_ERROR;
- } break;
- case CONNECT: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- sp<IProCameraCallbacks> cameraClient =
- interface_cast<IProCameraCallbacks>(data.readStrongBinder());
- reply->writeInt32(connect(cameraClient));
- return NO_ERROR;
- } break;
-
- /* Shared ProCameraUser */
- case EXCLUSIVE_TRY_LOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(exclusiveTryLock());
- return NO_ERROR;
- } break;
- case EXCLUSIVE_LOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(exclusiveLock());
- return NO_ERROR;
- } break;
- case EXCLUSIVE_UNLOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(exclusiveUnlock());
- return NO_ERROR;
- } break;
- case HAS_EXCLUSIVE_LOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(hasExclusiveLock());
- return NO_ERROR;
- } break;
- case SUBMIT_REQUEST: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- camera_metadata_t* metadata;
- CameraMetadata::readFromParcel(data, /*out*/&metadata);
-
- // arg2 = streaming (bool)
- bool streaming = data.readInt32();
-
- // return code: requestId (int32)
- reply->writeInt32(submitRequest(metadata, streaming));
-
- return NO_ERROR;
- } break;
- case CANCEL_REQUEST: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- int requestId = data.readInt32();
- reply->writeInt32(cancelRequest(requestId));
- return NO_ERROR;
- } break;
- case DELETE_STREAM: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- int streamId = data.readInt32();
- reply->writeInt32(deleteStream(streamId));
- return NO_ERROR;
- } break;
- case CREATE_STREAM: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- int width, height, format;
-
- width = data.readInt32();
- height = data.readInt32();
- format = data.readInt32();
-
- sp<IGraphicBufferProducer> bp =
- interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
-
- int streamId = -1;
- status_t ret;
- ret = createStream(width, height, format, bp, &streamId);
-
- reply->writeInt32(streamId);
- reply->writeInt32(ret);
-
- return NO_ERROR;
- } break;
-
- case CREATE_DEFAULT_REQUEST: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
-
- int templateId = data.readInt32();
-
- camera_metadata_t* request = NULL;
- status_t ret;
- ret = createDefaultRequest(templateId, &request);
-
- CameraMetadata::writeToParcel(*reply, request);
- reply->writeInt32(ret);
-
- free_camera_metadata(request);
-
- return NO_ERROR;
- } break;
- case GET_CAMERA_INFO: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
-
- int cameraId = data.readInt32();
-
- camera_metadata_t* info = NULL;
- status_t ret;
- ret = getCameraInfo(cameraId, &info);
-
- CameraMetadata::writeToParcel(*reply, info);
- reply->writeInt32(ret);
-
- free_camera_metadata(info);
-
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp
deleted file mode 100644
index 48f8e8e..0000000
--- a/camera/ProCamera.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
-**
-** Copyright (C) 2013, 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 "ProCamera"
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <utils/Mutex.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/IMemory.h>
-
-#include <camera/ProCamera.h>
-#include <camera/IProCameraUser.h>
-#include <camera/IProCameraCallbacks.h>
-
-#include <gui/IGraphicBufferProducer.h>
-
-#include <system/camera_metadata.h>
-
-namespace android {
-
-sp<ProCamera> ProCamera::connect(int cameraId)
-{
- return CameraBaseT::connect(cameraId, String16(),
- ICameraService::USE_CALLING_UID);
-}
-
-ProCamera::ProCamera(int cameraId)
- : CameraBase(cameraId)
-{
-}
-
-CameraTraits<ProCamera>::TCamConnectService CameraTraits<ProCamera>::fnConnectService =
- &ICameraService::connectPro;
-
-ProCamera::~ProCamera()
-{
-
-}
-
-/* IProCameraUser's implementation */
-
-// callback from camera service
-void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
-{
- return CameraBaseT::notifyCallback(msgType, ext1, ext2);
-}
-
-void ProCamera::onLockStatusChanged(
- IProCameraCallbacks::LockStatus newLockStatus)
-{
- ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
-
- sp<ProCameraListener> listener;
- {
- Mutex::Autolock _l(mLock);
- listener = mListener;
- }
- if (listener != NULL) {
- switch (newLockStatus) {
- case IProCameraCallbacks::LOCK_ACQUIRED:
- listener->onLockAcquired();
- break;
- case IProCameraCallbacks::LOCK_RELEASED:
- listener->onLockReleased();
- break;
- case IProCameraCallbacks::LOCK_STOLEN:
- listener->onLockStolen();
- break;
- default:
- ALOGE("%s: Unknown lock status: %d",
- __FUNCTION__, newLockStatus);
- }
- }
-}
-
-void ProCamera::onResultReceived(int32_t requestId, camera_metadata* result) {
- ALOGV("%s: requestId = %d, result = %p", __FUNCTION__, requestId, result);
-
- sp<ProCameraListener> listener;
- {
- Mutex::Autolock _l(mLock);
- listener = mListener;
- }
-
- CameraMetadata tmp(result);
-
- // Unblock waitForFrame(id) callers
- {
- Mutex::Autolock al(mWaitMutex);
- mMetadataReady = true;
- mLatestMetadata = tmp; // make copy
- mWaitCondition.broadcast();
- }
-
- result = tmp.release();
-
- if (listener != NULL) {
- listener->onResultReceived(requestId, result);
- } else {
- free_camera_metadata(result);
- }
-
-}
-
-status_t ProCamera::exclusiveTryLock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->exclusiveTryLock();
-}
-status_t ProCamera::exclusiveLock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->exclusiveLock();
-}
-status_t ProCamera::exclusiveUnlock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->exclusiveUnlock();
-}
-bool ProCamera::hasExclusiveLock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->hasExclusiveLock();
-}
-
-// Note that the callee gets a copy of the metadata.
-int ProCamera::submitRequest(const struct camera_metadata* metadata,
- bool streaming)
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
- streaming);
-}
-
-status_t ProCamera::cancelRequest(int requestId)
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->cancelRequest(requestId);
-}
-
-status_t ProCamera::deleteStream(int streamId)
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- status_t s = c->deleteStream(streamId);
-
- mStreams.removeItem(streamId);
-
- return s;
-}
-
-status_t ProCamera::createStream(int width, int height, int format,
- const sp<Surface>& surface,
- /*out*/
- int* streamId)
-{
- *streamId = -1;
-
- ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
- format);
-
- if (surface == 0) {
- return BAD_VALUE;
- }
-
- return createStream(width, height, format,
- surface->getIGraphicBufferProducer(),
- streamId);
-}
-
-status_t ProCamera::createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId) {
- *streamId = -1;
-
- ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
- format);
-
- if (bufferProducer == 0) {
- return BAD_VALUE;
- }
-
- sp <IProCameraUser> c = mCamera;
- status_t stat = c->createStream(width, height, format, bufferProducer,
- streamId);
-
- if (stat == OK) {
- StreamInfo s(*streamId);
-
- mStreams.add(*streamId, s);
- }
-
- return stat;
-}
-
-status_t ProCamera::createStreamCpu(int width, int height, int format,
- int heapCount,
- /*out*/
- sp<CpuConsumer>* cpuConsumer,
- int* streamId) {
- return createStreamCpu(width, height, format, heapCount,
- /*synchronousMode*/true,
- cpuConsumer, streamId);
-}
-
-status_t ProCamera::createStreamCpu(int width, int height, int format,
- int heapCount,
- bool synchronousMode,
- /*out*/
- sp<CpuConsumer>* cpuConsumer,
- int* streamId)
-{
- ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
- format);
-
- *cpuConsumer = NULL;
-
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- sp<CpuConsumer> cc = new CpuConsumer(consumer, heapCount
- /*, synchronousMode*/);
- cc->setName(String8("ProCamera::mCpuConsumer"));
-
- sp<Surface> stc = new Surface(producer);
-
- status_t s = createStream(width, height, format,
- stc->getIGraphicBufferProducer(),
- streamId);
-
- if (s != OK) {
- ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
- width, height, format);
- return s;
- }
-
- sp<ProFrameListener> frameAvailableListener =
- new ProFrameListener(this, *streamId);
-
- getStreamInfo(*streamId).cpuStream = true;
- getStreamInfo(*streamId).cpuConsumer = cc;
- getStreamInfo(*streamId).synchronousMode = synchronousMode;
- getStreamInfo(*streamId).stc = stc;
- // for lifetime management
- getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
-
- cc->setFrameAvailableListener(frameAvailableListener);
-
- *cpuConsumer = cc;
-
- return s;
-}
-
-camera_metadata* ProCamera::getCameraInfo(int cameraId) {
- ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
-
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NULL;
-
- camera_metadata* ptr = NULL;
- status_t status = c->getCameraInfo(cameraId, &ptr);
-
- if (status != OK) {
- ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
- }
-
- return ptr;
-}
-
-status_t ProCamera::createDefaultRequest(int templateId,
- camera_metadata** request) const {
- ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
-
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->createDefaultRequest(templateId, request);
-}
-
-void ProCamera::onFrameAvailable(int streamId) {
- ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
-
- sp<ProCameraListener> listener = mListener;
- StreamInfo& stream = getStreamInfo(streamId);
-
- if (listener.get() != NULL) {
- listener->onFrameAvailable(streamId, stream.cpuConsumer);
- }
-
- // Unblock waitForFrame(id) callers
- {
- Mutex::Autolock al(mWaitMutex);
- getStreamInfo(streamId).frameReady++;
- mWaitCondition.broadcast();
- }
-}
-
-int ProCamera::waitForFrameBuffer(int streamId) {
- status_t stat = BAD_VALUE;
- Mutex::Autolock al(mWaitMutex);
-
- StreamInfo& si = getStreamInfo(streamId);
-
- if (si.frameReady > 0) {
- int numFrames = si.frameReady;
- si.frameReady = 0;
- return numFrames;
- } else {
- while (true) {
- stat = mWaitCondition.waitRelative(mWaitMutex,
- mWaitTimeout);
- if (stat != OK) {
- ALOGE("%s: Error while waiting for frame buffer: %d",
- __FUNCTION__, stat);
- return stat;
- }
-
- if (si.frameReady > 0) {
- int numFrames = si.frameReady;
- si.frameReady = 0;
- return numFrames;
- }
- // else it was some other stream that got unblocked
- }
- }
-
- return stat;
-}
-
-int ProCamera::dropFrameBuffer(int streamId, int count) {
- StreamInfo& si = getStreamInfo(streamId);
-
- if (!si.cpuStream) {
- return BAD_VALUE;
- } else if (count < 0) {
- return BAD_VALUE;
- }
-
- if (!si.synchronousMode) {
- ALOGW("%s: No need to drop frames on asynchronous streams,"
- " as asynchronous mode only keeps 1 latest frame around.",
- __FUNCTION__);
- return BAD_VALUE;
- }
-
- int numDropped = 0;
- for (int i = 0; i < count; ++i) {
- CpuConsumer::LockedBuffer buffer;
- if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
- break;
- }
-
- si.cpuConsumer->unlockBuffer(buffer);
- numDropped++;
- }
-
- return numDropped;
-}
-
-status_t ProCamera::waitForFrameMetadata() {
- status_t stat = BAD_VALUE;
- Mutex::Autolock al(mWaitMutex);
-
- if (mMetadataReady) {
- return OK;
- } else {
- while (true) {
- stat = mWaitCondition.waitRelative(mWaitMutex,
- mWaitTimeout);
-
- if (stat != OK) {
- ALOGE("%s: Error while waiting for metadata: %d",
- __FUNCTION__, stat);
- return stat;
- }
-
- if (mMetadataReady) {
- mMetadataReady = false;
- return OK;
- }
- // else it was some other stream or metadata
- }
- }
-
- return stat;
-}
-
-CameraMetadata ProCamera::consumeFrameMetadata() {
- Mutex::Autolock al(mWaitMutex);
-
- // Destructive: Subsequent calls return empty metadatas
- CameraMetadata tmp = mLatestMetadata;
- mLatestMetadata.clear();
-
- return tmp;
-}
-
-ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
- return mStreams.editValueFor(streamId);
-}
-
-}; // namespace android
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index 2db4c14..5d37f9e 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -17,7 +17,6 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SRC_FILES:= \
- ProCameraTests.cpp \
VendorTagDescriptorTests.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
deleted file mode 100644
index 24b2327..0000000
--- a/camera/tests/ProCameraTests.cpp
+++ /dev/null
@@ -1,1284 +0,0 @@
-/*
- * Copyright (C) 2013 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 <gtest/gtest.h>
-#include <iostream>
-
-#include <binder/IPCThreadState.h>
-#include <utils/Thread.h>
-
-#include "Camera.h"
-#include "ProCamera.h"
-#include <utils/Vector.h>
-#include <utils/Mutex.h>
-#include <utils/Condition.h>
-
-#include <gui/SurfaceComposerClient.h>
-#include <gui/Surface.h>
-
-#include <system/camera_metadata.h>
-#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only
-#include <camera/CameraMetadata.h>
-
-#include <camera/ICameraServiceListener.h>
-
-namespace android {
-namespace camera2 {
-namespace tests {
-namespace client {
-
-#define CAMERA_ID 0
-#define TEST_DEBUGGING 0
-
-#define TEST_LISTENER_TIMEOUT 1000000000 // 1 second listener timeout
-#define TEST_FORMAT HAL_PIXEL_FORMAT_Y16 //TODO: YUY2 instead
-
-#define TEST_FORMAT_MAIN HAL_PIXEL_FORMAT_Y8
-#define TEST_FORMAT_DEPTH HAL_PIXEL_FORMAT_Y16
-
-// defaults for display "test"
-#define TEST_DISPLAY_FORMAT HAL_PIXEL_FORMAT_Y8
-#define TEST_DISPLAY_WIDTH 320
-#define TEST_DISPLAY_HEIGHT 240
-
-#define TEST_CPU_FRAME_COUNT 2
-#define TEST_CPU_HEAP_COUNT 5
-
-#define TEST_FRAME_PROCESSING_DELAY_US 200000 // 200 ms
-
-#if TEST_DEBUGGING
-#define dout std::cerr
-#else
-#define dout if (0) std::cerr
-#endif
-
-#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
-#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
-
-class ProCameraTest;
-
-struct ServiceListener : public BnCameraServiceListener {
-
- ServiceListener() :
- mLatestStatus(STATUS_UNKNOWN),
- mPrevStatus(STATUS_UNKNOWN)
- {
- }
-
- void onStatusChanged(Status status, int32_t cameraId) {
- dout << "On status changed: 0x" << std::hex
- << (unsigned int) status << " cameraId " << cameraId
- << std::endl;
-
- Mutex::Autolock al(mMutex);
-
- mLatestStatus = status;
- mCondition.broadcast();
- }
-
- void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
- dout << "On torch status changed: 0x" << std::hex
- << (unsigned int) status << " cameraId " << cameraId.string()
- << std::endl;
- }
-
- status_t waitForStatusChange(Status& newStatus) {
- Mutex::Autolock al(mMutex);
-
- if (mLatestStatus != mPrevStatus) {
- newStatus = mLatestStatus;
- mPrevStatus = mLatestStatus;
- return OK;
- }
-
- status_t stat = mCondition.waitRelative(mMutex,
- TEST_LISTENER_TIMEOUT);
-
- if (stat == OK) {
- newStatus = mLatestStatus;
- mPrevStatus = mLatestStatus;
- }
-
- return stat;
- }
-
- Condition mCondition;
- Mutex mMutex;
-
- Status mLatestStatus;
- Status mPrevStatus;
-};
-
-enum ProEvent {
- UNKNOWN,
- ACQUIRED,
- RELEASED,
- STOLEN,
- FRAME_RECEIVED,
- RESULT_RECEIVED,
-};
-
-inline int ProEvent_Mask(ProEvent e) {
- return (1 << static_cast<int>(e));
-}
-
-typedef Vector<ProEvent> EventList;
-
-class ProCameraTestThread : public Thread
-{
-public:
- ProCameraTestThread() {
- }
-
- virtual bool threadLoop() {
- mProc = ProcessState::self();
- mProc->startThreadPool();
-
- IPCThreadState *ptr = IPCThreadState::self();
-
- ptr->joinThreadPool();
-
- return false;
- }
-
- sp<ProcessState> mProc;
-};
-
-class ProCameraTestListener : public ProCameraListener {
-
-public:
- static const int EVENT_MASK_ALL = 0xFFFFFFFF;
-
- ProCameraTestListener() {
- mEventMask = EVENT_MASK_ALL;
- mDropFrames = false;
- }
-
- status_t WaitForEvent() {
- Mutex::Autolock cal(mConditionMutex);
-
- {
- Mutex::Autolock al(mListenerMutex);
-
- if (mProEventList.size() > 0) {
- return OK;
- }
- }
-
- return mListenerCondition.waitRelative(mConditionMutex,
- TEST_LISTENER_TIMEOUT);
- }
-
- /* Read events into out. Existing queue is flushed */
- void ReadEvents(EventList& out) {
- Mutex::Autolock al(mListenerMutex);
-
- for (size_t i = 0; i < mProEventList.size(); ++i) {
- out.push(mProEventList[i]);
- }
-
- mProEventList.clear();
- }
-
- /**
- * Dequeue 1 event from the event queue.
- * Returns UNKNOWN if queue is empty
- */
- ProEvent ReadEvent() {
- Mutex::Autolock al(mListenerMutex);
-
- if (mProEventList.size() == 0) {
- return UNKNOWN;
- }
-
- ProEvent ev = mProEventList[0];
- mProEventList.removeAt(0);
-
- return ev;
- }
-
- void SetEventMask(int eventMask) {
- Mutex::Autolock al(mListenerMutex);
- mEventMask = eventMask;
- }
-
- // Automatically acquire/release frames as they are available
- void SetDropFrames(bool dropFrames) {
- Mutex::Autolock al(mListenerMutex);
- mDropFrames = dropFrames;
- }
-
-private:
- void QueueEvent(ProEvent ev) {
- bool eventAdded = false;
- {
- Mutex::Autolock al(mListenerMutex);
-
- // Drop events not part of mask
- if (ProEvent_Mask(ev) & mEventMask) {
- mProEventList.push(ev);
- eventAdded = true;
- }
- }
-
- if (eventAdded) {
- mListenerCondition.broadcast();
- }
- }
-
-protected:
-
- //////////////////////////////////////////////////
- ///////// ProCameraListener //////////////////////
- //////////////////////////////////////////////////
-
-
- // Lock has been acquired. Write operations now available.
- virtual void onLockAcquired() {
- QueueEvent(ACQUIRED);
- }
- // Lock has been released with exclusiveUnlock
- virtual void onLockReleased() {
- QueueEvent(RELEASED);
- }
-
- // Lock has been stolen by another client.
- virtual void onLockStolen() {
- QueueEvent(STOLEN);
- }
-
- // Lock free.
- virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) {
-
- dout << "Trigger notify: " << ext1 << " " << ext2
- << " " << ext3 << std::endl;
- }
-
- virtual void onFrameAvailable(int streamId,
- const sp<CpuConsumer>& consumer) {
-
- QueueEvent(FRAME_RECEIVED);
-
- Mutex::Autolock al(mListenerMutex);
- if (mDropFrames) {
- CpuConsumer::LockedBuffer buf;
- status_t ret;
-
- if (OK == (ret = consumer->lockNextBuffer(&buf))) {
-
- dout << "Frame received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
- } else {
- dout << "Frame received on streamId = " << streamId << std::endl;
- }
- }
-
- virtual void onResultReceived(int32_t requestId,
- camera_metadata* request) {
- dout << "Result received requestId = " << requestId
- << ", requestPtr = " << (void*)request << std::endl;
- QueueEvent(RESULT_RECEIVED);
- free_camera_metadata(request);
- }
-
- virtual void notify(int32_t msg, int32_t ext1, int32_t ext2) {
- dout << "Notify received: msg " << std::hex << msg
- << ", ext1: " << std::hex << ext1 << ", ext2: " << std::hex << ext2
- << std::endl;
- }
-
- Vector<ProEvent> mProEventList;
- Mutex mListenerMutex;
- Mutex mConditionMutex;
- Condition mListenerCondition;
- int mEventMask;
- bool mDropFrames;
-};
-
-class ProCameraTest : public ::testing::Test {
-
-public:
- ProCameraTest() {
- char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
- if (displaySecsEnv != NULL) {
- mDisplaySecs = atoi(displaySecsEnv);
- if (mDisplaySecs < 0) {
- mDisplaySecs = 0;
- }
- } else {
- mDisplaySecs = 0;
- }
-
- char* displayFmtEnv = getenv("TEST_DISPLAY_FORMAT");
- if (displayFmtEnv != NULL) {
- mDisplayFmt = FormatFromString(displayFmtEnv);
- } else {
- mDisplayFmt = TEST_DISPLAY_FORMAT;
- }
-
- char* displayWidthEnv = getenv("TEST_DISPLAY_WIDTH");
- if (displayWidthEnv != NULL) {
- mDisplayW = atoi(displayWidthEnv);
- if (mDisplayW < 0) {
- mDisplayW = 0;
- }
- } else {
- mDisplayW = TEST_DISPLAY_WIDTH;
- }
-
- char* displayHeightEnv = getenv("TEST_DISPLAY_HEIGHT");
- if (displayHeightEnv != NULL) {
- mDisplayH = atoi(displayHeightEnv);
- if (mDisplayH < 0) {
- mDisplayH = 0;
- }
- } else {
- mDisplayH = TEST_DISPLAY_HEIGHT;
- }
- }
-
- static void SetUpTestCase() {
- // Binder Thread Pool Initialization
- mTestThread = new ProCameraTestThread();
- mTestThread->run("ProCameraTestThread");
- }
-
- virtual void SetUp() {
- mCamera = ProCamera::connect(CAMERA_ID);
- ASSERT_NE((void*)NULL, mCamera.get());
-
- mListener = new ProCameraTestListener();
- mCamera->setListener(mListener);
- }
-
- virtual void TearDown() {
- ASSERT_NE((void*)NULL, mCamera.get());
- mCamera->disconnect();
- }
-
-protected:
- sp<ProCamera> mCamera;
- sp<ProCameraTestListener> mListener;
-
- static sp<Thread> mTestThread;
-
- int mDisplaySecs;
- int mDisplayFmt;
- int mDisplayW;
- int mDisplayH;
-
- sp<SurfaceComposerClient> mComposerClient;
- sp<SurfaceControl> mSurfaceControl;
-
- sp<SurfaceComposerClient> mDepthComposerClient;
- sp<SurfaceControl> mDepthSurfaceControl;
-
- int getSurfaceWidth() {
- return 512;
- }
- int getSurfaceHeight() {
- return 512;
- }
-
- void createOnScreenSurface(sp<Surface>& surface) {
- mComposerClient = new SurfaceComposerClient;
- ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
-
- mSurfaceControl = mComposerClient->createSurface(
- String8("ProCameraTest StreamingImage Surface"),
- getSurfaceWidth(), getSurfaceHeight(),
- PIXEL_FORMAT_RGB_888, 0);
-
- mSurfaceControl->setPosition(0, 0);
-
- ASSERT_TRUE(mSurfaceControl != NULL);
- ASSERT_TRUE(mSurfaceControl->isValid());
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
- ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
-
- sp<ANativeWindow> window = mSurfaceControl->getSurface();
- surface = mSurfaceControl->getSurface();
-
- ASSERT_NE((void*)NULL, surface.get());
- }
-
- void createDepthOnScreenSurface(sp<Surface>& surface) {
- mDepthComposerClient = new SurfaceComposerClient;
- ASSERT_EQ(NO_ERROR, mDepthComposerClient->initCheck());
-
- mDepthSurfaceControl = mDepthComposerClient->createSurface(
- String8("ProCameraTest StreamingImage Surface"),
- getSurfaceWidth(), getSurfaceHeight(),
- PIXEL_FORMAT_RGB_888, 0);
-
- mDepthSurfaceControl->setPosition(640, 0);
-
- ASSERT_TRUE(mDepthSurfaceControl != NULL);
- ASSERT_TRUE(mDepthSurfaceControl->isValid());
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->setLayer(0x7FFFFFFF));
- ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
-
- sp<ANativeWindow> window = mDepthSurfaceControl->getSurface();
- surface = mDepthSurfaceControl->getSurface();
-
- ASSERT_NE((void*)NULL, surface.get());
- }
-
- template <typename T>
- static bool ExistsItem(T needle, T* array, size_t count) {
- if (!array) {
- return false;
- }
-
- for (size_t i = 0; i < count; ++i) {
- if (array[i] == needle) {
- return true;
- }
- }
- return false;
- }
-
-
- static int FormatFromString(const char* str) {
- std::string s(str);
-
-#define CMP_STR(x, y) \
- if (s == #x) return HAL_PIXEL_FORMAT_ ## y;
-#define CMP_STR_SAME(x) CMP_STR(x, x)
-
- CMP_STR_SAME( Y16);
- CMP_STR_SAME( Y8);
- CMP_STR_SAME( YV12);
- CMP_STR(NV16, YCbCr_422_SP);
- CMP_STR(NV21, YCrCb_420_SP);
- CMP_STR(YUY2, YCbCr_422_I);
- CMP_STR(RAW, RAW16);
- CMP_STR(RGBA, RGBA_8888);
-
- std::cerr << "Unknown format string " << str << std::endl;
- return -1;
-
- }
-
- /**
- * Creating a streaming request for these output streams from a template,
- * and submit it
- */
- void createSubmitRequestForStreams(int32_t* streamIds, size_t count, int requestCount=-1) {
-
- ASSERT_NE((void*)NULL, streamIds);
- ASSERT_LT(0u, count);
-
- camera_metadata_t *requestTmp = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&requestTmp));
- ASSERT_NE((void*)NULL, requestTmp);
- CameraMetadata request(requestTmp);
-
- // set the output streams. default is empty
-
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- request.update(tag, streamIds, count);
-
- requestTmp = request.release();
-
- if (requestCount < 0) {
- EXPECT_OK(mCamera->submitRequest(requestTmp, /*streaming*/true));
- } else {
- for (int i = 0; i < requestCount; ++i) {
- EXPECT_OK(mCamera->submitRequest(requestTmp,
- /*streaming*/false));
- }
- }
- request.acquire(requestTmp);
- }
-};
-
-sp<Thread> ProCameraTest::mTestThread;
-
-TEST_F(ProCameraTest, AvailableFormats) {
- if (HasFatalFailure()) {
- return;
- }
-
- CameraMetadata staticInfo = mCamera->getCameraInfo(CAMERA_ID);
- ASSERT_FALSE(staticInfo.isEmpty());
-
- uint32_t tag = static_cast<uint32_t>(ANDROID_SCALER_AVAILABLE_FORMATS);
- EXPECT_TRUE(staticInfo.exists(tag));
- camera_metadata_entry_t entry = staticInfo.find(tag);
-
- EXPECT_TRUE(ExistsItem<int32_t>(HAL_PIXEL_FORMAT_YV12,
- entry.data.i32, entry.count));
- EXPECT_TRUE(ExistsItem<int32_t>(HAL_PIXEL_FORMAT_YCrCb_420_SP,
- entry.data.i32, entry.count));
-}
-
-// test around exclusiveTryLock (immediate locking)
-TEST_F(ProCameraTest, LockingImmediate) {
-
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
- ProEvent_Mask(STOLEN) |
- ProEvent_Mask(RELEASED));
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveTryLock());
- // at this point we definitely have the lock
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
-
- EXPECT_TRUE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveUnlock());
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(RELEASED, mListener->ReadEvent());
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
-}
-
-// test around exclusiveLock (locking at some future point in time)
-TEST_F(ProCameraTest, LockingAsynchronous) {
-
- if (HasFatalFailure()) {
- return;
- }
-
-
- mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
- ProEvent_Mask(STOLEN) |
- ProEvent_Mask(RELEASED));
-
- // TODO: Add another procamera that has a lock here.
- // then we can be test that the lock wont immediately be acquired
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveTryLock());
- // at this point we definitely have the lock
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
-
- EXPECT_TRUE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveUnlock());
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(RELEASED, mListener->ReadEvent());
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
-}
-
-// Stream directly to the screen.
-TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) {
- if (HasFatalFailure()) {
- return;
- }
-
- sp<Surface> surface;
- if (mDisplaySecs > 0) {
- createOnScreenSurface(/*out*/surface);
- }
- else {
- dout << "Skipping, will not render to screen" << std::endl;
- return;
- }
-
- int depthStreamId = -1;
-
- sp<ServiceListener> listener = new ServiceListener();
- EXPECT_OK(ProCamera::addServiceListener(listener));
-
- ServiceListener::Status currentStatus;
-
- // when subscribing a new listener,
- // we immediately get a callback to the current status
- while (listener->waitForStatusChange(/*out*/currentStatus) != OK);
- EXPECT_EQ(ServiceListener::STATUS_PRESENT, currentStatus);
-
- dout << "Will now stream and resume infinitely..." << std::endl;
- while (true) {
-
- if (currentStatus == ServiceListener::STATUS_PRESENT) {
-
- ASSERT_OK(mCamera->createStream(mDisplayW, mDisplayH, mDisplayFmt,
- surface,
- &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { depthStreamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(
- streams,
- /*count*/1));
- }
-
- ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;
-
- // TODO: maybe check for getch every once in a while?
- while (listener->waitForStatusChange(/*out*/stat) != OK);
-
- if (currentStatus != stat) {
- if (stat == ServiceListener::STATUS_PRESENT) {
- dout << "Reconnecting to camera" << std::endl;
- mCamera = ProCamera::connect(CAMERA_ID);
- } else if (stat == ServiceListener::STATUS_NOT_AVAILABLE) {
- dout << "Disconnecting from camera" << std::endl;
- mCamera->disconnect();
- } else if (stat == ServiceListener::STATUS_NOT_PRESENT) {
- dout << "Camera unplugged" << std::endl;
- mCamera = NULL;
- } else {
- dout << "Unknown status change "
- << std::hex << stat << std::endl;
- }
-
- currentStatus = stat;
- }
- }
-
- EXPECT_OK(ProCamera::removeServiceListener(listener));
- EXPECT_OK(mCamera->deleteStream(depthStreamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-// Stream directly to the screen.
-TEST_F(ProCameraTest, DISABLED_StreamingImageDual) {
- if (HasFatalFailure()) {
- return;
- }
- sp<Surface> surface;
- sp<Surface> depthSurface;
- if (mDisplaySecs > 0) {
- createOnScreenSurface(/*out*/surface);
- createDepthOnScreenSurface(/*out*/depthSurface);
- }
-
- int streamId = -1;
- EXPECT_OK(mCamera->createStream(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, surface, &streamId));
- EXPECT_NE(-1, streamId);
-
- int depthStreamId = -1;
- EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- /*
- */
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- // it would probably be better to use CameraMetadata from camera service.
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- /*FIXME: dont need this later, at which point the above should become an
- ASSERT_NE*/
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- // wow what a verbose API.
- int32_t allStreams[] = { streamId, depthStreamId };
- // IMPORTANT. bad things will happen if its not a uint8.
- size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/streamCount, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- dout << "will sleep now for " << mDisplaySecs << std::endl;
- sleep(mDisplaySecs);
-
- free_camera_metadata(request);
-
- for (size_t i = 0; i < streamCount; ++i) {
- EXPECT_OK(mCamera->deleteStream(allStreams[i]));
- }
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, CpuConsumerSingle) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
- ProEvent_Mask(STOLEN) |
- ProEvent_Mask(RELEASED) |
- ProEvent_Mask(FRAME_RECEIVED));
- mListener->SetDropFrames(true);
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- // it would probably be better to use CameraMetadata from camera service.
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- /*FIXME: dont need this later, at which point the above should become an
- ASSERT_NE*/
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- int32_t allStreams[] = { streamId };
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/1) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/1));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/1, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- // Consume a couple of frames
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
- }
-
- // Done: clean up
- free_camera_metadata(request);
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, CpuConsumerDual) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(FRAME_RECEIVED));
- mListener->SetDropFrames(true);
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- int depthStreamId = -1;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &consumer, &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- /*
- */
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- // it would probably be better to use CameraMetadata from camera service.
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- // wow what a verbose API.
- int32_t allStreams[] = { streamId, depthStreamId };
- size_t streamCount = 2;
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/streamCount, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- // Consume a couple of frames
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- // stream id 1
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
-
- // stream id 2
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
-
- //TODO: events should be a struct with some data like the stream id
- }
-
- // Done: clean up
- free_camera_metadata(request);
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, ResultReceiver) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED));
- mListener->SetDropFrames(true);
- //FIXME: if this is run right after the previous test we get FRAME_RECEIVED
- // need to filter out events at read time
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- /*
- */
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- /*FIXME*/
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- int32_t allStreams[] = { streamId };
- size_t streamCount = 1;
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/streamCount, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- // Consume a couple of results
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(RESULT_RECEIVED, mListener->ReadEvent());
- }
-
- // Done: clean up
- free_camera_metadata(request);
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-// FIXME: This is racy and sometimes fails on waitForFrameMetadata
-TEST_F(ProCameraTest, DISABLED_WaitForResult) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetDropFrames(true);
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1));
-
- // Consume a couple of results
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_OK(mCamera->waitForFrameMetadata());
- CameraMetadata meta = mCamera->consumeFrameMetadata();
- EXPECT_FALSE(meta.isEmpty());
- }
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, WaitForSingleStreamBuffer) {
- if (HasFatalFailure()) {
- return;
- }
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
- /*requests*/TEST_CPU_FRAME_COUNT));
-
- // Consume a couple of results
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_EQ(1, mCamera->waitForFrameBuffer(streamId));
-
- CpuConsumer::LockedBuffer buf;
- EXPECT_OK(consumer->lockNextBuffer(&buf));
-
- dout << "Buffer synchronously received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-// FIXME: This is racy and sometimes fails on waitForFrameMetadata
-TEST_F(ProCameraTest, DISABLED_WaitForDualStreamBuffer) {
- if (HasFatalFailure()) {
- return;
- }
-
- const int REQUEST_COUNT = TEST_CPU_FRAME_COUNT * 10;
-
- // 15 fps
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- // 30 fps
- int depthStreamId = -1;
- sp<CpuConsumer> depthConsumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &depthConsumer, &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId, depthStreamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/2,
- /*requests*/REQUEST_COUNT));
-
- int depthFrames = 0;
- int greyFrames = 0;
-
- // Consume two frames simultaneously. Unsynchronized by timestamps.
- for (int i = 0; i < REQUEST_COUNT; ++i) {
-
- // Exhaust event queue so it doesn't keep growing
- while (mListener->ReadEvent() != UNKNOWN);
-
- // Get the metadata
- EXPECT_OK(mCamera->waitForFrameMetadata());
- CameraMetadata meta = mCamera->consumeFrameMetadata();
- EXPECT_FALSE(meta.isEmpty());
-
- // Get the buffers
-
- EXPECT_EQ(1, mCamera->waitForFrameBuffer(depthStreamId));
-
- /**
- * Guaranteed to be able to consume the depth frame,
- * since we waited on it.
- */
- CpuConsumer::LockedBuffer depthBuffer;
- EXPECT_OK(depthConsumer->lockNextBuffer(&depthBuffer));
-
- dout << "Depth Buffer synchronously received on streamId = " <<
- streamId <<
- ", dataPtr = " << (void*)depthBuffer.data <<
- ", timestamp = " << depthBuffer.timestamp << std::endl;
-
- EXPECT_OK(depthConsumer->unlockBuffer(depthBuffer));
-
- depthFrames++;
-
-
- /** Consume Greyscale frames if there are any.
- * There may not be since it runs at half FPS */
- CpuConsumer::LockedBuffer greyBuffer;
- while (consumer->lockNextBuffer(&greyBuffer) == OK) {
-
- dout << "GRAY Buffer synchronously received on streamId = " <<
- streamId <<
- ", dataPtr = " << (void*)greyBuffer.data <<
- ", timestamp = " << greyBuffer.timestamp << std::endl;
-
- EXPECT_OK(consumer->unlockBuffer(greyBuffer));
-
- greyFrames++;
- }
- }
-
- dout << "Done, summary: depth frames " << std::dec << depthFrames
- << ", grey frames " << std::dec << greyFrames << std::endl;
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesSync) {
- if (HasFatalFailure()) {
- return;
- }
-
- const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
- /*synchronousMode*/true, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
- /*requests*/NUM_REQUESTS));
-
- // Consume a couple of results
- for (int i = 0; i < NUM_REQUESTS; ++i) {
- int numFrames;
- EXPECT_TRUE((numFrames = mCamera->waitForFrameBuffer(streamId)) > 0);
-
- // Drop all but the newest framebuffer
- EXPECT_EQ(numFrames-1, mCamera->dropFrameBuffer(streamId, numFrames-1));
-
- dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;
-
- // Skip the counter ahead, don't try to consume these frames again
- i += numFrames-1;
-
- // "Consume" the buffer
- CpuConsumer::LockedBuffer buf;
- EXPECT_OK(consumer->lockNextBuffer(&buf));
-
- dout << "Buffer synchronously received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
-
- // Process at 10fps, stream is at 15fps.
- // This means we will definitely fill up the buffer queue with
- // extra buffers and need to drop them.
- usleep(TEST_FRAME_PROCESSING_DELAY_US);
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesAsync) {
- if (HasFatalFailure()) {
- return;
- }
-
- const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
- /*synchronousMode*/false, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
- /*requests*/NUM_REQUESTS));
-
- uint64_t lastFrameNumber = 0;
- int numFrames;
-
- // Consume a couple of results
- int i;
- for (i = 0; i < NUM_REQUESTS && lastFrameNumber < NUM_REQUESTS; ++i) {
- EXPECT_LT(0, (numFrames = mCamera->waitForFrameBuffer(streamId)));
-
- dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;
-
- // Skip the counter ahead, don't try to consume these frames again
- i += numFrames-1;
-
- // "Consume" the buffer
- CpuConsumer::LockedBuffer buf;
-
- EXPECT_EQ(OK, consumer->lockNextBuffer(&buf));
-
- lastFrameNumber = buf.frameNumber;
-
- dout << "Buffer asynchronously received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp <<
- ", framenumber = " << buf.frameNumber << std::endl;
-
- // Process at 10fps, stream is at 15fps.
- // This means we will definitely fill up the buffer queue with
- // extra buffers and need to drop them.
- usleep(TEST_FRAME_PROCESSING_DELAY_US);
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
-
- dout << "Done after " << i << " iterations " << std::endl;
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-
-
-//TODO: refactor into separate file
-TEST_F(ProCameraTest, ServiceListenersSubscribe) {
-
- ASSERT_EQ(4u, sizeof(ServiceListener::Status));
-
- sp<ServiceListener> listener = new ServiceListener();
-
- EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
- EXPECT_OK(ProCamera::addServiceListener(listener));
-
- EXPECT_EQ(ALREADY_EXISTS, ProCamera::addServiceListener(listener));
- EXPECT_OK(ProCamera::removeServiceListener(listener));
-
- EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
-}
-
-//TODO: refactor into separate file
-TEST_F(ProCameraTest, ServiceListenersFunctional) {
-
- sp<ServiceListener> listener = new ServiceListener();
-
- EXPECT_OK(ProCamera::addServiceListener(listener));
-
- sp<Camera> cam = Camera::connect(CAMERA_ID,
- /*clientPackageName*/String16(),
- -1);
- EXPECT_NE((void*)NULL, cam.get());
-
- ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;
- EXPECT_OK(listener->waitForStatusChange(/*out*/stat));
-
- EXPECT_EQ(ServiceListener::STATUS_NOT_AVAILABLE, stat);
-
- if (cam.get()) {
- cam->disconnect();
- }
-
- EXPECT_OK(listener->waitForStatusChange(/*out*/stat));
- EXPECT_EQ(ServiceListener::STATUS_PRESENT, stat);
-
- EXPECT_OK(ProCamera::removeServiceListener(listener));
-}
-
-
-
-}
-}
-}
-}
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 194a646..c8d3d19 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -25,8 +25,6 @@ namespace android {
class ICamera;
class ICameraClient;
-class IProCameraUser;
-class IProCameraCallbacks;
class ICameraServiceListener;
class ICameraDeviceUser;
class ICameraDeviceCallbacks;
@@ -44,7 +42,6 @@ public:
GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
GET_CAMERA_INFO,
CONNECT,
- CONNECT_PRO,
CONNECT_DEVICE,
ADD_LISTENER,
REMOVE_LISTENER,
@@ -105,13 +102,6 @@ public:
/*out*/
sp<ICamera>& device) = 0;
- virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb,
- int cameraId,
- const String16& clientPackageName,
- int clientUid,
- /*out*/
- sp<IProCameraUser>& device) = 0;
-
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
diff --git a/include/camera/IProCameraCallbacks.h b/include/camera/IProCameraCallbacks.h
deleted file mode 100644
index e8abb89..0000000
--- a/include/camera/IProCameraCallbacks.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 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_HARDWARE_IPROCAMERA_CALLBACKS_H
-#define ANDROID_HARDWARE_IPROCAMERA_CALLBACKS_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <utils/Timers.h>
-#include <system/camera.h>
-
-struct camera_metadata;
-
-namespace android {
-
-class IProCameraCallbacks : public IInterface
-{
- /**
- * Keep up-to-date with IProCameraCallbacks.aidl in frameworks/base
- */
-public:
- DECLARE_META_INTERFACE(ProCameraCallbacks);
-
- virtual void notifyCallback(int32_t msgType,
- int32_t ext1,
- int32_t ext2) = 0;
-
- enum LockStatus {
- LOCK_ACQUIRED,
- LOCK_RELEASED,
- LOCK_STOLEN,
- };
-
- virtual void onLockStatusChanged(LockStatus newLockStatus) = 0;
-
- /** Missing by design: implementation is client-side in ProCamera.cpp **/
- // virtual void onBufferReceived(int streamId,
- // const CpuConsumer::LockedBufer& buf);
- virtual void onResultReceived(int32_t requestId,
- camera_metadata* result) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnProCameraCallbacks : public BnInterface<IProCameraCallbacks>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/camera/IProCameraUser.h b/include/camera/IProCameraUser.h
deleted file mode 100644
index 2ccc4d2..0000000
--- a/include/camera/IProCameraUser.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013 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_HARDWARE_IPROCAMERAUSER_H
-#define ANDROID_HARDWARE_IPROCAMERAUSER_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <utils/String8.h>
-#include <camera/IProCameraCallbacks.h>
-
-struct camera_metadata;
-
-namespace android {
-
-class IProCameraUserClient;
-class IGraphicBufferProducer;
-class Surface;
-
-class IProCameraUser: public IInterface
-{
- /**
- * Keep up-to-date with IProCameraUser.aidl in frameworks/base
- */
-public:
- DECLARE_META_INTERFACE(ProCameraUser);
-
- virtual void disconnect() = 0;
-
- // connect to the service, given a callbacks listener
- virtual status_t connect(const sp<IProCameraCallbacks>& callbacks)
- = 0;
-
- /**
- * Locking
- **/
- virtual status_t exclusiveTryLock() = 0;
- virtual status_t exclusiveLock() = 0;
- virtual status_t exclusiveUnlock() = 0;
-
- virtual bool hasExclusiveLock() = 0;
-
- /**
- * Request Handling
- **/
-
- // Note that the callee gets a copy of the metadata.
- virtual int submitRequest(struct camera_metadata* metadata,
- bool streaming = false) = 0;
- virtual status_t cancelRequest(int requestId) = 0;
-
- virtual status_t deleteStream(int streamId) = 0;
- virtual status_t createStream(
- int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId) = 0;
-
- // Create a request object from a template.
- virtual status_t createDefaultRequest(int templateId,
- /*out*/
- camera_metadata** request)
- = 0;
-
- // Get static camera metadata
- virtual status_t getCameraInfo(int cameraId,
- /*out*/
- camera_metadata** info) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnProCameraUser: public BnInterface<IProCameraUser>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/camera/ProCamera.h b/include/camera/ProCamera.h
deleted file mode 100644
index e9b687a..0000000
--- a/include/camera/ProCamera.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2013 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_HARDWARE_PRO_CAMERA_H
-#define ANDROID_HARDWARE_PRO_CAMERA_H
-
-#include <utils/Timers.h>
-#include <utils/KeyedVector.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <system/camera.h>
-#include <camera/IProCameraCallbacks.h>
-#include <camera/IProCameraUser.h>
-#include <camera/Camera.h>
-#include <camera/CameraMetadata.h>
-#include <camera/ICameraService.h>
-#include <gui/CpuConsumer.h>
-
-#include <gui/Surface.h>
-
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-
-#include <camera/CameraBase.h>
-
-struct camera_metadata;
-
-namespace android {
-
-// All callbacks on this class are concurrent
-// (they come from separate threads)
-class ProCameraListener : virtual public RefBase
-{
-public:
- virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
-
- // Lock has been acquired. Write operations now available.
- virtual void onLockAcquired() = 0;
- // Lock has been released with exclusiveUnlock.
- virtual void onLockReleased() = 0;
- // Lock has been stolen by another client.
- virtual void onLockStolen() = 0;
-
- // Lock free.
- virtual void onTriggerNotify(int32_t msgType, int32_t ext1, int32_t ext2)
- = 0;
- // onFrameAvailable and OnResultReceived can come in with any order,
- // use android.sensor.timestamp and LockedBuffer.timestamp to correlate them
-
- /**
- * A new metadata buffer has been received.
- * -- Ownership of request passes on to the callee, free with
- * free_camera_metadata.
- */
- virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0;
-
- // TODO: make onFrameAvailable pure virtual
-
- // A new frame buffer has been received for this stream.
- // -- This callback only fires for createStreamCpu streams
- // -- A buffer may be obtained by calling cpuConsumer->lockNextBuffer
- // -- Use buf.timestamp to correlate with result's android.sensor.timestamp
- // -- The buffer should be accessed with CpuConsumer::lockNextBuffer
- // and CpuConsumer::unlockBuffer
- virtual void onFrameAvailable(int /*streamId*/,
- const sp<CpuConsumer>& /*cpuConsumer*/) {
- }
-
-};
-
-class ProCamera;
-
-template <>
-struct CameraTraits<ProCamera>
-{
- typedef ProCameraListener TCamListener;
- typedef IProCameraUser TCamUser;
- typedef IProCameraCallbacks TCamCallbacks;
- typedef status_t (ICameraService::*TCamConnectService)(const sp<IProCameraCallbacks>&,
- int, const String16&, int,
- /*out*/
- sp<IProCameraUser>&);
- static TCamConnectService fnConnectService;
-};
-
-
-class ProCamera :
- public CameraBase<ProCamera>,
- public BnProCameraCallbacks
-{
-public:
- /**
- * Connect a shared camera. By default access is restricted to read only
- * (Lock free) operations. To be able to submit custom requests a lock needs
- * to be acquired with exclusive[Try]Lock.
- */
- static sp<ProCamera> connect(int cameraId);
- virtual ~ProCamera();
-
- /**
- * Exclusive Locks:
- * - We may request exclusive access to a camera if no other
- * clients are using the camera. This works as a traditional
- * client, writing/reading any camera state.
- * - An application opening the camera (a regular 'Camera') will
- * always steal away the exclusive lock from a ProCamera,
- * this will call onLockReleased.
- * - onLockAcquired will be called again once it is possible
- * to again exclusively lock the camera.
- *
- */
-
- /**
- * All exclusiveLock/unlock functions are asynchronous. The remote endpoint
- * shall not block while waiting to acquire the lock. Instead the lock
- * notifications will come in asynchronously on the listener.
- */
-
- /**
- * Attempt to acquire the lock instantly (non-blocking)
- * - If this succeeds, you do not need to wait for onLockAcquired
- * but the event will still be fired
- *
- * Returns -EBUSY if already locked. 0 on success.
- */
- status_t exclusiveTryLock();
- // always returns 0. wait for onLockAcquired before lock is acquired.
- status_t exclusiveLock();
- // release a lock if we have one, or cancel the lock request.
- status_t exclusiveUnlock();
-
- // exclusive lock = do whatever we want. no lock = read only.
- bool hasExclusiveLock();
-
- /**
- * < 0 error, >= 0 the request ID. streaming to have the request repeat
- * until cancelled.
- * The request queue is flushed when a lock is released or stolen
- * if not locked will return PERMISSION_DENIED
- */
- int submitRequest(const struct camera_metadata* metadata,
- bool streaming = false);
- // if not locked will return PERMISSION_DENIED, BAD_VALUE if requestId bad
- status_t cancelRequest(int requestId);
-
- /**
- * Ask for a stream to be enabled.
- * Lock free. Service maintains counter of streams.
- */
- status_t requestStream(int streamId);
-// TODO: remove requestStream, its useless.
-
- /**
- * Delete a stream.
- * Lock free.
- *
- * NOTE: As a side effect this cancels ALL streaming requests.
- *
- * Errors: BAD_VALUE if unknown stream ID.
- * PERMISSION_DENIED if the stream wasn't yours
- */
- status_t deleteStream(int streamId);
-
- /**
- * Create a new HW stream, whose sink will be the window.
- * Lock free. Service maintains counter of streams.
- * Errors: -EBUSY if too many streams created
- */
- status_t createStream(int width, int height, int format,
- const sp<Surface>& surface,
- /*out*/
- int* streamId);
-
- /**
- * Create a new HW stream, whose sink will be the SurfaceTexture.
- * Lock free. Service maintains counter of streams.
- * Errors: -EBUSY if too many streams created
- */
- status_t createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId);
- status_t createStreamCpu(int width, int height, int format,
- int heapCount,
- /*out*/
- sp<CpuConsumer>* cpuConsumer,
- int* streamId);
- status_t createStreamCpu(int width, int height, int format,
- int heapCount,
- bool synchronousMode,
- /*out*/
- sp<CpuConsumer>* cpuConsumer,
- int* streamId);
-
- // Create a request object from a template.
- status_t createDefaultRequest(int templateId,
- /*out*/
- camera_metadata** request) const;
-
- // Get static camera metadata
- camera_metadata* getCameraInfo(int cameraId);
-
- // Blocks until a frame is available (CPU streams only)
- // - Obtain the frame data by calling CpuConsumer::lockNextBuffer
- // - Release the frame data after use with CpuConsumer::unlockBuffer
- // Return value:
- // - >0 - number of frames available to be locked
- // - <0 - error (refer to error codes)
- // Error codes:
- // -ETIMEDOUT if it took too long to get a frame
- int waitForFrameBuffer(int streamId);
-
- // Blocks until a metadata result is available
- // - Obtain the metadata by calling consumeFrameMetadata()
- // Error codes:
- // -ETIMEDOUT if it took too long to get a frame
- status_t waitForFrameMetadata();
-
- // Get the latest metadata. This is destructive.
- // - Calling this repeatedly will produce empty metadata objects.
- // - Use waitForFrameMetadata to sync until new data is available.
- CameraMetadata consumeFrameMetadata();
-
- // Convenience method to drop frame buffers (CPU streams only)
- // Return values:
- // >=0 - number of frames dropped (up to count)
- // <0 - error code
- // Error codes:
- // BAD_VALUE - invalid streamId or count passed
- int dropFrameBuffer(int streamId, int count);
-
-protected:
- ////////////////////////////////////////////////////////
- // IProCameraCallbacks implementation
- ////////////////////////////////////////////////////////
- virtual void notifyCallback(int32_t msgType,
- int32_t ext,
- int32_t ext2);
-
- virtual void onLockStatusChanged(
- IProCameraCallbacks::LockStatus newLockStatus);
-
- virtual void onResultReceived(int32_t requestId,
- camera_metadata* result);
-private:
- ProCamera(int cameraId);
-
- class ProFrameListener : public CpuConsumer::FrameAvailableListener {
- public:
- ProFrameListener(wp<ProCamera> camera, int streamID) {
- mCamera = camera;
- mStreamId = streamID;
- }
-
- protected:
- virtual void onFrameAvailable(const BufferItem& /* item */) {
- sp<ProCamera> c = mCamera.promote();
- if (c.get() != NULL) {
- c->onFrameAvailable(mStreamId);
- }
- }
-
- private:
- wp<ProCamera> mCamera;
- int mStreamId;
- };
- friend class ProFrameListener;
-
- struct StreamInfo
- {
- StreamInfo(int streamId) {
- this->streamID = streamId;
- cpuStream = false;
- frameReady = 0;
- }
-
- StreamInfo() {
- streamID = -1;
- cpuStream = false;
- }
-
- int streamID;
- bool cpuStream;
- sp<CpuConsumer> cpuConsumer;
- bool synchronousMode;
- sp<ProFrameListener> frameAvailableListener;
- sp<Surface> stc;
- int frameReady;
- };
-
- Condition mWaitCondition;
- Mutex mWaitMutex;
- static const nsecs_t mWaitTimeout = 1000000000; // 1sec
- KeyedVector<int, StreamInfo> mStreams;
- bool mMetadataReady;
- CameraMetadata mLatestMetadata;
-
- void onFrameAvailable(int streamId);
-
- StreamInfo& getStreamInfo(int streamId);
-
- friend class CameraBase;
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index aa91485..c1483f3 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -291,7 +291,7 @@ private:
OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat);
status_t setupAMRCodec(bool encoder, bool isWAMR, int32_t bitRate);
- status_t setupG711Codec(bool encoder, int32_t numChannels);
+ 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);
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index e341160..84b1b1a 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -250,7 +250,7 @@ private:
status_t setAC3Format(int32_t numChannels, int32_t sampleRate);
- void setG711Format(int32_t numChannels);
+ void setG711Format(int32_t sampleRate, int32_t numChannels);
status_t setVideoPortFormatType(
OMX_U32 portIndex,
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 31e10ce..97f3e20 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1591,7 +1591,11 @@ status_t ACodec::configureCodec(
if (!msg->findInt32("channel-count", &numChannels)) {
err = INVALID_OPERATION;
} else {
- err = setupG711Codec(encoder, numChannels);
+ int32_t sampleRate;
+ if (!msg->findInt32("sample-rate", &sampleRate)) {
+ sampleRate = 8000;
+ }
+ err = setupG711Codec(encoder, sampleRate, numChannels);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
int32_t numChannels, sampleRate, compressionLevel = -1;
@@ -2066,11 +2070,11 @@ status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1 /* numChannels */);
}
-status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
+status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
CHECK(!encoder); // XXX TODO
return setupRawAudioFormat(
- kPortIndexInput, 8000 /* sampleRate */, numChannels);
+ kPortIndexInput, sampleRate, numChannels);
}
status_t ACodec::setupFlacCodec(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index ea19ab2..4d30069 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -629,10 +629,14 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
// These are PCM-like formats with a fixed sample rate but
// a variable number of channels.
+ int32_t sampleRate;
int32_t numChannels;
CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+ if (!meta->findInt32(kKeySampleRate, &sampleRate)) {
+ sampleRate = 8000;
+ }
- setG711Format(numChannels);
+ setG711Format(sampleRate, numChannels);
} else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mMIME)) {
CHECK(!mIsEncoder);
@@ -3616,9 +3620,9 @@ status_t OMXCodec::setAC3Format(int32_t numChannels, int32_t sampleRate) {
sizeof(def));
}
-void OMXCodec::setG711Format(int32_t numChannels) {
+void OMXCodec::setG711Format(int32_t sampleRate, int32_t numChannels) {
CHECK(!mIsEncoder);
- setRawAudioFormat(kPortIndexInput, 8000, numChannels);
+ setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
}
void OMXCodec::setImageOutputFormat(
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 3a69095..015515e 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -41,8 +41,9 @@ SoftG711::SoftG711(
OMX_COMPONENTTYPE **component)
: SimpleSoftOMXComponent(name, callbacks, appData, component),
mIsMLaw(true),
+ mSignalledError(false),
mNumChannels(1),
- mSignalledError(false) {
+ mSamplingRate(8000) {
if (!strcmp(name, "OMX.google.g711.alaw.decoder")) {
mIsMLaw = false;
} else {
@@ -129,7 +130,7 @@ OMX_ERRORTYPE SoftG711::internalGetParameter(
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
pcmParams->nChannels = mNumChannels;
- pcmParams->nSamplingRate = 8000;
+ pcmParams->nSamplingRate = mSamplingRate;
return OMX_ErrorNone;
}
@@ -159,6 +160,8 @@ OMX_ERRORTYPE SoftG711::internalSetParameter(
mNumChannels = pcmParams->nChannels;
}
+ mSamplingRate = pcmParams->nSamplingRate;
+
return OMX_ErrorNone;
}
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.h b/media/libstagefright/codecs/g711/dec/SoftG711.h
index bff0c68..16b6340 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.h
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.h
@@ -46,8 +46,9 @@ private:
};
bool mIsMLaw;
- OMX_U32 mNumChannels;
bool mSignalledError;
+ OMX_U32 mNumChannels;
+ int32_t mSamplingRate;
void initPorts();
diff --git a/media/libstagefright/data/media_codecs_google_audio.xml b/media/libstagefright/data/media_codecs_google_audio.xml
index a06684b..b957b0c 100644
--- a/media/libstagefright/data/media_codecs_google_audio.xml
+++ b/media/libstagefright/data/media_codecs_google_audio.xml
@@ -38,12 +38,12 @@
</MediaCodec>
<MediaCodec name="OMX.google.g711.alaw.decoder" type="audio/g711-alaw">
<Limit name="channel-count" max="1" />
- <Limit name="sample-rate" ranges="8000" />
+ <Limit name="sample-rate" ranges="8000-48000" />
<Limit name="bitrate" range="64000" />
</MediaCodec>
<MediaCodec name="OMX.google.g711.mlaw.decoder" type="audio/g711-mlaw">
<Limit name="channel-count" max="1" />
- <Limit name="sample-rate" ranges="8000" />
+ <Limit name="sample-rate" ranges="8000-48000" />
<Limit name="bitrate" range="64000" />
</MediaCodec>
<MediaCodec name="OMX.google.vorbis.decoder" type="audio/vorbis">
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index f5328a6..738f8b6 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -128,6 +128,7 @@ LiveSession::LiveSession(
mInPreparationPhase(true),
mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())),
mCurBandwidthIndex(-1),
+ mLastBandwidthBps(-1ll),
mBandwidthEstimator(new BandwidthEstimator()),
mStreamMask(0),
mNewStreamMask(0),
@@ -159,24 +160,6 @@ LiveSession::~LiveSession() {
}
}
-sp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) {
- ABuffer *discontinuity = new ABuffer(0);
- discontinuity->meta()->setInt32("discontinuity", ATSParser::DISCONTINUITY_FORMATCHANGE);
- discontinuity->meta()->setInt32("swapPacketSource", swap);
- discontinuity->meta()->setInt32("switchGeneration", mSwitchGeneration);
- discontinuity->meta()->setInt64("timeUs", -1);
- return discontinuity;
-}
-
-void LiveSession::swapPacketSource(StreamType stream) {
- sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
- sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
- sp<AnotherPacketSource> tmp = aps;
- aps = aps2;
- aps2 = tmp;
- aps2->clear();
-}
-
status_t LiveSession::dequeueAccessUnit(
StreamType stream, sp<ABuffer> *accessUnit) {
if (!(mStreamMask & stream)) {
@@ -189,7 +172,13 @@ status_t LiveSession::dequeueAccessUnit(
sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
ssize_t idx = typeToIndex(stream);
- if (!packetSource->hasBufferAvailable(&finalResult)) {
+ // Do not let client pull data if we don't have data packets yet.
+ // We might only have a format discontinuity queued without data.
+ // When NuPlayerDecoder dequeues the format discontinuity, it will
+ // immediately try to getFormat. If we return NULL, NuPlayerDecoder
+ // thinks it can do seamless change, so will not shutdown decoder.
+ // When the actual format arrives, it can't handle it and get stuck.
+ if (!packetSource->hasDataBufferAvailable(&finalResult)) {
if (finalResult == OK) {
return -EAGAIN;
} else {
@@ -197,49 +186,8 @@ status_t LiveSession::dequeueAccessUnit(
}
}
- // Do not let client pull data if we don't have format yet.
- // We might only have a format discontinuity queued without actual data.
- // When NuPlayerDecoder dequeues the format discontinuity, it will
- // immediately try to getFormat. If we return NULL, NuPlayerDecoder
- // thinks it can do seamless change, so will not shutdown decoder.
- // When the actual format arrives, it can't handle it and get stuck.
- // TODO: We need a method to check if the packet source has any
- // data packets available, dequeuing should only start then.
- sp<MetaData> format = packetSource->getFormat();
- if (format == NULL) {
- return -EAGAIN;
- }
- int32_t targetDuration = 0;
- sp<AMessage> meta = packetSource->getLatestEnqueuedMeta();
- if (meta != NULL) {
- meta->findInt32("targetDuration", &targetDuration);
- }
-
- int64_t targetDurationUs = targetDuration * 1000000ll;
- if (targetDurationUs == 0 ||
- targetDurationUs > PlaylistFetcher::kMinBufferedDurationUs) {
- // Fetchers limit buffering to
- // min(3 * targetDuration, kMinBufferedDurationUs)
- targetDurationUs = PlaylistFetcher::kMinBufferedDurationUs;
- }
-
- // wait for counterpart
- sp<AnotherPacketSource> otherSource;
- uint32_t mask = mNewStreamMask & mStreamMask;
- uint32_t fetchersMask = 0;
- for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
- uint32_t fetcherMask = mFetcherInfos.valueAt(i).mFetcher->getStreamTypeMask();
- fetchersMask |= fetcherMask;
- }
- mask &= fetchersMask;
- if (stream == STREAMTYPE_AUDIO && (mask & STREAMTYPE_VIDEO)) {
- otherSource = mPacketSources.valueFor(STREAMTYPE_VIDEO);
- } else if (stream == STREAMTYPE_VIDEO && (mask & STREAMTYPE_AUDIO)) {
- otherSource = mPacketSources.valueFor(STREAMTYPE_AUDIO);
- }
- if (otherSource != NULL && !otherSource->hasBufferAvailable(&finalResult)) {
- return finalResult == OK ? -EAGAIN : finalResult;
- }
+ // Let the client dequeue as long as we have buffers available
+ // Do not make pause/resume decisions here.
status_t err = packetSource->dequeueAccessUnit(accessUnit);
@@ -278,41 +226,25 @@ status_t LiveSession::dequeueAccessUnit(
type,
extra == NULL ? "NULL" : extra->debugString().c_str());
- int32_t swap;
- if ((*accessUnit)->meta()->findInt32("swapPacketSource", &swap) && swap) {
- int32_t switchGeneration;
- CHECK((*accessUnit)->meta()->findInt32("switchGeneration", &switchGeneration));
- {
- Mutex::Autolock lock(mSwapMutex);
- if (switchGeneration == mSwitchGeneration) {
- swapPacketSource(stream);
- sp<AMessage> msg = new AMessage(kWhatSwapped, this);
- msg->setInt32("stream", stream);
- msg->setInt32("switchGeneration", switchGeneration);
- msg->post();
- }
- }
+ size_t seq = strm.mCurDiscontinuitySeq;
+ int64_t offsetTimeUs;
+ if (mDiscontinuityOffsetTimesUs.indexOfKey(seq) >= 0) {
+ offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(seq);
} else {
- size_t seq = strm.mCurDiscontinuitySeq;
- int64_t offsetTimeUs;
- if (mDiscontinuityOffsetTimesUs.indexOfKey(seq) >= 0) {
- offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(seq);
- } else {
- offsetTimeUs = 0;
- }
-
- seq += 1;
- if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
- int64_t firstTimeUs;
- firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
- offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
- offsetTimeUs += strm.mLastSampleDurationUs;
- } else {
- offsetTimeUs += strm.mLastSampleDurationUs;
- }
+ offsetTimeUs = 0;
+ }
- mDiscontinuityOffsetTimesUs.add(seq, offsetTimeUs);
+ seq += 1;
+ if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
+ int64_t firstTimeUs;
+ firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
+ offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
+ offsetTimeUs += strm.mLastSampleDurationUs;
+ } else {
+ offsetTimeUs += strm.mLastSampleDurationUs;
}
+
+ mDiscontinuityOffsetTimesUs.add(seq, offsetTimeUs);
} else if (err == OK) {
if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
@@ -373,7 +305,6 @@ status_t LiveSession::dequeueAccessUnit(
}
status_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
- // No swapPacketSource race condition; called from the same thread as dequeueAccessUnit.
if (!(mStreamMask & stream)) {
return UNKNOWN_ERROR;
}
@@ -389,6 +320,10 @@ status_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
return convertMetaDataToMessage(meta, format);
}
+sp<HTTPBase> LiveSession::getHTTPDataSource() {
+ return new MediaHTTP(mHTTPService->makeHTTPConnection());
+}
+
void LiveSession::connectAsync(
const char *url, const KeyedVector<String8, String8> *headers) {
sp<AMessage> msg = new AMessage(kWhatConnect, this);
@@ -468,21 +403,27 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
case PlaylistFetcher::kWhatPaused:
case PlaylistFetcher::kWhatStopped:
{
+ AString uri;
+ CHECK(msg->findString("uri", &uri));
+ ssize_t index = mFetcherInfos.indexOfKey(uri);
+ if (index < 0) {
+ // ignore msgs from fetchers that's already gone
+ break;
+ }
+
if (what == PlaylistFetcher::kWhatStopped) {
- AString uri;
- CHECK(msg->findString("uri", &uri));
- ssize_t index = mFetcherInfos.indexOfKey(uri);
- if (index < 0) {
- // ignore duplicated kWhatStopped messages.
- break;
- }
+ tryToFinishBandwidthSwitch(uri);
mFetcherLooper->unregisterHandler(
mFetcherInfos[index].mFetcher->id());
mFetcherInfos.removeItemsAt(index);
-
- if (mSwitchInProgress) {
- tryToFinishBandwidthSwitch();
+ } else if (what == PlaylistFetcher::kWhatPaused) {
+ int32_t seekMode;
+ CHECK(msg->findInt32("seekMode", &seekMode));
+ for (size_t i = 0; i < kMaxStreams; ++i) {
+ if (mStreams[i].mUri == uri) {
+ mStreams[i].mSeekMode = (SeekMode) seekMode;
+ }
}
}
@@ -564,6 +505,13 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ AString uri;
+ CHECK(msg->findString("uri", &uri));
+ ssize_t index = mFetcherInfos.indexOfKey(uri);
+ if (index >= 0) {
+ mFetcherInfos.editValueAt(index).mToBeResumed = true;
+ }
+
// Resume fetcher for the original variant; the resumed fetcher should
// continue until the timestamps found in msg, which is stored by the
// new fetcher to indicate where the new variant has started buffering.
@@ -607,12 +555,6 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
break;
}
- case kWhatSwapped:
- {
- onSwapped(msg);
- break;
- }
-
case kWhatPollBuffering:
{
int32_t generation;
@@ -751,11 +693,10 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
}
void LiveSession::finishDisconnect() {
+ ALOGV("finishDisconnect");
+
// No reconfiguration is currently pending, make sure none will trigger
// during disconnection either.
-
- // Protect mPacketSources from a swapPacketSource race condition through disconnect.
- // (finishDisconnect, onFinishDisconnect2)
cancelBandwidthSwitch();
// cancel buffer polling
@@ -805,8 +746,8 @@ sp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
FetcherInfo info;
info.mFetcher = new PlaylistFetcher(notify, this, uri, mSubtitleGeneration);
info.mDurationUs = -1ll;
- info.mIsPrepared = false;
info.mToBeRemoved = false;
+ info.mToBeResumed = false;
mFetcherLooper->registerHandler(info.mFetcher);
mFetcherInfos.add(uri, info);
@@ -835,14 +776,15 @@ ssize_t LiveSession::fetchFile(
int64_t range_offset, int64_t range_length,
uint32_t block_size, /* download block size */
sp<DataSource> *source, /* to return and reuse source */
- String8 *actualUrl) {
+ String8 *actualUrl,
+ bool forceConnectHTTP /* force connect HTTP when resuing source */) {
off64_t size;
sp<DataSource> temp_source;
if (source == NULL) {
source = &temp_source;
}
- if (*source == NULL) {
+ if (*source == NULL || forceConnectHTTP) {
if (!strncasecmp(url, "file://", 7)) {
*source = new FileSource(url + 7);
} else if (strncasecmp(url, "http://", 7)
@@ -861,13 +803,18 @@ ssize_t LiveSession::fetchFile(
? "" : AStringPrintf("%lld",
range_offset + range_length - 1).c_str()).c_str()));
}
- status_t err = mHTTPDataSource->connect(url, &headers);
+
+ HTTPBase* httpDataSource =
+ (*source == NULL) ? mHTTPDataSource.get() : (HTTPBase*)source->get();
+ status_t err = httpDataSource->connect(url, &headers);
if (err != OK) {
return err;
}
- *source = mHTTPDataSource;
+ if (*source == NULL) {
+ *source = mHTTPDataSource;
+ }
}
}
@@ -1003,6 +950,57 @@ static double uniformRand() {
}
#endif
+float LiveSession::getAbortThreshold(
+ ssize_t currentBWIndex, ssize_t targetBWIndex) const {
+ float abortThreshold = -1.0f;
+ if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) {
+ /*
+ If we're switching down, we need to decide whether to
+
+ 1) finish last segment of high-bandwidth variant, or
+ 2) abort last segment of high-bandwidth variant, and fetch an
+ overlapping portion from low-bandwidth variant.
+
+ Here we try to maximize the amount of buffer left when the
+ switch point is met. Given the following parameters:
+
+ B: our current buffering level in seconds
+ T: target duration in seconds
+ X: sample duration in seconds remain to fetch in last segment
+ bw0: bandwidth of old variant (as specified in playlist)
+ bw1: bandwidth of new variant (as specified in playlist)
+ bw: measured bandwidth available
+
+ If we choose 1), when switch happens at the end of current
+ segment, our buffering will be
+ B + X - X * bw0 / bw
+
+ If we choose 2), when switch happens where we aborted current
+ segment, our buffering will be
+ B - (T - X) * bw1 / bw
+
+ We should only choose 1) if
+ X/T < bw1 / (bw1 + bw0 - bw)
+ */
+
+ CHECK(mLastBandwidthBps >= 0);
+ abortThreshold =
+ (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
+ / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
+ + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth
+ - (float)mLastBandwidthBps * 0.7f);
+ if (abortThreshold < 0.0f) {
+ abortThreshold = -1.0f; // do not abort
+ }
+ ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f",
+ mBandwidthItems.itemAt(currentBWIndex).mBandwidth,
+ mBandwidthItems.itemAt(targetBWIndex).mBandwidth,
+ mLastBandwidthBps,
+ abortThreshold);
+ }
+ return abortThreshold;
+}
+
void LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) {
mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs);
}
@@ -1210,8 +1208,6 @@ void LiveSession::changeConfiguration(
CHECK(!mReconfigurationInProgress);
mReconfigurationInProgress = true;
- mCurBandwidthIndex = bandwidthIndex;
-
ALOGV("changeConfiguration => timeUs:%" PRId64 " us, bwIndex:%zu, pickTrack:%d",
timeUs, bandwidthIndex, pickTrack);
@@ -1238,7 +1234,6 @@ void LiveSession::changeConfiguration(
if (timeUs < 0ll) {
// delay fetcher removal if not picking tracks
discardFetcher = pickTrack;
-
}
for (size_t j = 0; j < kMaxStreams; ++j) {
@@ -1253,12 +1248,24 @@ void LiveSession::changeConfiguration(
if (discardFetcher) {
mFetcherInfos.valueAt(i).mFetcher->stopAsync();
} else {
- // if we're seeking, pause immediately (no need to finish the segment)
- bool immediate = (timeUs >= 0ll);
- mFetcherInfos.valueAt(i).mFetcher->pauseAsync(immediate);
+ float threshold = -1.0f; // always finish fetching by default
+ if (timeUs >= 0ll) {
+ // seeking, no need to finish fetching
+ threshold = 0.0f;
+ } else if (!pickTrack) {
+ // adapting, abort if remaining of current segment is over threshold
+ threshold = getAbortThreshold(
+ mCurBandwidthIndex, bandwidthIndex);
+ }
+
+ ALOGV("Pausing with threshold %.3f", threshold);
+
+ mFetcherInfos.valueAt(i).mFetcher->pauseAsync(threshold);
}
}
+ mCurBandwidthIndex = bandwidthIndex;
+
sp<AMessage> msg;
if (timeUs < 0ll) {
// skip onChangeConfiguration2 (decoder destruction) if not seeking.
@@ -1451,7 +1458,6 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
}
// streamMask now only contains the types that need a new fetcher created.
-
if (streamMask != 0) {
ALOGV("creating new fetchers for mask 0x%08x", streamMask);
}
@@ -1472,6 +1478,7 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
int64_t startTimeUs = -1;
int64_t segmentStartTimeUs = -1ll;
int32_t discontinuitySeq = -1;
+ SeekMode seekMode = kSeekModeExactPosition;
sp<AnotherPacketSource> sources[kMaxStreams];
if (i == kSubtitleIndex) {
@@ -1491,6 +1498,16 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
sp<AMessage> meta;
if (pickTrack) {
// selecting
+
+ // FIXME:
+ // This should only apply to the track that's being picked, we
+ // need a bitmask to indicate that.
+ //
+ // It's possible that selectTrack() gets called during a bandwidth
+ // switch, and we needed to fetch a new variant. The new fetcher
+ // should start from where old fetcher left off, not where decoder
+ // is dequeueing at.
+
meta = sources[j]->getLatestDequeuedMeta();
} else {
// adapting
@@ -1527,14 +1544,22 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
ALOGV("stream[%zu]: queue format change", j);
sources[j]->queueDiscontinuity(
- ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
+ ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true);
} else {
// adapting, queue discontinuities after resume
sources[j] = mPacketSources2.valueFor(indexToType(j));
sources[j]->clear();
uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
if (extraStreams & indexToType(j)) {
- sources[j]->queueAccessUnit(createFormatChangeBuffer(/*swap*/ false));
+ sources[j]->queueDiscontinuity(
+ ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true);
+ }
+ // the new fetcher might be providing streams that used to be
+ // provided by two different fetchers, if one of the fetcher
+ // paused in the middle while the other somehow paused in next
+ // seg, we have to start from next seg.
+ if (seekMode < mStreams[j].mSeekMode) {
+ seekMode = mStreams[j].mSeekMode;
}
}
}
@@ -1550,7 +1575,7 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
startTimeUs < 0 ? mLastSeekTimeUs : startTimeUs,
segmentStartTimeUs,
discontinuitySeq,
- switching);
+ seekMode);
}
// All fetchers have now been started, the configuration change
@@ -1569,25 +1594,57 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
}
}
-void LiveSession::onSwapped(const sp<AMessage> &msg) {
- int32_t switchGeneration;
- CHECK(msg->findInt32("switchGeneration", &switchGeneration));
- if (switchGeneration != mSwitchGeneration) {
+void LiveSession::swapPacketSource(StreamType stream) {
+ ALOGV("swapPacketSource: stream = %d", stream);
+
+ // transfer packets from source2 to source
+ sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
+ sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
+
+ // queue discontinuity in mPacketSource
+ aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false);
+
+ // queue packets in mPacketSource2 to mPacketSource
+ status_t finalResult = OK;
+ sp<ABuffer> accessUnit;
+ while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK &&
+ OK == aps2->dequeueAccessUnit(&accessUnit)) {
+ aps->queueAccessUnit(accessUnit);
+ }
+ aps2->clear();
+}
+
+void LiveSession::tryToFinishBandwidthSwitch(const AString &uri) {
+ if (!mSwitchInProgress) {
+ return;
+ }
+
+ ssize_t index = mFetcherInfos.indexOfKey(uri);
+ if (index < 0 || !mFetcherInfos[index].mToBeRemoved) {
return;
}
- int32_t stream;
- CHECK(msg->findInt32("stream", &stream));
+ // Swap packet source of streams provided by old variant
+ for (size_t idx = 0; idx < kMaxStreams; idx++) {
+ if (uri == mStreams[idx].mUri) {
+ StreamType stream = indexToType(idx);
- ssize_t idx = typeToIndex(stream);
- CHECK(idx >= 0);
- if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
- ALOGW("swapping stream type %d %s to empty stream", stream, mStreams[idx].mUri.c_str());
+ swapPacketSource(stream);
+
+ if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
+ ALOGW("swapping stream type %d %s to empty stream",
+ stream, mStreams[idx].mUri.c_str());
+ }
+ mStreams[idx].mUri = mStreams[idx].mNewUri;
+ mStreams[idx].mNewUri.clear();
+
+ mSwapMask &= ~stream;
+ }
}
- mStreams[idx].mUri = mStreams[idx].mNewUri;
- mStreams[idx].mNewUri.clear();
- mSwapMask &= ~stream;
+ mFetcherInfos.editValueAt(index).mToBeRemoved = false;
+
+ ALOGV("tryToFinishBandwidthSwitch: mSwapMask=%x", mSwapMask);
if (mSwapMask != 0) {
return;
}
@@ -1595,21 +1652,50 @@ void LiveSession::onSwapped(const sp<AMessage> &msg) {
// Check if new variant contains extra streams.
uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
while (extraStreams) {
- StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
- swapPacketSource(extraStream);
- extraStreams &= ~extraStream;
+ StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1));
+ extraStreams &= ~stream;
+
+ swapPacketSource(stream);
- idx = typeToIndex(extraStream);
+ ssize_t idx = typeToIndex(stream);
CHECK(idx >= 0);
if (mStreams[idx].mNewUri.empty()) {
ALOGW("swapping extra stream type %d %s to empty stream",
- extraStream, mStreams[idx].mUri.c_str());
+ stream, mStreams[idx].mUri.c_str());
}
mStreams[idx].mUri = mStreams[idx].mNewUri;
mStreams[idx].mNewUri.clear();
}
- tryToFinishBandwidthSwitch();
+ // Restart new fetcher (it was paused after the first 47k block)
+ // and let it fetch into mPacketSources (not mPacketSources2)
+ for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
+ FetcherInfo &info = mFetcherInfos.editValueAt(i);
+ if (info.mToBeResumed) {
+ const AString &uri = mFetcherInfos.keyAt(i);
+ sp<AnotherPacketSource> sources[kMaxStreams];
+ for (size_t j = 0; j < kMaxStreams; ++j) {
+ if (uri == mStreams[j].mUri) {
+ sources[j] = mPacketSources.valueFor(indexToType(j));
+ }
+ }
+ if (sources[kAudioIndex] != NULL
+ || sources[kVideoIndex] != NULL
+ || sources[kSubtitleIndex] != NULL) {
+ ALOGV("resuming fetcher %s", uri.c_str());
+ info.mFetcher->startAsync(
+ sources[kAudioIndex],
+ sources[kVideoIndex],
+ sources[kSubtitleIndex]);
+ }
+ info.mToBeResumed = false;
+ }
+ }
+
+ mStreamMask = mNewStreamMask;
+ mSwitchInProgress = false;
+
+ ALOGI("#### Finished Bandwidth Switch");
}
void LiveSession::schedulePollBuffering() {
@@ -1624,7 +1710,7 @@ void LiveSession::cancelPollBuffering() {
void LiveSession::onPollBuffering() {
ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, "
- "mInPreparationPhase %d, mCurBandwidthIndex %d, mStreamMask 0x%x",
+ "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x",
mSwitchInProgress, mReconfigurationInProgress,
mInPreparationPhase, mCurBandwidthIndex, mStreamMask);
@@ -1643,30 +1729,9 @@ void LiveSession::onPollBuffering() {
schedulePollBuffering();
}
-// Mark switch done when:
-// 1. all old buffers are swapped out
-void LiveSession::tryToFinishBandwidthSwitch() {
- if (!mSwitchInProgress) {
- return;
- }
-
- bool needToRemoveFetchers = false;
- for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
- if (mFetcherInfos.valueAt(i).mToBeRemoved) {
- needToRemoveFetchers = true;
- break;
- }
- }
-
- if (!needToRemoveFetchers && mSwapMask == 0) {
- ALOGI("mSwitchInProgress = false");
- mStreamMask = mNewStreamMask;
- mSwitchInProgress = false;
- }
-}
-
void LiveSession::cancelBandwidthSwitch() {
- Mutex::Autolock lock(mSwapMutex);
+ ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++", mSwitchGeneration);
+
mSwitchGeneration++;
mSwitchInProgress = false;
mSwapMask = 0;
@@ -1760,6 +1825,7 @@ void LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
int32_t bandwidthBps;
if (mBandwidthEstimator->estimateBandwidth(&bandwidthBps)) {
ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
+ mLastBandwidthBps = bandwidthBps;
} else {
ALOGV("no bandwidth estimate.");
return;
@@ -1778,7 +1844,7 @@ void LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
return;
}
- ALOGI("#### Initiate Bandwidth Switch: %d => %d",
+ ALOGI("#### Starting Bandwidth Switch: %zd => %zd",
mCurBandwidthIndex, bandwidthIndex);
changeConfiguration(-1, bandwidthIndex, false);
}
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index 685fefa..cbf988e 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -54,6 +54,12 @@ struct LiveSession : public AHandler {
STREAMTYPE_SUBTITLES = 1 << kSubtitleIndex,
};
+ enum SeekMode {
+ kSeekModeExactPosition = 0, // used for seeking
+ kSeekModeNextSample = 1, // used for seamless switching
+ kSeekModeNextSegment = 2, // used for seamless switching
+ };
+
LiveSession(
const sp<AMessage> &notify,
uint32_t flags,
@@ -63,6 +69,8 @@ struct LiveSession : public AHandler {
status_t getStreamFormat(StreamType stream, sp<AMessage> *format);
+ sp<HTTPBase> getHTTPDataSource();
+
void connectAsync(
const char *url,
const KeyedVector<String8, String8> *headers = NULL);
@@ -88,11 +96,6 @@ struct LiveSession : public AHandler {
kWhatPreparationFailed,
};
- // create a format-change discontinuity
- //
- // swap:
- // whether is format-change discontinuity should trigger a buffer swap
- sp<ABuffer> createFormatChangeBuffer(bool swap = true);
protected:
virtual ~LiveSession();
@@ -110,7 +113,6 @@ private:
kWhatChangeConfiguration2 = 'chC2',
kWhatChangeConfiguration3 = 'chC3',
kWhatFinishDisconnect2 = 'fin2',
- kWhatSwapped = 'swap',
kWhatPollBuffering = 'poll',
};
@@ -127,23 +129,22 @@ private:
struct FetcherInfo {
sp<PlaylistFetcher> mFetcher;
int64_t mDurationUs;
- bool mIsPrepared;
bool mToBeRemoved;
+ bool mToBeResumed;
};
struct StreamItem {
const char *mType;
AString mUri, mNewUri;
+ SeekMode mSeekMode;
size_t mCurDiscontinuitySeq;
int64_t mLastDequeuedTimeUs;
int64_t mLastSampleDurationUs;
StreamItem()
- : mType(""),
- mCurDiscontinuitySeq(0),
- mLastDequeuedTimeUs(0),
- mLastSampleDurationUs(0) {}
+ : StreamItem("") {}
StreamItem(const char *type)
: mType(type),
+ mSeekMode(kSeekModeExactPosition),
mCurDiscontinuitySeq(0),
mLastDequeuedTimeUs(0),
mLastSampleDurationUs(0) {}
@@ -169,6 +170,7 @@ private:
Vector<BandwidthItem> mBandwidthItems;
ssize_t mCurBandwidthIndex;
+ int32_t mLastBandwidthBps;
sp<BandwidthEstimator> mBandwidthEstimator;
sp<M3UParser> mPlaylist;
@@ -190,11 +192,6 @@ private:
// A second set of packet sources that buffer content for the variant we're switching to.
KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2;
- // A mutex used to serialize two sets of events:
- // * the swapping of packet sources in dequeueAccessUnit on the player thread, AND
- // * a forced bandwidth switch termination in cancelSwitch on the live looper.
- Mutex mSwapMutex;
-
int32_t mSwitchGeneration;
int32_t mSubtitleGeneration;
@@ -243,11 +240,15 @@ private:
uint32_t block_size = 0,
/* reuse DataSource if doing partial fetch */
sp<DataSource> *source = NULL,
- String8 *actualUrl = NULL);
+ String8 *actualUrl = NULL,
+ /* force connect http even when resuing DataSource */
+ bool forceConnectHTTP = false);
sp<M3UParser> fetchPlaylist(
const char *url, uint8_t *curPlaylistHash, bool *unchanged);
+ float getAbortThreshold(
+ ssize_t currentBWIndex, ssize_t targetBWIndex) const;
void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
size_t getBandwidthIndex(int32_t bandwidthBps);
int64_t latestMediaSegmentStartTimeUs();
@@ -261,12 +262,9 @@ private:
void onChangeConfiguration(const sp<AMessage> &msg);
void onChangeConfiguration2(const sp<AMessage> &msg);
void onChangeConfiguration3(const sp<AMessage> &msg);
- void onSwapped(const sp<AMessage> &msg);
- void tryToFinishBandwidthSwitch();
+ void swapPacketSource(StreamType stream);
+ void tryToFinishBandwidthSwitch(const AString &uri);
- // cancelBandwidthSwitch is atomic wrt swapPacketSource; call it to prevent packet sources
- // from being swapped out on stale discontinuities while manipulating
- // mPacketSources/mPacketSources2.
void cancelBandwidthSwitch();
void schedulePollBuffering();
@@ -279,8 +277,6 @@ private:
void postPrepared(status_t err);
- void swapPacketSource(StreamType stream);
-
DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
};
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index a447010..68f0357 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -54,6 +54,92 @@ const int64_t PlaylistFetcher::kFetcherResumeThreshold = 100000ll;
const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
const int32_t PlaylistFetcher::kNumSkipFrames = 5;
+struct PlaylistFetcher::DownloadState : public RefBase {
+ DownloadState();
+ void resetState();
+ bool hasSavedState() const;
+ void restoreState(
+ AString &uri,
+ sp<AMessage> &itemMeta,
+ sp<ABuffer> &buffer,
+ sp<ABuffer> &tsBuffer,
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist);
+ void saveState(
+ AString &uri,
+ sp<AMessage> &itemMeta,
+ sp<ABuffer> &buffer,
+ sp<ABuffer> &tsBuffer,
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist);
+
+private:
+ bool mHasSavedState;
+ AString mUri;
+ sp<AMessage> mItemMeta;
+ sp<ABuffer> mBuffer;
+ sp<ABuffer> mTsBuffer;
+ int32_t mFirstSeqNumberInPlaylist;
+ int32_t mLastSeqNumberInPlaylist;
+};
+
+PlaylistFetcher::DownloadState::DownloadState() {
+ resetState();
+}
+
+bool PlaylistFetcher::DownloadState::hasSavedState() const {
+ return mHasSavedState;
+}
+
+void PlaylistFetcher::DownloadState::resetState() {
+ mHasSavedState = false;
+
+ mUri.clear();
+ mItemMeta = NULL;
+ mBuffer = NULL;
+ mTsBuffer = NULL;
+ mFirstSeqNumberInPlaylist = 0;
+ mLastSeqNumberInPlaylist = 0;
+}
+
+void PlaylistFetcher::DownloadState::restoreState(
+ AString &uri,
+ sp<AMessage> &itemMeta,
+ sp<ABuffer> &buffer,
+ sp<ABuffer> &tsBuffer,
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist) {
+ if (!mHasSavedState) {
+ return;
+ }
+
+ uri = mUri;
+ itemMeta = mItemMeta;
+ buffer = mBuffer;
+ tsBuffer = mTsBuffer;
+ firstSeqNumberInPlaylist = mFirstSeqNumberInPlaylist;
+ lastSeqNumberInPlaylist = mLastSeqNumberInPlaylist;
+
+ resetState();
+}
+
+void PlaylistFetcher::DownloadState::saveState(
+ AString &uri,
+ sp<AMessage> &itemMeta,
+ sp<ABuffer> &buffer,
+ sp<ABuffer> &tsBuffer,
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist) {
+ mHasSavedState = true;
+
+ mUri = uri;
+ mItemMeta = itemMeta;
+ mBuffer = buffer;
+ mTsBuffer = tsBuffer;
+ mFirstSeqNumberInPlaylist = firstSeqNumberInPlaylist;
+ mLastSeqNumberInPlaylist = lastSeqNumberInPlaylist;
+}
+
PlaylistFetcher::PlaylistFetcher(
const sp<AMessage> &notify,
const sp<LiveSession> &session,
@@ -71,18 +157,21 @@ PlaylistFetcher::PlaylistFetcher(
mSeqNumber(-1),
mNumRetries(0),
mStartup(true),
- mAdaptive(false),
+ mSeekMode(LiveSession::kSeekModeExactPosition),
mPrepared(false),
mTimeChangeSignaled(false),
mNextPTSTimeUs(-1ll),
mMonitorQueueGeneration(0),
mSubtitleGeneration(subtitleGeneration),
mLastDiscontinuitySeq(-1ll),
- mStopping(false),
mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
mFirstPTSValid(false),
- mVideoBuffer(new AnotherPacketSource(NULL)) {
+ mFirstTimeUs(-1ll),
+ mVideoBuffer(new AnotherPacketSource(NULL)),
+ mThresholdRatio(-1.0f),
+ mDownloadState(new DownloadState()) {
memset(mPlaylistHash, 0, sizeof(mPlaylistHash));
+ mHTTPDataSource = mSession->getHTTPDataSource();
}
PlaylistFetcher::~PlaylistFetcher() {
@@ -334,9 +423,12 @@ void PlaylistFetcher::cancelMonitorQueue() {
++mMonitorQueueGeneration;
}
-void PlaylistFetcher::setStopping(bool stopping) {
- AutoMutex _l(mStoppingLock);
- mStopping = stopping;
+void PlaylistFetcher::setStoppingThreshold(float thresholdRatio) {
+ AutoMutex _l(mThresholdLock);
+ if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
+ return;
+ }
+ mThresholdRatio = thresholdRatio;
}
void PlaylistFetcher::startAsync(
@@ -346,7 +438,7 @@ void PlaylistFetcher::startAsync(
int64_t startTimeUs,
int64_t segmentStartTimeUs,
int32_t startDiscontinuitySeq,
- bool adaptive) {
+ LiveSession::SeekMode seekMode) {
sp<AMessage> msg = new AMessage(kWhatStart, this);
uint32_t streamTypeMask = 0ul;
@@ -370,19 +462,19 @@ void PlaylistFetcher::startAsync(
msg->setInt64("startTimeUs", startTimeUs);
msg->setInt64("segmentStartTimeUs", segmentStartTimeUs);
msg->setInt32("startDiscontinuitySeq", startDiscontinuitySeq);
- msg->setInt32("adaptive", adaptive);
+ msg->setInt32("seekMode", seekMode);
msg->post();
}
-void PlaylistFetcher::pauseAsync(bool immediate) {
- if (immediate) {
- setStopping(true);
+void PlaylistFetcher::pauseAsync(float thresholdRatio) {
+ if (thresholdRatio >= 0.0f) {
+ setStoppingThreshold(thresholdRatio);
}
(new AMessage(kWhatPause, this))->post();
}
void PlaylistFetcher::stopAsync(bool clear) {
- setStopping(true);
+ setStoppingThreshold(0.0f);
sp<AMessage> msg = new AMessage(kWhatStop, this);
msg->setInt32("clear", clear);
@@ -414,6 +506,10 @@ void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatPaused);
+ notify->setInt32("seekMode",
+ mDownloadState->hasSavedState()
+ ? LiveSession::kSeekModeNextSample
+ : LiveSession::kSeekModeNextSegment);
notify->post();
break;
}
@@ -464,6 +560,7 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) {
mStartTimeUsNotify = mNotify->dup();
mStartTimeUsNotify->setInt32("what", kWhatStartedAt);
mStartTimeUsNotify->setInt32("streamMask", 0);
+ mStartTimeUsNotify->setString("uri", mURI);
uint32_t streamTypeMask;
CHECK(msg->findInt32("streamTypeMask", (int32_t *)&streamTypeMask));
@@ -471,11 +568,11 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) {
int64_t startTimeUs;
int64_t segmentStartTimeUs;
int32_t startDiscontinuitySeq;
- int32_t adaptive;
+ int32_t seekMode;
CHECK(msg->findInt64("startTimeUs", &startTimeUs));
CHECK(msg->findInt64("segmentStartTimeUs", &segmentStartTimeUs));
CHECK(msg->findInt32("startDiscontinuitySeq", &startDiscontinuitySeq));
- CHECK(msg->findInt32("adaptive", &adaptive));
+ CHECK(msg->findInt32("seekMode", &seekMode));
if (streamTypeMask & LiveSession::STREAMTYPE_AUDIO) {
void *ptr;
@@ -510,6 +607,7 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) {
mDiscontinuitySeq = startDiscontinuitySeq;
mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
+ mSeekMode = (LiveSession::SeekMode) seekMode;
if (startTimeUs >= 0) {
mStartTimeUs = startTimeUs;
@@ -519,8 +617,8 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) {
mPrepared = false;
mIDRFound = false;
mTimeChangeSignaled = false;
- mAdaptive = adaptive;
mVideoBuffer->clear();
+ mDownloadState->resetState();
}
postMonitorQueue();
@@ -532,7 +630,7 @@ void PlaylistFetcher::onPause() {
cancelMonitorQueue();
mLastDiscontinuitySeq = mDiscontinuitySeq;
- setStopping(false);
+ setStoppingThreshold(-1.0f);
}
void PlaylistFetcher::onStop(const sp<AMessage> &msg) {
@@ -547,10 +645,11 @@ void PlaylistFetcher::onStop(const sp<AMessage> &msg) {
}
}
+ mDownloadState->resetState();
mPacketSources.clear();
mStreamTypeMask = 0;
- setStopping(false);
+ setStoppingThreshold(-1.0f);
}
// Resume until we have reached the boundary timestamps listed in `msg`; when
@@ -602,9 +701,6 @@ status_t PlaylistFetcher::onResumeUntil(const sp<AMessage> &msg) {
// Don't resume if all streams are within a resume threshold
if (stopCount == mPacketSources.size()) {
- for (size_t i = 0; i < mPacketSources.size(); i++) {
- mPacketSources.valueAt(i)->queueAccessUnit(mSession->createFormatChangeBuffer());
- }
stopAsync(/* clear = */ false);
return OK;
}
@@ -742,10 +838,74 @@ bool PlaylistFetcher::bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer) {
return buffer->size() > 0 && buffer->data()[0] == 0x47;
}
-void PlaylistFetcher::onDownloadNext() {
+bool PlaylistFetcher::shouldPauseDownload(bool startFound) {
+ if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
+ // doesn't apply to subtitles
+ return false;
+ }
+
+ // If we're switching, save state and pause after start point is found
+ if (mSeekMode != LiveSession::kSeekModeExactPosition && startFound) {
+ return true;
+ }
+
+ // Calculate threshold to abort current download
+ int32_t targetDurationSecs;
+ CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
+ int64_t targetDurationUs = targetDurationSecs * 1000000ll;
+ int64_t thresholdUs = -1;
+ {
+ AutoMutex _l(mThresholdLock);
+ thresholdUs = (mThresholdRatio < 0.0f) ?
+ -1ll : mThresholdRatio * targetDurationUs;
+ }
+
+ if (thresholdUs < 0) {
+ // never abort
+ return false;
+ } else if (thresholdUs == 0) {
+ // immediately abort
+ return true;
+ }
+
+ // now we have a positive thresholdUs, abort if remaining
+ // portion to download is over that threshold.
+ if (mSegmentFirstPTS < 0) {
+ // this means we haven't even find the first access unit,
+ // abort now as we must be very far away from the end.
+ return true;
+ }
+ int64_t lastEnqueueUs = mSegmentFirstPTS;
+ for (size_t i = 0; i < mPacketSources.size(); ++i) {
+ if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) {
+ continue;
+ }
+ sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
+ int32_t type;
+ if (meta == NULL || meta->findInt32("discontinuity", &type)) {
+ continue;
+ }
+ int64_t tmpUs;
+ CHECK(meta->findInt64("timeUs", &tmpUs));
+ if (tmpUs > lastEnqueueUs) {
+ lastEnqueueUs = tmpUs;
+ }
+ }
+ lastEnqueueUs -= mSegmentFirstPTS;
+ if (targetDurationUs - lastEnqueueUs > thresholdUs) {
+ return true;
+ }
+ return false;
+}
+
+bool PlaylistFetcher::initDownloadState(
+ AString &uri,
+ sp<AMessage> &itemMeta,
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist) {
status_t err = refreshPlaylist();
- int32_t firstSeqNumberInPlaylist = 0;
- int32_t lastSeqNumberInPlaylist = 0;
+ firstSeqNumberInPlaylist = 0;
+ lastSeqNumberInPlaylist = 0;
bool discontinuity = false;
if (mPlaylist != NULL) {
@@ -761,6 +921,8 @@ void PlaylistFetcher::onDownloadNext() {
}
}
+ mSegmentFirstPTS = -1ll;
+
if (mPlaylist != NULL && mSeqNumber < 0) {
CHECK_GE(mStartTimeUs, 0ll);
@@ -788,7 +950,7 @@ void PlaylistFetcher::onDownloadNext() {
// timestamps coming from the media container) is used to determine the position
// inside a segments.
mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs);
- if (mAdaptive) {
+ if (mSeekMode == LiveSession::kSeekModeNextSegment) {
// avoid double fetch/decode
mSeqNumber += 1;
}
@@ -838,12 +1000,12 @@ void PlaylistFetcher::onDownloadNext() {
mSeqNumber, firstSeqNumberInPlaylist,
lastSeqNumberInPlaylist, delayUs, mNumRetries);
postMonitorQueue(delayUs);
- return;
+ return false;
}
if (err != OK) {
notifyError(err);
- return;
+ return false;
}
// we've missed the boat, let's start 3 segments prior to the latest sequence
@@ -858,12 +1020,8 @@ void PlaylistFetcher::onDownloadNext() {
// but since the segments we are supposed to fetch have already rolled off
// the playlist, i.e. we have already missed the boat, we inevitably have to
// skip.
- for (size_t i = 0; i < mPacketSources.size(); i++) {
- sp<ABuffer> formatChange = mSession->createFormatChangeBuffer();
- mPacketSources.valueAt(i)->queueAccessUnit(formatChange);
- }
stopAsync(/* clear = */ false);
- return;
+ return false;
}
mSeqNumber = lastSeqNumberInPlaylist - 3;
if (mSeqNumber < firstSeqNumberInPlaylist) {
@@ -879,14 +1037,12 @@ void PlaylistFetcher::onDownloadNext() {
firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1);
notifyError(ERROR_END_OF_STREAM);
- return;
+ return false;
}
}
mNumRetries = 0;
- AString uri;
- sp<AMessage> itemMeta;
CHECK(mPlaylist->itemAt(
mSeqNumber - firstSeqNumberInPlaylist,
&uri,
@@ -909,20 +1065,6 @@ void PlaylistFetcher::onDownloadNext() {
}
mLastDiscontinuitySeq = -1;
- int64_t range_offset, range_length;
- if (!itemMeta->findInt64("range-offset", &range_offset)
- || !itemMeta->findInt64("range-length", &range_length)) {
- range_offset = 0;
- range_length = -1;
- }
-
- ALOGV("fetching segment %d from (%d .. %d)",
- mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist);
-
- ALOGV("fetching '%s'", uri.c_str());
-
- sp<DataSource> source;
- sp<ABuffer> buffer, tsBuffer;
// decrypt a junk buffer to prefetch key; since a session uses only one http connection,
// this avoids interleaved connections to the key and segment file.
{
@@ -932,7 +1074,7 @@ void PlaylistFetcher::onDownloadNext() {
true /* first */);
if (err != OK) {
notifyError(err);
- return;
+ return false;
}
}
@@ -981,13 +1123,57 @@ void PlaylistFetcher::onDownloadNext() {
}
}
+ ALOGV("fetching segment %d from (%d .. %d)",
+ mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist);
+ return true;
+}
+
+void PlaylistFetcher::onDownloadNext() {
+ AString uri;
+ sp<AMessage> itemMeta;
+ sp<ABuffer> buffer;
+ sp<ABuffer> tsBuffer;
+ int32_t firstSeqNumberInPlaylist = 0;
+ int32_t lastSeqNumberInPlaylist = 0;
+ bool connectHTTP = true;
+
+ if (mDownloadState->hasSavedState()) {
+ mDownloadState->restoreState(
+ uri,
+ itemMeta,
+ buffer,
+ tsBuffer,
+ firstSeqNumberInPlaylist,
+ lastSeqNumberInPlaylist);
+ connectHTTP = false;
+ ALOGV("resuming: '%s'", uri.c_str());
+ } else {
+ if (!initDownloadState(
+ uri,
+ itemMeta,
+ firstSeqNumberInPlaylist,
+ lastSeqNumberInPlaylist)) {
+ return;
+ }
+ ALOGV("fetching: '%s'", uri.c_str());
+ }
+
+ int64_t range_offset, range_length;
+ if (!itemMeta->findInt64("range-offset", &range_offset)
+ || !itemMeta->findInt64("range-length", &range_length)) {
+ range_offset = 0;
+ range_length = -1;
+ }
+
// block-wise download
ssize_t bytesRead;
do {
- int64_t startUs = ALooper::GetNowUs();
+ sp<DataSource> source = mHTTPDataSource;
+ int64_t startUs = ALooper::GetNowUs();
bytesRead = mSession->fetchFile(
- uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize, &source);
+ uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize,
+ &source, NULL, connectHTTP);
// add sample for bandwidth estimation (excluding subtitles)
if (bytesRead > 0
@@ -998,6 +1184,8 @@ void PlaylistFetcher::onDownloadNext() {
mSession->addBandwidthMeasurement(bytesRead, delayUs);
}
+ connectHTTP = false;
+
if (bytesRead < 0) {
status_t err = bytesRead;
ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
@@ -1022,6 +1210,8 @@ void PlaylistFetcher::onDownloadNext() {
return;
}
+ bool startUp = mStartup; // save current start up state
+
err = OK;
if (bufferStartsWithTsSyncByte(buffer)) {
// Incremental extraction is only supported for MPEG2 transport streams.
@@ -1034,7 +1224,6 @@ void PlaylistFetcher::onDownloadNext() {
tsBuffer->setRange(tsOff, tsSize);
}
tsBuffer->setRange(tsBuffer->offset(), tsBuffer->size() + bytesRead);
-
err = extractAndQueueAccessUnitsFromTs(tsBuffer);
}
@@ -1054,9 +1243,18 @@ void PlaylistFetcher::onDownloadNext() {
} else if (err != OK) {
notifyError(err);
return;
+ } else if (bytesRead != 0 &&
+ shouldPauseDownload(mStartup != startUp /* startFound */)) {
+ mDownloadState->saveState(
+ uri,
+ itemMeta,
+ buffer,
+ tsBuffer,
+ firstSeqNumberInPlaylist,
+ lastSeqNumberInPlaylist);
+ return;
}
-
- } while (bytesRead != 0 && !mStopping);
+ } while (bytesRead != 0);
if (bufferStartsWithTsSyncByte(buffer)) {
// If we don't see a stream in the program table after fetching a full ts segment
@@ -1092,7 +1290,7 @@ void PlaylistFetcher::onDownloadNext() {
return;
}
- err = OK;
+ status_t err = OK;
if (tsBuffer != NULL) {
AString method;
CHECK(buffer->meta()->findString("cipher-method", &method));
@@ -1125,11 +1323,11 @@ void PlaylistFetcher::onDownloadNext() {
}
++mSeqNumber;
-
postMonitorQueue();
}
-int32_t PlaylistFetcher::getSeqNumberWithAnchorTime(int64_t anchorTimeUs) const {
+int32_t PlaylistFetcher::getSeqNumberWithAnchorTime(
+ int64_t anchorTimeUs, int64_t targetDurationUs) const {
int32_t firstSeqNumberInPlaylist, lastSeqNumberInPlaylist;
if (mPlaylist->meta() == NULL
|| !mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist)) {
@@ -1138,7 +1336,8 @@ int32_t PlaylistFetcher::getSeqNumberWithAnchorTime(int64_t anchorTimeUs) const
lastSeqNumberInPlaylist = firstSeqNumberInPlaylist + mPlaylist->size() - 1;
int32_t index = mSeqNumber - firstSeqNumberInPlaylist - 1;
- while (index >= 0 && anchorTimeUs > mStartTimeUs) {
+ // adjust anchorTimeUs to within 1x targetDurationUs from mStartTimeUs
+ while (index >= 0 && anchorTimeUs - mStartTimeUs > targetDurationUs) {
sp<AMessage> itemMeta;
CHECK(mPlaylist->itemAt(index, NULL /* uri */, &itemMeta));
@@ -1324,6 +1523,9 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
int64_t timeUs;
CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
+ if (mSegmentFirstPTS < 0ll) {
+ mSegmentFirstPTS = timeUs;
+ }
if (mStartup) {
if (!mFirstPTSValid) {
mFirstTimeUs = timeUs;
@@ -1336,21 +1538,26 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
}
}
- if (timeUs < mStartTimeUs || (isAvc && !mIDRFound)) {
- // buffer up to the closest preceding IDR frame
- ALOGV("timeUs %" PRId64 " us < mStartTimeUs %" PRId64 " us",
- timeUs, mStartTimeUs);
+ bool seeking = mSeekMode == LiveSession::kSeekModeExactPosition;
+ bool startTimeReached =
+ seeking ? (timeUs >= mStartTimeUs)
+ : (timeUs > mStartTimeUs);
+
+ if (!startTimeReached || (isAvc && !mIDRFound)) {
+ // buffer up to the closest preceding IDR frame in the next segement,
+ // or the closest succeeding IDR frame after the exact position
if (isAvc) {
- if (IsIDR(accessUnit)) {
+ if (IsIDR(accessUnit) && (seeking || startTimeReached)) {
mVideoBuffer->clear();
mIDRFound = true;
}
- if (mIDRFound) {
+ if (mIDRFound && seeking && !startTimeReached) {
mVideoBuffer->queueAccessUnit(accessUnit);
}
}
-
- continue;
+ if (!startTimeReached || (isAvc && !mIDRFound)) {
+ continue;
+ }
}
}
@@ -1387,7 +1594,8 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
// live stream; re-adjust based on the actual timestamp extracted from the
// media segment; if we didn't move backward after the re-adjustment
// (newSeqNumber), start at least 1 segment prior.
- int32_t newSeqNumber = getSeqNumberWithAnchorTime(timeUs);
+ int32_t newSeqNumber = getSeqNumberWithAnchorTime(
+ timeUs, targetDurationUs);
if (newSeqNumber >= mSeqNumber) {
--mSeqNumber;
} else {
@@ -1395,6 +1603,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
}
mStartTimeUsNotify = mNotify->dup();
mStartTimeUsNotify->setInt32("what", kWhatStartedAt);
+ mIDRFound = false;
return -EAGAIN;
}
@@ -1413,7 +1622,11 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
if (streamMask == mStreamTypeMask) {
mStartup = false;
- mStartTimeUsNotify->post();
+ // only need to post if we're switching and searching for a
+ // start point in next segment, or next IDR
+ if (mSeekMode != LiveSession::kSeekModeExactPosition) {
+ mStartTimeUsNotify->post();
+ }
mStartTimeUsNotify.clear();
}
}
@@ -1428,7 +1641,6 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
|| !mStopParams->findInt64(key, &stopTimeUs)
|| (discontinuitySeq == mDiscontinuitySeq
&& timeUs >= stopTimeUs)) {
- packetSource->queueAccessUnit(mSession->createFormatChangeBuffer());
mStreamTypeMask &= ~stream;
mPacketSources.removeItemsAt(i);
break;
@@ -1678,7 +1890,8 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
// Duplicated logic from how we handle .ts playlists.
if (mStartup && mSegmentStartTimeUs >= 0
&& timeUs - mStartTimeUs > targetDurationUs) {
- int32_t newSeqNumber = getSeqNumberWithAnchorTime(timeUs);
+ int32_t newSeqNumber = getSeqNumberWithAnchorTime(
+ timeUs, targetDurationUs);
if (newSeqNumber >= mSeqNumber) {
--mSeqNumber;
} else {
@@ -1704,7 +1917,6 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
|| discontinuitySeq > mDiscontinuitySeq
|| !mStopParams->findInt64("timeUsAudio", &stopTimeUs)
|| (discontinuitySeq == mDiscontinuitySeq && unitTimeUs >= stopTimeUs)) {
- packetSource->queueAccessUnit(mSession->createFormatChangeBuffer());
mStreamTypeMask = 0;
mPacketSources.clear();
return ERROR_OUT_OF_RANGE;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index b82e50d..8d34cbc 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -65,9 +65,9 @@ struct PlaylistFetcher : public AHandler {
int64_t segmentStartTimeUs = -1ll, // starting position within playlist
// startTimeUs!=segmentStartTimeUs only when playlist is live
int32_t startDiscontinuitySeq = 0,
- bool adaptive = false);
+ LiveSession::SeekMode seekMode = LiveSession::kSeekModeExactPosition);
- void pauseAsync(bool immediate = false);
+ void pauseAsync(float thresholdRatio);
void stopAsync(bool clear = true);
@@ -95,6 +95,8 @@ private:
kWhatDownloadNext = 'dlnx',
};
+ struct DownloadState;
+
static const int64_t kMaxMonitorDelayUs;
static const int32_t kNumSkipFrames;
@@ -105,6 +107,7 @@ private:
sp<AMessage> mNotify;
sp<AMessage> mStartTimeUsNotify;
+ sp<HTTPBase> mHTTPDataSource;
sp<LiveSession> mSession;
AString mURI;
@@ -131,7 +134,7 @@ private:
int32_t mNumRetries;
bool mStartup;
bool mIDRFound;
- bool mAdaptive;
+ int32_t mSeekMode;
bool mPrepared;
bool mTimeChangeSignaled;
int64_t mNextPTSTimeUs;
@@ -141,9 +144,6 @@ private:
int32_t mLastDiscontinuitySeq;
- Mutex mStoppingLock;
- bool mStopping;
-
enum RefreshState {
INITIAL_MINIMUM_RELOAD_DELAY,
FIRST_UNCHANGED_RELOAD_ATTEMPT,
@@ -157,8 +157,8 @@ private:
sp<ATSParser> mTSParser;
bool mFirstPTSValid;
- uint64_t mFirstPTS;
int64_t mFirstTimeUs;
+ int64_t mSegmentFirstPTS;
sp<AnotherPacketSource> mVideoBuffer;
// Stores the initialization vector to decrypt the next block of cipher text, which can
@@ -166,6 +166,11 @@ private:
// the last block of cipher text (cipher-block chaining).
unsigned char mAESInitVec[16];
+ Mutex mThresholdLock;
+ float mThresholdRatio;
+
+ sp<DownloadState> mDownloadState;
+
// Set first to true if decrypting the first segment of a playlist segment. When
// first is true, reset the initialization vector based on the available
// information in the manifest; otherwise, use the initialization vector as
@@ -181,7 +186,8 @@ private:
void postMonitorQueue(int64_t delayUs = 0, int64_t minDelayUs = 0);
void cancelMonitorQueue();
- void setStopping(bool stopping);
+ void setStoppingThreshold(float thresholdRatio);
+ bool shouldPauseDownload(bool startFound);
int64_t delayUsToRefreshPlaylist() const;
status_t refreshPlaylist();
@@ -195,6 +201,11 @@ private:
void onStop(const sp<AMessage> &msg);
void onMonitorQueue();
void onDownloadNext();
+ bool initDownloadState(
+ AString &uri,
+ sp<AMessage> &itemMeta,
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist);
// Resume a fetcher to continue until the stopping point stored in msg.
status_t onResumeUntil(const sp<AMessage> &msg);
@@ -213,7 +224,8 @@ private:
void queueDiscontinuity(
ATSParser::DiscontinuityType type, const sp<AMessage> &extra);
- int32_t getSeqNumberWithAnchorTime(int64_t anchorTimeUs) const;
+ int32_t getSeqNumberWithAnchorTime(
+ int64_t anchorTimeUs, int64_t targetDurationUs) const;
int32_t getSeqNumberForDiscontinuity(size_t discontinuitySeq) const;
int32_t getSeqNumberForTime(int64_t timeUs) const;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 75d76dc..5c50747 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -46,6 +46,9 @@ struct ATSParser : public RefBase {
DISCONTINUITY_AUDIO_FORMAT
| DISCONTINUITY_VIDEO_FORMAT
| DISCONTINUITY_TIME,
+ DISCONTINUITY_FORMAT_ONLY =
+ DISCONTINUITY_AUDIO_FORMAT
+ | DISCONTINUITY_VIDEO_FORMAT,
};
enum Flags {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 79a9b04..9f42217 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -298,6 +298,7 @@ void AnotherPacketSource::signalEOS(status_t result) {
bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
Mutex::Autolock autoLock(mLock);
+ *finalResult = OK;
if (!mBuffers.empty()) {
return true;
}
@@ -306,6 +307,21 @@ bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
return false;
}
+bool AnotherPacketSource::hasDataBufferAvailable(status_t *finalResult) {
+ Mutex::Autolock autoLock(mLock);
+ *finalResult = OK;
+ List<sp<ABuffer> >::iterator it;
+ for (it = mBuffers.begin(); it != mBuffers.end(); it++) {
+ int32_t discontinuity;
+ if (!(*it)->meta()->findInt32("discontinuity", &discontinuity)) {
+ return true;
+ }
+ }
+
+ *finalResult = mEOSResult;
+ return false;
+}
+
int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) {
Mutex::Autolock autoLock(mLock);
return getBufferedDurationUs_l(finalResult);
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 809a858..d4fde7c 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -43,8 +43,12 @@ struct AnotherPacketSource : public MediaSource {
void clear();
+ // Returns true if we have any packets including discontinuities
bool hasBufferAvailable(status_t *finalResult);
+ // Returns true if we have packets that's not discontinuities
+ bool hasDataBufferAvailable(status_t *finalResult);
+
// Returns the difference between the last and the first queued
// presentation timestamps since the last discontinuity (if any).
int64_t getBufferedDurationUs(status_t *finalResult);
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index de841c8..9c60911 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -42,7 +42,6 @@ LOCAL_SRC_FILES:= \
api1/client2/CaptureSequencer.cpp \
api1/client2/ZslProcessor3.cpp \
api2/CameraDeviceClient.cpp \
- api_pro/ProCamera2Client.cpp \
device2/Camera2Device.cpp \
device3/Camera3Device.cpp \
device3/Camera3Stream.cpp \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 55f7a40..58512eb 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -52,7 +52,6 @@
#include "CameraService.h"
#include "api1/CameraClient.h"
#include "api1/Camera2Client.h"
-#include "api_pro/ProCamera2Client.h"
#include "api2/CameraDeviceClient.h"
#include "utils/CameraTraces.h"
#include "CameraDeviceFactory.h"
@@ -1066,16 +1065,6 @@ status_t CameraService::connectLegacy(
return NO_ERROR;
}
-status_t CameraService::connectPro(const sp<IProCameraCallbacks>& cameraCb,
- int cameraId,
- const String16& clientPackageName,
- int clientUid,
- /*out*/
- sp<IProCameraUser>& device) {
- ALOGE("%s: Unimplemented, please use connectDevice", __FUNCTION__);
- return INVALID_OPERATION;
-}
-
status_t CameraService::connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
@@ -1428,7 +1417,6 @@ status_t CameraService::onTransact(
// Permission checks
switch (code) {
case BnCameraService::CONNECT:
- case BnCameraService::CONNECT_PRO:
case BnCameraService::CONNECT_DEVICE:
case BnCameraService::CONNECT_LEGACY:
const int pid = getCallingPid();
@@ -1710,33 +1698,6 @@ void CameraService::Client::OpsCallback::opChanged(int32_t op,
}
// ----------------------------------------------------------------------------
-// IProCamera
-// ----------------------------------------------------------------------------
-
-CameraService::ProClient::ProClient(const sp<CameraService>& cameraService,
- const sp<IProCameraCallbacks>& remoteCallback,
- const String16& clientPackageName,
- int cameraId,
- int cameraFacing,
- int clientPid,
- uid_t clientUid,
- int servicePid)
- : CameraService::BasicClient(cameraService, IInterface::asBinder(remoteCallback),
- clientPackageName, cameraId, cameraFacing,
- clientPid, clientUid, servicePid)
-{
- mRemoteCallback = remoteCallback;
-}
-
-CameraService::ProClient::~ProClient() {
-}
-
-void CameraService::ProClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
- const CaptureResultExtras& resultExtras) {
- mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
-}
-
-// ----------------------------------------------------------------------------
// CameraState
// ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 53420e5..53f1c72 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -27,8 +27,6 @@
#include <camera/ICamera.h>
#include <camera/ICameraClient.h>
-#include <camera/IProCameraUser.h>
-#include <camera/IProCameraCallbacks.h>
#include <camera/camera2/ICameraDeviceUser.h>
#include <camera/camera2/ICameraDeviceCallbacks.h>
#include <camera/VendorTagDescriptor.h>
@@ -127,11 +125,6 @@ public:
/*out*/
sp<ICamera>& device);
- virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb,
- int cameraId, const String16& clientPackageName, int clientUid,
- /*out*/
- sp<IProCameraUser>& device);
-
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
@@ -195,7 +188,7 @@ public:
// virtual inheritance
virtual sp<IBinder> asBinderWrapper() = 0;
- // Return the remote callback binder object (e.g. IProCameraCallbacks)
+ // Return the remote callback binder object (e.g. ICameraDeviceCallbacks)
sp<IBinder> getRemote() {
return mRemoteBinder;
}
@@ -330,51 +323,6 @@ public:
}; // class Client
- class ProClient : public BnProCameraUser, public BasicClient {
- public:
- typedef IProCameraCallbacks TCamCallbacks;
-
- ProClient(const sp<CameraService>& cameraService,
- const sp<IProCameraCallbacks>& remoteCallback,
- const String16& clientPackageName,
- int cameraId,
- int cameraFacing,
- int clientPid,
- uid_t clientUid,
- int servicePid);
-
- virtual ~ProClient();
-
- const sp<IProCameraCallbacks>& getRemoteCallback() {
- return mRemoteCallback;
- }
-
- /***
- IProCamera implementation
- ***/
- virtual status_t connect(const sp<IProCameraCallbacks>& callbacks)
- = 0;
- virtual status_t exclusiveTryLock() = 0;
- virtual status_t exclusiveLock() = 0;
- virtual status_t exclusiveUnlock() = 0;
-
- virtual bool hasExclusiveLock() = 0;
-
- // Note that the callee gets a copy of the metadata.
- virtual int submitRequest(camera_metadata_t* metadata,
- bool streaming = false) = 0;
- virtual status_t cancelRequest(int requestId) = 0;
-
- // Callbacks from camera service
- virtual void onExclusiveLockStolen() = 0;
-
- virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
- const CaptureResultExtras& resultExtras);
- protected:
-
- sp<IProCameraCallbacks> mRemoteCallback;
- }; // class ProClient
-
typedef std::shared_ptr<resource_policy::ClientDescriptor<String8,
sp<CameraService::BasicClient>>> DescriptorPtr;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 0e2311c..8587e0e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -645,9 +645,6 @@ void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
}
}
-// TODO: refactor the code below this with IProCameraUser.
-// it's 100% copy-pasted, so lets not change it right now to make it easier.
-
void CameraDeviceClient::detachDevice() {
if (mDevice == 0) return;
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
deleted file mode 100644
index a977494..0000000
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (C) 2013 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 "ProCamera2Client"
-#define ATRACE_TAG ATRACE_TAG_CAMERA
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include <cutils/properties.h>
-#include <gui/Surface.h>
-#include <gui/Surface.h>
-
-#include "api_pro/ProCamera2Client.h"
-#include "common/CameraDeviceBase.h"
-
-namespace android {
-using namespace camera2;
-
-// Interface used by CameraService
-
-ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
- const sp<IProCameraCallbacks>& remoteCallback,
- const String16& clientPackageName,
- int cameraId,
- int cameraFacing,
- int clientPid,
- uid_t clientUid,
- int servicePid) :
- Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
- cameraId, cameraFacing, clientPid, clientUid, servicePid)
-{
- ATRACE_CALL();
- ALOGI("ProCamera %d: Opened", cameraId);
-
- mExclusiveLock = false;
-}
-
-status_t ProCamera2Client::initialize(CameraModule *module)
-{
- ATRACE_CALL();
- status_t res;
-
- res = Camera2ClientBase::initialize(module);
- if (res != OK) {
- return res;
- }
-
- String8 threadName;
- mFrameProcessor = new FrameProcessorBase(mDevice);
- threadName = String8::format("PC2-%d-FrameProc", mCameraId);
- mFrameProcessor->run(threadName.string());
-
- mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
- FRAME_PROCESSOR_LISTENER_MAX_ID,
- /*listener*/this);
-
- return OK;
-}
-
-ProCamera2Client::~ProCamera2Client() {
-}
-
-status_t ProCamera2Client::exclusiveTryLock() {
- ATRACE_CALL();
- ALOGV("%s", __FUNCTION__);
-
- Mutex::Autolock icl(mBinderSerializationLock);
- SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
-
- if (!mDevice.get()) return PERMISSION_DENIED;
-
- if (!mExclusiveLock) {
- mExclusiveLock = true;
-
- if (mRemoteCallback != NULL) {
- mRemoteCallback->onLockStatusChanged(
- IProCameraCallbacks::LOCK_ACQUIRED);
- }
-
- ALOGV("%s: exclusive lock acquired", __FUNCTION__);
-
- return OK;
- }
-
- // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
-
- // don't allow recursive locking
- ALOGW("%s: exclusive lock already exists - recursive locking is not"
- "allowed", __FUNCTION__);
-
- return ALREADY_EXISTS;
-}
-
-status_t ProCamera2Client::exclusiveLock() {
- ATRACE_CALL();
- ALOGV("%s", __FUNCTION__);
-
- Mutex::Autolock icl(mBinderSerializationLock);
- SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
-
- if (!mDevice.get()) return PERMISSION_DENIED;
-
- /**
- * TODO: this should asynchronously 'wait' until the lock becomes available
- * if another client already has an exclusive lock.
- *
- * once we have proper sharing support this will need to do
- * more than just return immediately
- */
- if (!mExclusiveLock) {
- mExclusiveLock = true;
-
- if (mRemoteCallback != NULL) {
- mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
- }
-
- ALOGV("%s: exclusive lock acquired", __FUNCTION__);
-
- return OK;
- }
-
- // don't allow recursive locking
- ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
- , __FUNCTION__);
- return ALREADY_EXISTS;
-}
-
-status_t ProCamera2Client::exclusiveUnlock() {
- ATRACE_CALL();
- ALOGV("%s", __FUNCTION__);
-
- Mutex::Autolock icl(mBinderSerializationLock);
- SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
-
- // don't allow unlocking if we have no lock
- if (!mExclusiveLock) {
- ALOGW("%s: cannot unlock, no lock was held in the first place",
- __FUNCTION__);
- return BAD_VALUE;
- }
-
- mExclusiveLock = false;
- if (mRemoteCallback != NULL ) {
- mRemoteCallback->onLockStatusChanged(
- IProCameraCallbacks::LOCK_RELEASED);
- }
- ALOGV("%s: exclusive lock released", __FUNCTION__);
-
- return OK;
-}
-
-bool ProCamera2Client::hasExclusiveLock() {
- Mutex::Autolock icl(mBinderSerializationLock);
- return mExclusiveLock;
-}
-
-void ProCamera2Client::onExclusiveLockStolen() {
- ALOGV("%s: ProClient lost exclusivity (id %d)",
- __FUNCTION__, mCameraId);
-
- Mutex::Autolock icl(mBinderSerializationLock);
- SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
-
- if (mExclusiveLock && mRemoteCallback.get() != NULL) {
- mRemoteCallback->onLockStatusChanged(
- IProCameraCallbacks::LOCK_STOLEN);
- }
-
- mExclusiveLock = false;
-
- //TODO: we should not need to detach the device, merely reset it.
- detachDevice();
-}
-
-status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
- bool streaming) {
- ATRACE_CALL();
- ALOGV("%s", __FUNCTION__);
-
- Mutex::Autolock icl(mBinderSerializationLock);
-
- if (!mDevice.get()) return DEAD_OBJECT;
-
- if (!mExclusiveLock) {
- return PERMISSION_DENIED;
- }
-
- CameraMetadata metadata(request);
-
- if (!enforceRequestPermissions(metadata)) {
- return PERMISSION_DENIED;
- }
-
- if (streaming) {
- return mDevice->setStreamingRequest(metadata);
- } else {
- return mDevice->capture(metadata);
- }
-
- // unreachable. thx gcc for a useless warning
- return OK;
-}
-
-status_t ProCamera2Client::cancelRequest(int requestId) {
- (void)requestId;
- ATRACE_CALL();
- ALOGV("%s", __FUNCTION__);
-
- Mutex::Autolock icl(mBinderSerializationLock);
-
- if (!mDevice.get()) return DEAD_OBJECT;
-
- if (!mExclusiveLock) {
- return PERMISSION_DENIED;
- }
-
- // TODO: implement
- ALOGE("%s: not fully implemented yet", __FUNCTION__);
- return INVALID_OPERATION;
-}
-
-status_t ProCamera2Client::deleteStream(int streamId) {
- ATRACE_CALL();
- ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
-
- status_t res;
- if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
-
- Mutex::Autolock icl(mBinderSerializationLock);
-
- if (!mDevice.get()) return DEAD_OBJECT;
- mDevice->clearStreamingRequest();
-
- status_t code;
- if ((code = mDevice->waitUntilDrained()) != OK) {
- ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
- }
-
- return mDevice->deleteStream(streamId);
-}
-
-status_t ProCamera2Client::createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId)
-{
- if (streamId) {
- *streamId = -1;
- }
-
- ATRACE_CALL();
- ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
-
- status_t res;
- if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
-
- Mutex::Autolock icl(mBinderSerializationLock);
-
- if (!mDevice.get()) return DEAD_OBJECT;
-
- sp<IBinder> binder;
- sp<ANativeWindow> window;
- if (bufferProducer != 0) {
- binder = IInterface::asBinder(bufferProducer);
- window = new Surface(bufferProducer);
- }
-
- return mDevice->createStream(window, width, height, format,
- HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0,
- streamId);
-}
-
-// Create a request object from a template.
-// -- Caller owns the newly allocated metadata
-status_t ProCamera2Client::createDefaultRequest(int templateId,
- /*out*/
- camera_metadata** request)
-{
- ATRACE_CALL();
- ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
-
- if (request) {
- *request = NULL;
- }
-
- status_t res;
- if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
-
- Mutex::Autolock icl(mBinderSerializationLock);
-
- if (!mDevice.get()) return DEAD_OBJECT;
-
- CameraMetadata metadata;
- if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
- *request = metadata.release();
- }
-
- return res;
-}
-
-status_t ProCamera2Client::getCameraInfo(int cameraId,
- /*out*/
- camera_metadata** info)
-{
- if (cameraId != mCameraId) {
- return INVALID_OPERATION;
- }
-
- Mutex::Autolock icl(mBinderSerializationLock);
-
- if (!mDevice.get()) return DEAD_OBJECT;
-
- CameraMetadata deviceInfo = mDevice->info();
- *info = deviceInfo.release();
-
- return OK;
-}
-
-status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
- String8 result;
- result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
- mCameraId,
- (getRemoteCallback() != NULL ?
- IInterface::asBinder(getRemoteCallback()).get() : NULL),
- mClientPid);
- result.append(" State:\n");
- write(fd, result.string(), result.size());
-
- // TODO: print dynamic/request section from most recent requests
- mFrameProcessor->dump(fd, args);
- return dumpDevice(fd, args);
-}
-
-// IProCameraUser interface
-
-void ProCamera2Client::detachDevice() {
- if (mDevice == 0) return;
-
- ALOGV("Camera %d: Stopping processors", mCameraId);
-
- mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
- FRAME_PROCESSOR_LISTENER_MAX_ID,
- /*listener*/this);
- mFrameProcessor->requestExit();
- ALOGV("Camera %d: Waiting for threads", mCameraId);
- mFrameProcessor->join();
- ALOGV("Camera %d: Disconnecting device", mCameraId);
-
- // WORKAROUND: HAL refuses to disconnect while there's streams in flight
- {
- mDevice->clearStreamingRequest();
-
- status_t code;
- if ((code = mDevice->waitUntilDrained()) != OK) {
- ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
- code);
- }
- }
-
- Camera2ClientBase::detachDevice();
-}
-
-void ProCamera2Client::onResultAvailable(const CaptureResult& result) {
- ATRACE_CALL();
- ALOGV("%s", __FUNCTION__);
-
- Mutex::Autolock icl(mBinderSerializationLock);
- SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
-
- if (mRemoteCallback != NULL) {
- CameraMetadata tmp(result.mMetadata);
- camera_metadata_t* meta = tmp.release();
- ALOGV("%s: meta = %p ", __FUNCTION__, meta);
- mRemoteCallback->onResultReceived(result.mResultExtras.requestId, meta);
- tmp.acquire(meta);
- }
-}
-
-bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {
-
- const int pid = IPCThreadState::self()->getCallingPid();
- const int selfPid = getpid();
- camera_metadata_entry_t entry;
-
- /**
- * Mixin default important security values
- * - android.led.transmit = defaulted ON
- */
- CameraMetadata staticInfo = mDevice->info();
- entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
- for(size_t i = 0; i < entry.count; ++i) {
- uint8_t led = entry.data.u8[i];
-
- switch(led) {
- case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
- uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
- if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
- metadata.update(ANDROID_LED_TRANSMIT,
- &transmitDefault, 1);
- }
- break;
- }
- }
- }
-
- // We can do anything!
- if (pid == selfPid) {
- return true;
- }
-
- /**
- * Permission check special fields in the request
- * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
- */
- entry = metadata.find(ANDROID_LED_TRANSMIT);
- if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
- String16 permissionString =
- String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
- if (!checkCallingPermission(permissionString)) {
- const int uid = IPCThreadState::self()->getCallingUid();
- ALOGE("Permission Denial: "
- "can't disable transmit LED pid=%d, uid=%d", pid, uid);
- return false;
- }
- }
-
- return true;
-}
-
-} // namespace android
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.h b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
deleted file mode 100644
index 7f5f6ac..0000000
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2013 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_SERVERS_CAMERA_PROCAMERA2CLIENT_H
-#define ANDROID_SERVERS_CAMERA_PROCAMERA2CLIENT_H
-
-#include "CameraService.h"
-#include "common/FrameProcessorBase.h"
-#include "common/Camera2ClientBase.h"
-#include "device2/Camera2Device.h"
-#include "camera/CaptureResult.h"
-
-namespace android {
-
-class IMemory;
-/**
- * Implements the binder IProCameraUser API,
- * meant for HAL2-level private API access.
- */
-class ProCamera2Client :
- public Camera2ClientBase<CameraService::ProClient>,
- public camera2::FrameProcessorBase::FilteredListener
-{
-public:
- /**
- * IProCameraUser interface (see IProCameraUser for details)
- */
- virtual status_t exclusiveTryLock();
- virtual status_t exclusiveLock();
- virtual status_t exclusiveUnlock();
-
- virtual bool hasExclusiveLock();
-
- // Note that the callee gets a copy of the metadata.
- virtual int submitRequest(camera_metadata_t* metadata,
- bool streaming = false);
- virtual status_t cancelRequest(int requestId);
-
- virtual status_t deleteStream(int streamId);
-
- virtual status_t createStream(
- int width,
- int height,
- int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId);
-
- // Create a request object from a template.
- // -- Caller owns the newly allocated metadata
- virtual status_t createDefaultRequest(int templateId,
- /*out*/
- camera_metadata** request);
-
- // Get the static metadata for the camera
- // -- Caller owns the newly allocated metadata
- virtual status_t getCameraInfo(int cameraId,
- /*out*/
- camera_metadata** info);
-
- /**
- * Interface used by CameraService
- */
-
- ProCamera2Client(const sp<CameraService>& cameraService,
- const sp<IProCameraCallbacks>& remoteCallback,
- const String16& clientPackageName,
- int cameraId,
- int cameraFacing,
- int clientPid,
- uid_t clientUid,
- int servicePid);
- virtual ~ProCamera2Client();
-
- virtual status_t initialize(CameraModule *module);
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- // Callbacks from camera service
- virtual void onExclusiveLockStolen();
-
- /**
- * Interface used by independent components of ProCamera2Client.
- */
-
-protected:
- /** FilteredListener implementation **/
- virtual void onResultAvailable(const CaptureResult& result);
-
- virtual void detachDevice();
-
-private:
- /** IProCameraUser interface-related private members */
-
- /** Preview callback related members */
- sp<camera2::FrameProcessorBase> mFrameProcessor;
- static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
- static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
-
- /** Utility members */
- bool enforceRequestPermissions(CameraMetadata& metadata);
-
- // Whether or not we have an exclusive lock on the device
- // - if no we can't modify the request queue.
- // note that creating/deleting streams we own is still OK
- bool mExclusiveLock;
-};
-
-}; // namespace android
-
-#endif
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 0415d67..c0c2314 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -337,7 +337,6 @@ void Camera2ClientBase<TClientBase>::SharedCameraCallbacks::clear() {
mRemoteCallback.clear();
}
-template class Camera2ClientBase<CameraService::ProClient>;
template class Camera2ClientBase<CameraService::Client>;
template class Camera2ClientBase<CameraDeviceClientBase>;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index eb21d55..168ea0a 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -36,7 +36,7 @@ public:
typedef typename TClientBase::TCamCallbacks TCamCallbacks;
/**
- * Base binder interface (see ICamera/IProCameraUser for details)
+ * Base binder interface (see ICamera/ICameraDeviceUser for details)
*/
virtual status_t connect(const sp<TCamCallbacks>& callbacks);
virtual void disconnect();