From 985fd30a10f6fec4293f071fd258c4726cff5a3d Mon Sep 17 00:00:00 2001 From: Igor Murashkin Date: Wed, 20 Feb 2013 18:24:43 -0800 Subject: Camera: ProCamera2Client - add createStream (service is stubbed) and unit test Change-Id: I1ae7ba9b24f5883c214c19a7ed0eaf0c802d69c1 --- camera/IProCameraUser.cpp | 178 ++++++++++++++++++++++++++++++++-------- camera/ProCamera.cpp | 25 +++--- camera/tests/ProCameraTests.cpp | 20 +++-- 3 files changed, 169 insertions(+), 54 deletions(-) (limited to 'camera') diff --git a/camera/IProCameraUser.cpp b/camera/IProCameraUser.cpp index 76c2dcd..cd7bf5c 100644 --- a/camera/IProCameraUser.cpp +++ b/camera/IProCameraUser.cpp @@ -42,8 +42,78 @@ enum { CANCEL_REQUEST, REQUEST_STREAM, CANCEL_STREAM, + CREATE_STREAM, + CREATE_DEFAULT_REQUEST, }; +/** + * Caller becomes the owner of the new metadata + * 'const Parcel' doesnt prevent us from calling the read functions. + * which is interesting since it changes the internal state + */ +void readMetadata(const Parcel& data, camera_metadata_t** out) { + camera_metadata_t* metadata; + + // arg0 = metadataSize (int32) + size_t metadataSize = static_cast(data.readInt32()); + + if (metadataSize == 0) { + if (out) { + *out = NULL; + } + return; + } + + // NOTE: this doesn't make sense to me. shouldnt the blob + // know how big it is? why do we have to specify the size + // to Parcel::readBlob ? + + ReadableBlob blob; + // arg1 = metadata (blob) + { + data.readBlob(metadataSize, &blob); + const camera_metadata_t* tmp = + reinterpret_cast(blob.data()); + size_t entry_capacity = get_camera_metadata_entry_capacity(tmp); + size_t data_capacity = get_camera_metadata_data_capacity(tmp); + + metadata = allocate_camera_metadata(entry_capacity, data_capacity); + copy_camera_metadata(metadata, metadataSize, tmp); + } + blob.release(); + + if (out) { + *out = metadata; + } else { + free_camera_metadata(metadata); + } +} + +/** + * Caller retains ownership of metadata + * - Write 2 (int32 + blob) args in the current position + */ +void writeMetadata(Parcel& data, camera_metadata_t* metadata) { + // arg0 = metadataSize (int32) + size_t metadataSize; + + if (metadata == NULL) { + data.writeInt32(0); + return; + } + + metadataSize = get_camera_metadata_compact_size(metadata); + data.writeInt32(static_cast(metadataSize)); + + // arg1 = metadata (blob) + WritableBlob blob; + { + data.writeBlob(metadataSize, &blob); + copy_camera_metadata(blob.data(), metadataSize, metadata); + } + blob.release(); +} + class BpProCameraUser: public BpInterface { public: @@ -109,17 +179,8 @@ public: Parcel data, reply; data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); - // arg0 = metadataSize (int32) - size_t metadataSize = get_camera_metadata_compact_size(metadata); - data.writeInt32(static_cast(metadataSize)); - - // arg1 = metadata (blob) - WritableBlob blob; - { - data.writeBlob(metadataSize, &blob); - copy_camera_metadata(blob.data(), metadataSize, metadata); - } - blob.release(); + // arg0+arg1 + writeMetadata(data, metadata); // arg2 = streaming (bool) data.writeInt32(streaming); @@ -157,6 +218,44 @@ public: return reply.readInt32(); } + virtual status_t createStream(int width, int height, int format, + const sp& surface, + /*out*/ + int* streamId) + { + Parcel data, reply; + data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); + data.writeInt32(width); + data.writeInt32(height); + data.writeInt32(format); + + Surface::writeToParcel(surface, &data); + 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); + readMetadata(reply, /*out*/request); + return reply.readInt32(); + } + + +private: + + }; IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser"); @@ -205,28 +304,7 @@ status_t BnProCameraUser::onTransact( case SUBMIT_REQUEST: { CHECK_INTERFACE(IProCameraUser, data, reply); camera_metadata_t* metadata; - - // arg0 = metadataSize (int32) - size_t metadataSize = static_cast(data.readInt32()); - - // NOTE: this doesn't make sense to me. shouldnt the blob - // know how big it is? why do we have to specify the size - // to Parcel::readBlob ? - - ReadableBlob blob; - // arg1 = metadata (blob) - { - data.readBlob(metadataSize, &blob); - const camera_metadata_t* tmp = - reinterpret_cast(blob.data()); - size_t entry_capacity = get_camera_metadata_entry_capacity(tmp); - size_t data_capacity = get_camera_metadata_data_capacity(tmp); - - metadata = allocate_camera_metadata(entry_capacity, - data_capacity); - copy_camera_metadata(metadata, metadataSize, tmp); - } - blob.release(); + readMetadata(data, /*out*/&metadata); // arg2 = streaming (bool) bool streaming = data.readInt32(); @@ -254,6 +332,40 @@ status_t BnProCameraUser::onTransact( reply->writeInt32(cancelStream(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 surface = Surface::readFromParcel(data); + + int streamId = -1; + status_t ret; + ret = createStream(width, height, format, surface, &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); + + writeMetadata(*reply, request); + reply->writeInt32(ret); + + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp index 26e4de9..92ec9d6 100644 --- a/camera/ProCamera.cpp +++ b/camera/ProCamera.cpp @@ -262,7 +262,7 @@ status_t ProCamera::cancelStream(int streamId) } status_t ProCamera::createStream(int width, int height, int format, - const sp& window, + const sp& surface, /*out*/ int* streamId) { @@ -271,12 +271,14 @@ status_t ProCamera::createStream(int width, int height, int format, ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, format); - if (window == 0) { + if (surface == 0) { return BAD_VALUE; } - // TODO: actually implement this in IProCamera - return INVALID_OPERATION; + sp c = mCamera; + if (c == 0) return NO_INIT; + + return c->createStream(width, height, format, surface, streamId); } status_t ProCamera::createStream(int width, int height, int format, @@ -288,13 +290,10 @@ status_t ProCamera::createStream(int width, int height, int format, format); sp binder; - sp window; + status_t stat = INVALID_OPERATION; if (bufferProducer != 0) { binder = bufferProducer->asBinder(); - window = new Surface(bufferProducer); - - status_t stat = createStream(width, height, format, window, streamId); ALOGV("%s: createStreamT END (%d), StreamID = %d", __FUNCTION__, stat, *streamId); @@ -304,7 +303,7 @@ status_t ProCamera::createStream(int width, int height, int format, return BAD_VALUE; } - return BAD_VALUE; + return stat; } int ProCamera::getNumberOfCameras() { @@ -321,12 +320,12 @@ camera_metadata* ProCamera::getCameraInfo(int cameraId) { status_t ProCamera::createDefaultRequest(int templateId, camera_metadata** request) const { - ALOGE("%s: not implemented yet", __FUNCTION__); - ALOGV("%s: templateId = %d", __FUNCTION__, templateId); - *request = NULL; - return INVALID_OPERATION; + sp c = mCamera; + if (c == 0) return NO_INIT; + + return c->createDefaultRequest(templateId, request); } }; // namespace android diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp index d632b7e..230e160 100644 --- a/camera/tests/ProCameraTests.cpp +++ b/camera/tests/ProCameraTests.cpp @@ -317,14 +317,12 @@ TEST_F(ProCameraTest, StreamingImage) { } sp surface; - sp window; if (mDisplaySecs > 0) { createOnScreenSurface(/*out*/surface); - window = surface; } int streamId = -1; EXPECT_OK(mCamera->createStream(/*width*/640, /*height*/480, TEST_FORMAT, - window, &streamId)); + surface, &streamId)); EXPECT_NE(-1, streamId); EXPECT_OK(mCamera->exclusiveTryLock()); @@ -351,8 +349,16 @@ TEST_F(ProCameraTest, StreamingImage) { uint32_t tag = static_cast(ANDROID_REQUEST_OUTPUT_STREAMS); int find = find_camera_metadata_entry(request, tag, &entry); if (find == -ENOENT) { - ASSERT_OK(add_camera_metadata_entry(request, tag, &streamId, - /*data_count*/1)); + if (add_camera_metadata_entry(request, tag, &streamId, /*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, &streamId, + /*data_count*/1)); + } } else { ASSERT_OK(update_camera_metadata_entry(request, entry.index, &streamId, /*data_count*/1, &entry)); @@ -360,10 +366,8 @@ TEST_F(ProCameraTest, StreamingImage) { EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true)); + dout << "will sleep now for " << mDisplaySecs << std::endl; sleep(mDisplaySecs); - //should the window be empty until the buffer is flipped? - // that would certainly make sense - free_camera_metadata(request); EXPECT_OK(mCamera->cancelStream(streamId)); -- cgit v1.1