Camera: HAL1 recording batching support
Test: Angler HAL1 + batching normal recording mode
Bug: 35997432
Change-Id: If088715ccdb40163f44150c16deed62432692c07
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index bf9904c..c6c35ef 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -240,6 +240,14 @@
c->releaseRecordingFrameHandle(handle);
}
+void Camera::releaseRecordingFrameHandleBatch(
+ const std::vector<native_handle_t*> handles) {
+ ALOGV("releaseRecordingFrameHandleBatch");
+ sp <::android::hardware::ICamera> c = mCamera;
+ if (c == 0) return;
+ c->releaseRecordingFrameHandleBatch(handles);
+}
+
// get preview state
bool Camera::previewEnabled()
{
@@ -418,6 +426,37 @@
}
}
+void Camera::recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles)
+{
+ // If recording proxy listener is registered, forward the frame and return.
+ // The other listener (mListener) is ignored because the receiver needs to
+ // call releaseRecordingFrameHandle.
+ sp<ICameraRecordingProxyListener> proxylistener;
+ {
+ Mutex::Autolock _l(mLock);
+ proxylistener = mRecordingProxyListener;
+ }
+ if (proxylistener != NULL) {
+ proxylistener->recordingFrameHandleCallbackTimestampBatch(timestamps, handles);
+ return;
+ }
+
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+
+ if (listener != NULL) {
+ listener->postRecordingFrameHandleTimestampBatch(timestamps, handles);
+ } else {
+ ALOGW("No listener was set. Drop a batch of recording frames.");
+ releaseRecordingFrameHandleBatch(handles);
+ }
+}
+
sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
ALOGV("getProxy");
return new RecordingProxy(this);
@@ -448,6 +487,12 @@
mCamera->releaseRecordingFrameHandle(handle);
}
+void Camera::RecordingProxy::releaseRecordingFrameHandleBatch(
+ const std::vector<native_handle_t*>& handles) {
+ ALOGV("RecordingProxy::releaseRecordingFrameHandleBatch");
+ mCamera->releaseRecordingFrameHandleBatch(handles);
+}
+
Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
{
mCamera = camera;
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index 2bf956d..f0945c7 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -55,6 +55,7 @@
SET_VIDEO_BUFFER_MODE,
SET_VIDEO_BUFFER_TARGET,
RELEASE_RECORDING_FRAME_HANDLE,
+ RELEASE_RECORDING_FRAME_HANDLE_BATCH,
};
class BpCamera: public BpInterface<ICamera>
@@ -172,6 +173,24 @@
native_handle_delete(handle);
}
+ void releaseRecordingFrameHandleBatch(const std::vector<native_handle_t*>& handles) {
+ ALOGV("releaseRecordingFrameHandleBatch");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ uint32_t n = handles.size();
+ data.writeUint32(n);
+ for (auto& handle : handles) {
+ data.writeNativeHandle(handle);
+ }
+ remote()->transact(RELEASE_RECORDING_FRAME_HANDLE_BATCH, data, &reply);
+
+ // Close the native handle because camera received a dup copy.
+ for (auto& handle : handles) {
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ }
+ }
+
status_t setVideoBufferMode(int32_t videoBufferMode)
{
ALOGV("setVideoBufferMode: %d", videoBufferMode);
@@ -378,6 +397,19 @@
releaseRecordingFrameHandle(data.readNativeHandle());
return NO_ERROR;
} break;
+ case RELEASE_RECORDING_FRAME_HANDLE_BATCH: {
+ ALOGV("RELEASE_RECORDING_FRAME_HANDLE_BATCH");
+ CHECK_INTERFACE(ICamera, data, reply);
+ // releaseRecordingFrameHandle will be responsble to close the native handle.
+ uint32_t n = data.readUint32();
+ std::vector<native_handle_t*> handles;
+ handles.reserve(n);
+ for (uint32_t i = 0; i < n; i++) {
+ handles.push_back(data.readNativeHandle());
+ }
+ releaseRecordingFrameHandleBatch(handles);
+ return NO_ERROR;
+ } break;
case SET_VIDEO_BUFFER_MODE: {
ALOGV("SET_VIDEO_BUFFER_MODE");
CHECK_INTERFACE(ICamera, data, reply);
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 1b6fac4..7e6297c 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -32,6 +32,7 @@
DATA_CALLBACK,
DATA_CALLBACK_TIMESTAMP,
RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP,
+ RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH,
};
class BpCameraClient: public BpInterface<ICameraClient>
@@ -91,6 +92,29 @@
remote()->transact(RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP, data, &reply,
IBinder::FLAG_ONEWAY);
}
+
+ void recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles) {
+ ALOGV("recordingFrameHandleCallbackTimestampBatch");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+ uint32_t n = timestamps.size();
+ if (n != handles.size()) {
+ ALOGE("%s: size of timestamps(%zu) and handles(%zu) mismatch!",
+ __FUNCTION__, timestamps.size(), handles.size());
+ return;
+ }
+ data.writeUint32(n);
+ for (auto ts : timestamps) {
+ data.writeInt64(ts);
+ }
+ for (auto& handle : handles) {
+ data.writeNativeHandle(handle);
+ }
+ remote()->transact(RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");
@@ -154,6 +178,41 @@
recordingFrameHandleCallbackTimestamp(timestamp, handle);
return NO_ERROR;
} break;
+ case RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH: {
+ ALOGV("RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH");
+ CHECK_INTERFACE(ICameraClient, data, reply);
+ uint32_t n = 0;
+ status_t res = data.readUint32(&n);
+ if (res != OK) {
+ ALOGE("%s: Failed to read batch size: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return BAD_VALUE;
+ }
+ std::vector<nsecs_t> timestamps;
+ std::vector<native_handle_t*> handles;
+ timestamps.reserve(n);
+ handles.reserve(n);
+ for (uint32_t i = 0; i < n; i++) {
+ res = data.readInt64(×tamps[i]);
+ if (res != OK) {
+ ALOGE("%s: Failed to read timestamp[%d]: %s (%d)",
+ __FUNCTION__, i, strerror(-res), res);
+ return BAD_VALUE;
+ }
+ }
+ for (uint32_t i = 0; i < n; i++) {
+ native_handle_t* handle = data.readNativeHandle();
+ if (handle == nullptr) {
+ ALOGE("%s: Received a null native handle at handles[%d]",
+ __FUNCTION__, i);
+ return BAD_VALUE;
+ }
+ handles.push_back(handle);
+ }
+
+ // The native handle will be freed in BpCamera::releaseRecordingFrameHandleBatch.
+ recordingFrameHandleCallbackTimestampBatch(timestamps, handles);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
index c9f8b5c..bd6af75 100644
--- a/camera/ICameraRecordingProxy.cpp
+++ b/camera/ICameraRecordingProxy.cpp
@@ -32,6 +32,7 @@
STOP_RECORDING,
RELEASE_RECORDING_FRAME,
RELEASE_RECORDING_FRAME_HANDLE,
+ RELEASE_RECORDING_FRAME_HANDLE_BATCH,
};
@@ -82,6 +83,24 @@
native_handle_close(handle);
native_handle_delete(handle);
}
+
+ void releaseRecordingFrameHandleBatch(const std::vector<native_handle_t*>& handles) {
+ ALOGV("releaseRecordingFrameHandleBatch");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ uint32_t n = handles.size();
+ data.writeUint32(n);
+ for (auto& handle : handles) {
+ data.writeNativeHandle(handle);
+ }
+ remote()->transact(RELEASE_RECORDING_FRAME_HANDLE_BATCH, data, &reply);
+
+ // Close the native handle because camera received a dup copy.
+ for (auto& handle : handles) {
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ }
+ }
};
IMPLEMENT_META_INTERFACE(CameraRecordingProxy, "android.hardware.ICameraRecordingProxy");
@@ -121,6 +140,31 @@
releaseRecordingFrameHandle(data.readNativeHandle());
return NO_ERROR;
} break;
+ case RELEASE_RECORDING_FRAME_HANDLE_BATCH: {
+ ALOGV("RELEASE_RECORDING_FRAME_HANDLE_BATCH");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ uint32_t n = 0;
+ status_t res = data.readUint32(&n);
+ if (res != OK) {
+ ALOGE("%s: Failed to read batch size: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return BAD_VALUE;
+ }
+ std::vector<native_handle_t*> handles;
+ handles.reserve(n);
+ for (uint32_t i = 0; i < n; i++) {
+ native_handle_t* handle = data.readNativeHandle();
+ if (handle == nullptr) {
+ ALOGE("%s: Received a null native handle at handles[%d]",
+ __FUNCTION__, i);
+ return BAD_VALUE;
+ }
+ handles.push_back(handle);
+ }
+
+ // releaseRecordingFrameHandleBatch will be responsble to close the native handle.
+ releaseRecordingFrameHandleBatch(handles);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
index 8529d3e..c954241 100644
--- a/camera/ICameraRecordingProxyListener.cpp
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -28,6 +28,7 @@
enum {
DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP,
+ RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH
};
class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
@@ -62,6 +63,36 @@
native_handle_close(handle);
native_handle_delete(handle);
}
+
+ void recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles) {
+ ALOGV("recordingFrameHandleCallbackTimestampBatch");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+
+ uint32_t n = timestamps.size();
+ if (n != handles.size()) {
+ ALOGE("%s: size of timestamps(%zu) and handles(%zu) mismatch!",
+ __FUNCTION__, timestamps.size(), handles.size());
+ return;
+ }
+ data.writeUint32(n);
+ for (auto ts : timestamps) {
+ data.writeInt64(ts);
+ }
+ for (auto& handle : handles) {
+ data.writeNativeHandle(handle);
+ }
+ remote()->transact(RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH, data, &reply,
+ IBinder::FLAG_ONEWAY);
+
+ // The native handle is dupped in ICameraClient so we need to free it here.
+ for (auto& handle : handles) {
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ }
+ }
};
IMPLEMENT_META_INTERFACE(CameraRecordingProxyListener, "android.hardware.ICameraRecordingProxyListener");
@@ -101,6 +132,41 @@
recordingFrameHandleCallbackTimestamp(timestamp, handle);
return NO_ERROR;
} break;
+ case RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH: {
+ ALOGV("RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP_BATCH");
+ CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+ uint32_t n = 0;
+ status_t res = data.readUint32(&n);
+ if (res != OK) {
+ ALOGE("%s: Failed to read batch size: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return BAD_VALUE;
+ }
+ std::vector<nsecs_t> timestamps;
+ std::vector<native_handle_t*> handles;
+ timestamps.reserve(n);
+ handles.reserve(n);
+ for (uint32_t i = 0; i < n; i++) {
+ res = data.readInt64(×tamps[i]);
+ if (res != OK) {
+ ALOGE("%s: Failed to read timestamp[%d]: %s (%d)",
+ __FUNCTION__, i, strerror(-res), res);
+ return BAD_VALUE;
+ }
+ }
+ for (uint32_t i = 0; i < n; i++) {
+ native_handle_t* handle = data.readNativeHandle();
+ if (handle == nullptr) {
+ ALOGE("%s: Received a null native handle at handles[%d]",
+ __FUNCTION__, i);
+ return BAD_VALUE;
+ }
+ handles.push_back(handle);
+ }
+ // The native handle will be freed in
+ // BpCameraRecordingProxy::releaseRecordingFrameHandleBatch.
+ recordingFrameHandleCallbackTimestampBatch(timestamps, handles);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/include/camera/Camera.h b/camera/include/camera/Camera.h
index 57dc228..430aa1c 100644
--- a/camera/include/camera/Camera.h
+++ b/camera/include/camera/Camera.h
@@ -44,6 +44,9 @@
camera_frame_metadata_t *metadata) = 0;
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0;
virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle) = 0;
+ virtual void postRecordingFrameHandleTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles) = 0;
};
class Camera;
@@ -118,6 +121,10 @@
// release a recording frame handle
void releaseRecordingFrameHandle(native_handle_t *handle);
+ // release a batch of recording frame handles
+ void releaseRecordingFrameHandleBatch(
+ const std::vector<native_handle_t*> handles);
+
// autoFocus - status returned from callback
status_t autoFocus();
@@ -166,6 +173,10 @@
camera_frame_metadata_t *metadata);
virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
virtual void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle);
+ virtual void recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles);
+
class RecordingProxy : public BnCameraRecordingProxy
{
@@ -177,6 +188,8 @@
virtual void stopRecording();
virtual void releaseRecordingFrame(const sp<IMemory>& mem);
virtual void releaseRecordingFrameHandle(native_handle_t* handle);
+ virtual void releaseRecordingFrameHandleBatch(
+ const std::vector<native_handle_t*>& handles);
private:
sp<Camera> mCamera;
diff --git a/camera/include/camera/ICameraRecordingProxy.h b/camera/include/camera/ICameraRecordingProxy.h
index cb6824a..02af2f3 100644
--- a/camera/include/camera/ICameraRecordingProxy.h
+++ b/camera/include/camera/ICameraRecordingProxy.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+#include <vector>
#include <binder/IInterface.h>
#include <cutils/native_handle.h>
#include <utils/RefBase.h>
@@ -85,6 +86,8 @@
virtual void stopRecording() = 0;
virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
virtual void releaseRecordingFrameHandle(native_handle_t *handle) = 0;
+ virtual void releaseRecordingFrameHandleBatch(
+ const std::vector<native_handle_t*>& handles) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/camera/include/camera/ICameraRecordingProxyListener.h b/camera/include/camera/ICameraRecordingProxyListener.h
index 1fee5b9..da03c56 100644
--- a/camera/include/camera/ICameraRecordingProxyListener.h
+++ b/camera/include/camera/ICameraRecordingProxyListener.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+#include <vector>
#include <binder/IInterface.h>
#include <cutils/native_handle.h>
#include <stdint.h>
@@ -38,6 +39,10 @@
virtual void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp,
native_handle_t* handle) = 0;
+
+ virtual void recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/camera/include/camera/android/hardware/ICamera.h b/camera/include/camera/android/hardware/ICamera.h
index 315669e..80823d6 100644
--- a/camera/include/camera/android/hardware/ICamera.h
+++ b/camera/include/camera/android/hardware/ICamera.h
@@ -101,6 +101,11 @@
// ICameraClient::recordingFrameHandleCallbackTimestamp.
virtual void releaseRecordingFrameHandle(native_handle_t *handle) = 0;
+ // Release a batch of recording frame handles that was received via
+ // ICameraClient::recordingFrameHandleCallbackTimestampBatch
+ virtual void releaseRecordingFrameHandleBatch(
+ const std::vector<native_handle_t*>& handles) = 0;
+
// auto focus
virtual status_t autoFocus() = 0;
diff --git a/camera/include/camera/android/hardware/ICameraClient.h b/camera/include/camera/android/hardware/ICameraClient.h
index f6ee311..8e46d17 100644
--- a/camera/include/camera/android/hardware/ICameraClient.h
+++ b/camera/include/camera/android/hardware/ICameraClient.h
@@ -41,6 +41,13 @@
// ICamera::releaseRecordingFrameHandle to release the frame handle.
virtual void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp,
native_handle_t* handle) = 0;
+
+ // Invoked to send a batch of recording frame handles with timestamp. Call
+ // ICamera::releaseRecordingFrameHandleBatch to release the frame handles.
+ // Size of timestamps and handles must match
+ virtual void recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/camera/tests/CameraZSLTests.cpp b/camera/tests/CameraZSLTests.cpp
index 6c91fdc..ecca354 100644
--- a/camera/tests/CameraZSLTests.cpp
+++ b/camera/tests/CameraZSLTests.cpp
@@ -51,6 +51,9 @@
const sp<IMemory>&) override {};
void recordingFrameHandleCallbackTimestamp(nsecs_t,
native_handle_t*) override {};
+ void recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t>&,
+ const std::vector<native_handle_t*>&) override {};
status_t waitForPreviewStart();
status_t waitForEvent(Mutex &mutex, Condition &condition, bool &flag);