From 418e493e8d67924cfda652cb64965647ce6381cb Mon Sep 17 00:00:00 2001 From: Igor Murashkin Date: Thu, 21 Feb 2013 12:02:29 -0800 Subject: Camera: ProCamera - implement onResultReceived callback for metadata callbacks Change-Id: I46775402b007244bc383d6343a620eebbd492aad --- camera/IProCameraCallbacks.cpp | 25 ++++++++ camera/ProCamera.cpp | 18 ++++++ camera/tests/ProCameraTests.cpp | 128 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 159 insertions(+), 12 deletions(-) (limited to 'camera') diff --git a/camera/IProCameraCallbacks.cpp b/camera/IProCameraCallbacks.cpp index 756fba2..6cd36bf 100644 --- a/camera/IProCameraCallbacks.cpp +++ b/camera/IProCameraCallbacks.cpp @@ -28,6 +28,8 @@ #include +#include + namespace android { enum { @@ -35,8 +37,12 @@ enum { DATA_CALLBACK, DATA_CALLBACK_TIMESTAMP, LOCK_STATUS_CHANGED, + RESULT_RECEIVED, }; +void readMetadata(const Parcel& data, camera_metadata_t** out); +void writeMetadata(Parcel& data, camera_metadata_t* metadata); + class BpProCameraCallbacks: public BpInterface { public: @@ -96,6 +102,15 @@ public: remote()->transact(LOCK_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); } + + void onResultReceived(int32_t frameId, camera_metadata* result) { + ALOGV("onResultReceived"); + Parcel data, reply; + data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor()); + data.writeInt32(frameId); + writeMetadata(data, result); + remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(ProCameraCallbacks, @@ -152,6 +167,16 @@ status_t BnProCameraCallbacks::onTransact( onLockStatusChanged(newLockStatus); return NO_ERROR; } break; + case RESULT_RECEIVED: { + ALOGV("RESULT_RECEIVED"); + CHECK_INTERFACE(IProCameraCallbacks, data, reply); + int32_t frameId = data.readInt32(); + camera_metadata_t *result = NULL; + readMetadata(data, &result); + onResultReceived(frameId, result); + return NO_ERROR; + break; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp index 5ee0e4d..142c03b 100644 --- a/camera/ProCamera.cpp +++ b/camera/ProCamera.cpp @@ -33,6 +33,8 @@ #include #include +#include + namespace android { // client singleton for camera service binder interface @@ -198,6 +200,22 @@ void ProCamera::onLockStatusChanged( } } +void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) { + ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result); + + sp listener; + { + Mutex::Autolock _l(mLock); + listener = mListener; + } + if (listener != NULL) { + listener->onResultReceived(frameId, result); + } else { + free_camera_metadata(result); + } + +} + status_t ProCamera::exclusiveTryLock() { sp c = mCamera; diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp index dafa995..021fbae 100644 --- a/camera/tests/ProCameraTests.cpp +++ b/camera/tests/ProCameraTests.cpp @@ -66,8 +66,13 @@ enum ProEvent { RELEASED, STOLEN, BUFFER_RECEIVED, + RESULT_RECEIVED, }; +inline int ProEvent_Mask(ProEvent e) { + return (1 << static_cast(e)); +} + typedef Vector EventList; class ProCameraTestThread : public Thread @@ -93,6 +98,12 @@ public: class ProCameraTestListener : public ProCameraListener { public: + static const int EVENT_MASK_ALL = 0xFFFFFFFF; + + ProCameraTestListener() { + mEventMask = EVENT_MASK_ALL; + } + status_t WaitForEvent() { Mutex::Autolock cal(mConditionMutex); @@ -136,15 +147,26 @@ public: return ev; } + void SetEventMask(int eventMask) { + Mutex::Autolock al(mListenerMutex); + mEventMask = eventMask; + } + private: void QueueEvent(ProEvent ev) { + bool eventAdded = false; { Mutex::Autolock al(mListenerMutex); - mProEventList.push(ev); - } + if (ProEvent_Mask(ev) & mEventMask) { + mProEventList.push(ev); + eventAdded = true; + } + } - mListenerCondition.broadcast(); + if (eventAdded) { + mListenerCondition.broadcast(); + } } protected: @@ -184,8 +206,11 @@ protected: QueueEvent(BUFFER_RECEIVED); } - virtual void onRequestReceived( - camera_metadata* request) { + virtual void onResultReceived(int32_t frameId, + camera_metadata* request) { + dout << "Result received frameId = " << frameId + << ", requestPtr = " << (void*)request << std::endl; + QueueEvent(RESULT_RECEIVED); free_camera_metadata(request); } @@ -201,6 +226,7 @@ protected: Mutex mListenerMutex; Mutex mConditionMutex; Condition mListenerCondition; + int mEventMask; }; class ProCameraTest : public ::testing::Test { @@ -309,6 +335,10 @@ TEST_F(ProCameraTest, LockingImmediate) { 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 @@ -332,13 +362,17 @@ TEST_F(ProCameraTest, LockingAsynchronous) { 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->exclusiveLock()); - // at this point we may or may not have the lock - // we cant be sure until we get an ACQUIRED event + EXPECT_EQ(OK, mCamera->exclusiveTryLock()); + // at this point we definitely have the lock EXPECT_EQ(OK, mListener->WaitForEvent()); EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); @@ -353,7 +387,7 @@ TEST_F(ProCameraTest, LockingAsynchronous) { } // Stream directly to the screen. -TEST_F(ProCameraTest, StreamingImageSingle) { +TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) { if (HasFatalFailure()) { return; } @@ -433,7 +467,7 @@ TEST_F(ProCameraTest, StreamingImageSingle) { } // Stream directly to the screen. -TEST_F(ProCameraTest, StreamingImageDual) { +TEST_F(ProCameraTest, DISABLED_StreamingImageDual) { if (HasFatalFailure()) { return; } @@ -523,6 +557,9 @@ TEST_F(ProCameraTest, CpuConsumerSingle) { if (HasFatalFailure()) { return; } + + mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED)); + int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240, TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId)); @@ -585,6 +622,9 @@ TEST_F(ProCameraTest, CpuConsumerDual) { if (HasFatalFailure()) { return; } + + mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED)); + int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960, TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId)); @@ -596,8 +636,6 @@ TEST_F(ProCameraTest, CpuConsumerDual) { EXPECT_NE(-1, depthStreamId); EXPECT_OK(mCamera->exclusiveTryLock()); - EXPECT_EQ(OK, mListener->WaitForEvent()); - EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); /* */ /* iterate in a loop submitting requests every frame. @@ -657,6 +695,72 @@ TEST_F(ProCameraTest, CpuConsumerDual) { EXPECT_OK(mCamera->exclusiveUnlock()); } +TEST_F(ProCameraTest, ResultReceiver) { + if (HasFatalFailure()) { + return; + } + + mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED)); + //FIXME: if this is run right after the previous test we get BUFFER_RECEIVED + // need to filter out events at read time + + int streamId = -1; + EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960, + TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &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 + + uint8_t allStreams[] = { streamId }; + size_t streamCount = 1; + camera_metadata_entry_t entry; + uint32_t tag = static_cast(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()); +} + } } } -- cgit v1.1