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 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 145 insertions(+), 33 deletions(-) (limited to 'camera/IProCameraUser.cpp') 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); } -- cgit v1.1