summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu-cheng Li <wuchengli@google.com>2011-06-01 17:22:24 +0800
committerWu-cheng Li <wuchengli@google.com>2011-06-27 15:44:57 +0800
commit4ca2c7c913f8bd4ada13aca56d36045d42d1e00f (patch)
treed65d0cadafa63bd9ab2aa9e8fbb6704b27a13fbc
parentc5a57efb706ec79032fc09c43b16d11ed0876604 (diff)
downloadframeworks_av-4ca2c7c913f8bd4ada13aca56d36045d42d1e00f.zip
frameworks_av-4ca2c7c913f8bd4ada13aca56d36045d42d1e00f.tar.gz
frameworks_av-4ca2c7c913f8bd4ada13aca56d36045d42d1e00f.tar.bz2
Add framework support for camcorder zoom.
The purpose of ICameraRecordingProxy and ICameraRecordingProxyListener is to allow applications using the camera during recording. Camera service allows only one client at a time. Since camcorder application needs to own the camera to do things like zoom, the media recorder cannot access the camera directly during recording. So ICameraRecordingProxy is a proxy of ICamera, which allows the media recorder to start/stop the recording and release recording frames. ICameraRecordingProxyListener is an interface that allows the recorder to receive video frames during recording. ICameraRecordingProxy startRecording() stopRecording() releaseRecordingFrame() ICameraRecordingProxyListener dataCallbackTimestamp() The camcorder app opens the camera and starts the preview. The app passes ICamera and ICameraRecordingProxy to the media recorder by MediaRecorder::setCamera(). The recorder uses ICamera to setup the camera in MediaRecorder::start(). After setup, the recorder disconnects from camera service. The recorder calls ICameraRecordingProxy::startRecording() and passes a ICameraRecordingProxyListener to the app. The app connects back to camera service and starts the recording. The app owns the camera and can do things like zoom. The media recorder receives the video frames from the listener and releases them by ICameraRecordingProxy::releaseRecordingFrame. The recorder calls ICameraRecordingProxy::stopRecording() to stop the recording. The call sequences are as follows: 1. The app: Camera.unlock(). 2. The app: MediaRecorder.setCamera(). 3. Start recording (1) The app: MediaRecorder.start(). (2) The recorder: ICamera.unlock() and ICamera.disconnect(). (3) The recorder: ICameraRecordingProxy.startRecording(). (4) The app: ICamera.reconnect(). (5) The app: ICamera.startRecording(). 4. During recording (1) The recorder: receive frames from ICameraRecordingProxyListener.dataCallbackTimestamp() (2) The recorder: release frames by ICameraRecordingProxy.releaseRecordingFrame(). 5. Stop recording (1) The app: MediaRecorder.stop() (2) The recorder: ICameraRecordingProxy.stopRecording(). (3) The app: ICamera.stopRecording(). bug:2644213 Change-Id: I15269397defc25cbbcae16abc071c8349c123122
-rw-r--r--camera/Android.mk4
-rw-r--r--camera/Camera.cpp56
-rw-r--r--camera/ICameraRecordingProxy.cpp109
-rw-r--r--camera/ICameraRecordingProxyListener.cpp75
-rw-r--r--include/camera/Camera.h25
-rw-r--r--include/camera/ICameraRecordingProxy.h101
-rw-r--r--include/camera/ICameraRecordingProxyListener.h52
-rw-r--r--include/media/IMediaRecorder.h46
-rw-r--r--include/media/MediaRecorderBase.h4
-rw-r--r--include/media/mediarecorder.h3
-rw-r--r--include/media/stagefright/CameraSource.h34
-rw-r--r--include/media/stagefright/CameraSourceTimeLapse.h2
-rw-r--r--media/libmedia/IMediaRecorder.cpp9
-rw-r--r--media/libmedia/mediarecorder.cpp6
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp5
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.h4
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp14
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h4
-rw-r--r--media/libstagefright/CameraSource.cpp88
-rw-r--r--media/libstagefright/CameraSourceTimeLapse.cpp16
-rw-r--r--services/camera/libcameraservice/CameraService.cpp9
21 files changed, 579 insertions, 87 deletions
diff --git a/camera/Android.mk b/camera/Android.mk
index b17b3d2..dc00957 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -6,7 +6,9 @@ LOCAL_SRC_FILES:= \
CameraParameters.cpp \
ICamera.cpp \
ICameraClient.cpp \
- ICameraService.cpp
+ ICameraService.cpp \
+ ICameraRecordingProxy.cpp \
+ ICameraRecordingProxyListener.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 5eb48da..3c00db5 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -19,11 +19,12 @@
#define LOG_TAG "Camera"
#include <utils/Log.h>
#include <utils/threads.h>
-
+#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IMemory.h>
#include <camera/Camera.h>
+#include <camera/ICameraRecordingProxyListener.h>
#include <camera/ICameraService.h>
#include <surfaceflinger/Surface.h>
@@ -236,6 +237,10 @@ void Camera::stopPreview()
void Camera::stopRecording()
{
LOGV("stopRecording");
+ {
+ Mutex::Autolock _l(mLock);
+ mRecordingProxyListener.clear();
+ }
sp <ICamera> c = mCamera;
if (c == 0) return;
c->stopRecording();
@@ -327,6 +332,12 @@ void Camera::setListener(const sp<CameraListener>& listener)
mListener = listener;
}
+void Camera::setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener)
+{
+ Mutex::Autolock _l(mLock);
+ mRecordingProxyListener = listener;
+}
+
void Camera::setPreviewCallbackFlags(int flag)
{
LOGV("setPreviewCallbackFlags");
@@ -364,6 +375,19 @@ void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
// callback from camera service when timestamped frame is ready
void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
{
+ // If recording proxy listener is registered, forward the frame and return.
+ // The other listener (mListener) is ignored because the receiver needs to
+ // call releaseRecordingFrame.
+ sp<ICameraRecordingProxyListener> proxylistener;
+ {
+ Mutex::Autolock _l(mLock);
+ proxylistener = mRecordingProxyListener;
+ }
+ if (proxylistener != NULL) {
+ proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+ return;
+ }
+
sp<CameraListener> listener;
{
Mutex::Autolock _l(mLock);
@@ -389,4 +413,34 @@ void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
LOGW("Camera server died!");
}
+sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
+ LOGV("getProxy");
+ return new RecordingProxy(this);
+}
+
+status_t Camera::RecordingProxy::startRecording(const sp<ICameraRecordingProxyListener>& listener)
+{
+ LOGV("RecordingProxy::startRecording");
+ mCamera->setRecordingProxyListener(listener);
+ mCamera->reconnect();
+ return mCamera->startRecording();
+}
+
+void Camera::RecordingProxy::stopRecording()
+{
+ LOGV("RecordingProxy::stopRecording");
+ mCamera->stopRecording();
+}
+
+void Camera::RecordingProxy::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+ LOGV("RecordingProxy::releaseRecordingFrame");
+ mCamera->releaseRecordingFrame(mem);
+}
+
+Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
+{
+ mCamera = camera;
+}
+
}; // namespace android
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
new file mode 100644
index 0000000..64b6a5c
--- /dev/null
+++ b/camera/ICameraRecordingProxy.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 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 "ICameraRecordingProxy"
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <stdint.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+ START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
+ STOP_RECORDING,
+ RELEASE_RECORDING_FRAME,
+};
+
+
+class BpCameraRecordingProxy: public BpInterface<ICameraRecordingProxy>
+{
+public:
+ BpCameraRecordingProxy(const sp<IBinder>& impl)
+ : BpInterface<ICameraRecordingProxy>(impl)
+ {
+ }
+
+ status_t startRecording(const sp<ICameraRecordingProxyListener>& listener)
+ {
+ LOGV("startRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ remote()->transact(START_RECORDING, data, &reply);
+ return reply.readInt32();
+ }
+
+ void stopRecording()
+ {
+ LOGV("stopRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ remote()->transact(STOP_RECORDING, data, &reply);
+ }
+
+ void releaseRecordingFrame(const sp<IMemory>& mem)
+ {
+ LOGV("releaseRecordingFrame");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ data.writeStrongBinder(mem->asBinder());
+ remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxy, "android.hardware.ICameraRecordingProxy");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxy::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case START_RECORDING: {
+ LOGV("START_RECORDING");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ sp<ICameraRecordingProxyListener> listener =
+ interface_cast<ICameraRecordingProxyListener>(data.readStrongBinder());
+ reply->writeInt32(startRecording(listener));
+ return NO_ERROR;
+ } break;
+ case STOP_RECORDING: {
+ LOGV("STOP_RECORDING");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ stopRecording();
+ return NO_ERROR;
+ } break;
+ case RELEASE_RECORDING_FRAME: {
+ LOGV("RELEASE_RECORDING_FRAME");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+ releaseRecordingFrame(mem);
+ return NO_ERROR;
+ } break;
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
new file mode 100644
index 0000000..f8cece5
--- /dev/null
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 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 "ICameraRecordingProxyListener"
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+ DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
+{
+public:
+ BpCameraRecordingProxyListener(const sp<IBinder>& impl)
+ : BpInterface<ICameraRecordingProxyListener>(impl)
+ {
+ }
+
+ void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
+ {
+ LOGV("dataCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+ data.writeInt64(timestamp);
+ data.writeInt32(msgType);
+ data.writeStrongBinder(imageData->asBinder());
+ remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxyListener, "android.hardware.ICameraRecordingProxyListener");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxyListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case DATA_CALLBACK_TIMESTAMP: {
+ LOGV("DATA_CALLBACK_TIMESTAMP");
+ CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+ nsecs_t timestamp = data.readInt64();
+ int32_t msgType = data.readInt32();
+ sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+ dataCallbackTimestamp(timestamp, msgType, imageData);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 7106bfa..f701280 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -18,9 +18,11 @@
#define ANDROID_HARDWARE_CAMERA_H
#include <utils/Timers.h>
-#include <camera/ICameraClient.h>
#include <gui/ISurfaceTexture.h>
#include <system/camera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
namespace android {
@@ -70,7 +72,7 @@ public:
static status_t getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo);
static sp<Camera> connect(int cameraId);
- ~Camera();
+ virtual ~Camera();
void init();
status_t reconnect();
@@ -129,8 +131,11 @@ public:
status_t storeMetaDataInBuffers(bool enabled);
void setListener(const sp<CameraListener>& listener);
+ void setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
void setPreviewCallbackFlags(int preview_callback_flag);
+ sp<ICameraRecordingProxy> getRecordingProxy();
+
// ICameraClient interface
virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr);
@@ -138,6 +143,20 @@ public:
sp<ICamera> remote();
+ class RecordingProxy : public BnCameraRecordingProxy
+ {
+ public:
+ RecordingProxy(const sp<Camera>& camera);
+
+ // ICameraRecordingProxy interface
+ virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener);
+ virtual void stopRecording();
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+
+ private:
+ sp<Camera> mCamera;
+ };
+
private:
Camera();
Camera(const Camera&);
@@ -162,12 +181,12 @@ private:
status_t mStatus;
sp<CameraListener> mListener;
+ sp<ICameraRecordingProxyListener> mRecordingProxyListener;
friend class DeathNotifier;
static Mutex mLock;
static sp<ICameraService> mCameraService;
-
};
}; // namespace android
diff --git a/include/camera/ICameraRecordingProxy.h b/include/camera/ICameraRecordingProxy.h
new file mode 100644
index 0000000..2aac284
--- /dev/null
+++ b/include/camera/ICameraRecordingProxy.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 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_ICAMERA_RECORDING_PROXY_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+
+#include <binder/IInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class ICameraRecordingProxyListener;
+class IMemory;
+class Parcel;
+
+/*
+ * The purpose of ICameraRecordingProxy and ICameraRecordingProxyListener is to
+ * allow applications using the camera during recording.
+ *
+ * Camera service allows only one client at a time. Since camcorder application
+ * needs to own the camera to do things like zoom, the media recorder cannot
+ * access the camera directly during recording. So ICameraRecordingProxy is a
+ * proxy of ICamera, which allows the media recorder to start/stop the recording
+ * and release recording frames. ICameraRecordingProxyListener is an interface
+ * that allows the recorder to receive video frames during recording.
+ *
+ * ICameraRecordingProxy
+ * startRecording()
+ * stopRecording()
+ * releaseRecordingFrame()
+ *
+ * ICameraRecordingProxyListener
+ * dataCallbackTimestamp()
+
+ * The camcorder app opens the camera and starts the preview. The app passes
+ * ICamera and ICameraRecordingProxy to the media recorder by
+ * MediaRecorder::setCamera(). The recorder uses ICamera to setup the camera in
+ * MediaRecorder::start(). After setup, the recorder disconnects from camera
+ * service. The recorder calls ICameraRecordingProxy::startRecording() and
+ * passes a ICameraRecordingProxyListener to the app. The app connects back to
+ * camera service and starts the recording. The app owns the camera and can do
+ * things like zoom. The media recorder receives the video frames from the
+ * listener and releases them by ICameraRecordingProxy::releaseRecordingFrame.
+ * The recorder calls ICameraRecordingProxy::stopRecording() to stop the
+ * recording.
+ *
+ * The call sequences are as follows:
+ * 1. The app: Camera.unlock().
+ * 2. The app: MediaRecorder.setCamera().
+ * 3. Start recording
+ * (1) The app: MediaRecorder.start().
+ * (2) The recorder: ICamera.unlock() and ICamera.disconnect().
+ * (3) The recorder: ICameraRecordingProxy.startRecording().
+ * (4) The app: ICamera.reconnect().
+ * (5) The app: ICamera.startRecording().
+ * 4. During recording
+ * (1) The recorder: receive frames from ICameraRecordingProxyListener.dataCallbackTimestamp()
+ * (2) The recorder: release frames by ICameraRecordingProxy.releaseRecordingFrame().
+ * 5. Stop recording
+ * (1) The app: MediaRecorder.stop()
+ * (2) The recorder: ICameraRecordingProxy.stopRecording().
+ * (3) The app: ICamera.stopRecording().
+ */
+
+class ICameraRecordingProxy: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(CameraRecordingProxy);
+
+ virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener) = 0;
+ virtual void stopRecording() = 0;
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxy: public BnInterface<ICameraRecordingProxy>
+{
+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/ICameraRecordingProxyListener.h b/include/camera/ICameraRecordingProxyListener.h
new file mode 100644
index 0000000..b6c0624
--- /dev/null
+++ b/include/camera/ICameraRecordingProxyListener.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 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_ICAMERA_RECORDING_PROXY_LISTENER_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+
+#include <binder/IInterface.h>
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class Parcel;
+class IMemory;
+
+class ICameraRecordingProxyListener: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(CameraRecordingProxyListener);
+
+ virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+ const sp<IMemory>& data) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxyListener: public BnInterface<ICameraRecordingProxyListener>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 28be7c1..a73267d 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -24,6 +24,7 @@ namespace android {
class Surface;
class ICamera;
+class ICameraRecordingProxy;
class IMediaRecorderClient;
class IMediaRecorder: public IInterface
@@ -31,28 +32,29 @@ class IMediaRecorder: public IInterface
public:
DECLARE_META_INTERFACE(MediaRecorder);
- virtual status_t setCamera(const sp<ICamera>& camera) = 0;
- virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
- virtual status_t setVideoSource(int vs) = 0;
- virtual status_t setAudioSource(int as) = 0;
- virtual status_t setOutputFormat(int of) = 0;
- virtual status_t setVideoEncoder(int ve) = 0;
- virtual status_t setAudioEncoder(int ae) = 0;
- virtual status_t setOutputFile(const char* path) = 0;
- virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
- virtual status_t setOutputFileAuxiliary(int fd) = 0;
- virtual status_t setVideoSize(int width, int height) = 0;
- virtual status_t setVideoFrameRate(int frames_per_second) = 0;
- virtual status_t setParameters(const String8& params) = 0;
- virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
- virtual status_t prepare() = 0;
- virtual status_t getMaxAmplitude(int* max) = 0;
- virtual status_t start() = 0;
- virtual status_t stop() = 0;
- virtual status_t reset() = 0;
- virtual status_t init() = 0;
- virtual status_t close() = 0;
- virtual status_t release() = 0;
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy) = 0;
+ virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
+ virtual status_t setVideoSource(int vs) = 0;
+ virtual status_t setAudioSource(int as) = 0;
+ virtual status_t setOutputFormat(int of) = 0;
+ virtual status_t setVideoEncoder(int ve) = 0;
+ virtual status_t setAudioEncoder(int ae) = 0;
+ virtual status_t setOutputFile(const char* path) = 0;
+ virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
+ virtual status_t setOutputFileAuxiliary(int fd) = 0;
+ virtual status_t setVideoSize(int width, int height) = 0;
+ virtual status_t setVideoFrameRate(int frames_per_second) = 0;
+ virtual status_t setParameters(const String8& params) = 0;
+ virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+ virtual status_t prepare() = 0;
+ virtual status_t getMaxAmplitude(int* max) = 0;
+ virtual status_t start() = 0;
+ virtual status_t stop() = 0;
+ virtual status_t reset() = 0;
+ virtual status_t init() = 0;
+ virtual status_t close() = 0;
+ virtual status_t release() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 7e22a24..1c08969 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -24,6 +24,7 @@
namespace android {
+class ICameraRecordingProxy;
class Surface;
struct MediaRecorderBase {
@@ -38,7 +39,8 @@ struct MediaRecorderBase {
virtual status_t setVideoEncoder(video_encoder ve) = 0;
virtual status_t setVideoSize(int width, int height) = 0;
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
- virtual status_t setCamera(const sp<ICamera>& camera) = 0;
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy) = 0;
virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
virtual status_t setOutputFile(const char *path) = 0;
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 36bf34e..af12d3c 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -30,6 +30,7 @@ namespace android {
class Surface;
class IMediaRecorder;
class ICamera;
+class ICameraRecordingProxy;
typedef void (*media_completion_f)(status_t status, void *cookie);
@@ -202,7 +203,7 @@ public:
void died();
status_t initCheck();
- status_t setCamera(const sp<ICamera>& camera);
+ status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
status_t setPreviewSurface(const sp<Surface>& surface);
status_t setVideoSource(int vs);
status_t setAudioSource(int as);
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index bb25bae..80b7c1c 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -21,6 +21,7 @@
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaSource.h>
#include <camera/ICamera.h>
+#include <camera/ICameraRecordingProxyListener.h>
#include <camera/CameraParameters.h>
#include <utils/List.h>
#include <utils/RefBase.h>
@@ -68,6 +69,7 @@ public:
* @return NULL on error.
*/
static CameraSource *CreateFromCamera(const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
@@ -111,6 +113,23 @@ public:
virtual void signalBufferReturned(MediaBuffer* buffer);
protected:
+ class ProxyListener: public BnCameraRecordingProxyListener {
+ public:
+ ProxyListener(const sp<CameraSource>& source);
+ virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+ const sp<IMemory> &data);
+
+ private:
+ sp<CameraSource> mSource;
+ };
+
+ // isBinderAlive needs linkToDeath to work.
+ class DeathNotifier: public IBinder::DeathRecipient {
+ public:
+ DeathNotifier() {}
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
enum CameraFlags {
FLAGS_SET_CAMERA = 1L << 0,
FLAGS_HOT_CAMERA = 1L << 1,
@@ -123,6 +142,8 @@ protected:
status_t mInitCheck;
sp<Camera> mCamera;
+ sp<ICameraRecordingProxy> mCameraRecordingProxy;
+ sp<DeathNotifier> mDeathNotifier;
sp<Surface> mSurface;
sp<MetaData> mMeta;
@@ -132,7 +153,8 @@ protected:
bool mStarted;
int32_t mNumFramesEncoded;
- CameraSource(const sp<ICamera>& camera, int32_t cameraId,
+ CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
Size videoSize, int32_t frameRate,
const sp<Surface>& surface,
bool storeMetaDataInVideoBuffers);
@@ -172,10 +194,12 @@ private:
void releaseOneRecordingFrame(const sp<IMemory>& frame);
- status_t init(const sp<ICamera>& camera, int32_t cameraId,
- Size videoSize, int32_t frameRate,
- bool storeMetaDataInVideoBuffers);
- status_t isCameraAvailable(const sp<ICamera>& camera, int32_t cameraId);
+ status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId, Size videoSize, int32_t frameRate,
+ bool storeMetaDataInVideoBuffers);
+ status_t isCameraAvailable(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId);
status_t isCameraColorFormatSupported(const CameraParameters& params);
status_t configureCamera(CameraParameters* params,
int32_t width, int32_t height,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 0e5d534..f07ebba 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -33,6 +33,7 @@ class CameraSourceTimeLapse : public CameraSource {
public:
static CameraSourceTimeLapse *CreateFromCamera(
const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
@@ -132,6 +133,7 @@ private:
CameraSourceTimeLapse(
const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 59cd1b7..a44ef5a 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -60,12 +60,13 @@ public:
{
}
- status_t setCamera(const sp<ICamera>& camera)
+ status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
{
- LOGV("setCamera(%p)", camera.get());
+ LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeStrongBinder(camera->asBinder());
+ data.writeStrongBinder(proxy->asBinder());
remote()->transact(SET_CAMERA, data, &reply);
return reply.readInt32();
}
@@ -434,7 +435,9 @@ status_t BnMediaRecorder::onTransact(
LOGV("SET_CAMERA");
CHECK_INTERFACE(IMediaRecorder, data, reply);
sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder());
- reply->writeInt32(setCamera(camera));
+ sp<ICameraRecordingProxy> proxy =
+ interface_cast<ICameraRecordingProxy>(data.readStrongBinder());
+ reply->writeInt32(setCamera(camera, proxy));
return NO_ERROR;
} break;
default:
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 0100a17..9e4edd0 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -28,9 +28,9 @@
namespace android {
-status_t MediaRecorder::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
{
- LOGV("setCamera(%p)", camera.get());
+ LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
if(mMediaRecorder == NULL) {
LOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
@@ -40,7 +40,7 @@ status_t MediaRecorder::setCamera(const sp<ICamera>& camera)
return INVALID_OPERATION;
}
- status_t ret = mMediaRecorder->setCamera(camera);
+ status_t ret = mMediaRecorder->setCamera(camera, proxy);
if (OK != ret) {
LOGV("setCamera failed: %d", ret);
mCurrentState = MEDIA_RECORDER_ERROR;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 29cc019..115db1a 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -57,7 +57,8 @@ static bool checkPermission(const char* permissionString) {
return ok;
}
-status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy)
{
LOGV("setCamera");
Mutex::Autolock lock(mLock);
@@ -65,7 +66,7 @@ status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
LOGE("recorder is not initialized");
return NO_INIT;
}
- return mRecorder->setCamera(camera);
+ return mRecorder->setCamera(camera, proxy);
}
status_t MediaRecorderClient::setPreviewSurface(const sp<Surface>& surface)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index fded98e..bbca529 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -24,11 +24,13 @@ namespace android {
class MediaRecorderBase;
class MediaPlayerService;
+class ICameraRecordingProxy;
class MediaRecorderClient : public BnMediaRecorder
{
public:
- virtual status_t setCamera(const sp<ICamera>& camera);
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setVideoSource(int vs);
virtual status_t setAudioSource(int as);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 978571c..b003476 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -198,14 +198,20 @@ status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
return OK;
}
-status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
+status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy) {
LOGV("setCamera");
if (camera == 0) {
LOGE("camera is NULL");
return BAD_VALUE;
}
+ if (proxy == 0) {
+ LOGE("camera proxy is NULL");
+ return BAD_VALUE;
+ }
mCamera = camera;
+ mCameraProxy = proxy;
return OK;
}
@@ -1235,15 +1241,17 @@ status_t StagefrightRecorder::setupCameraSource(
videoSize.height = mVideoHeight;
if (mCaptureTimeLapse) {
mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
- mCamera, mCameraId,
+ mCamera, mCameraProxy, mCameraId,
videoSize, mFrameRate, mPreviewSurface,
mTimeBetweenTimeLapseFrameCaptureUs);
*cameraSource = mCameraSourceTimeLapse;
} else {
*cameraSource = CameraSource::CreateFromCamera(
- mCamera, mCameraId, videoSize, mFrameRate,
+ mCamera, mCameraProxy, mCameraId, videoSize, mFrameRate,
mPreviewSurface, true /*storeMetaDataInVideoBuffers*/);
}
+ mCamera.clear();
+ mCameraProxy.clear();
if (*cameraSource == NULL) {
return UNKNOWN_ERROR;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index aa67aa7..cb9c406 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -27,6 +27,7 @@
namespace android {
class Camera;
+class ICameraRecordingProxy;
class CameraSource;
class CameraSourceTimeLapse;
class MediaSourceSplitter;
@@ -48,7 +49,7 @@ struct StagefrightRecorder : public MediaRecorderBase {
virtual status_t setVideoEncoder(video_encoder ve);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
- virtual status_t setCamera(const sp<ICamera>& camera);
+ virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setOutputFile(const char *path);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
@@ -66,6 +67,7 @@ struct StagefrightRecorder : public MediaRecorderBase {
private:
sp<ICamera> mCamera;
+ sp<ICameraRecordingProxy> mCameraProxy;
sp<Surface> mPreviewSurface;
sp<IMediaRecorderClient> mListener;
sp<MediaWriter> mWriter, mWriterAux;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 61bb2a8..bdffce9 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -115,19 +115,20 @@ CameraSource *CameraSource::Create() {
size.height = -1;
sp<ICamera> camera;
- return new CameraSource(camera, 0, size, -1, NULL, false);
+ return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
}
// static
CameraSource *CameraSource::CreateFromCamera(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
const sp<Surface>& surface,
bool storeMetaDataInVideoBuffers) {
- CameraSource *source = new CameraSource(camera, cameraId,
+ CameraSource *source = new CameraSource(camera, proxy, cameraId,
videoSize, frameRate, surface,
storeMetaDataInVideoBuffers);
return source;
@@ -135,6 +136,7 @@ CameraSource *CameraSource::CreateFromCamera(
CameraSource::CameraSource(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
@@ -153,11 +155,10 @@ CameraSource::CameraSource(
mNumGlitches(0),
mGlitchDurationThresholdUs(200000),
mCollectStats(false) {
-
mVideoSize.width = -1;
mVideoSize.height = -1;
- mInitCheck = init(camera, cameraId,
+ mInitCheck = init(camera, proxy, cameraId,
videoSize, frameRate,
storeMetaDataInVideoBuffers);
}
@@ -167,24 +168,32 @@ status_t CameraSource::initCheck() const {
}
status_t CameraSource::isCameraAvailable(
- const sp<ICamera>& camera, int32_t cameraId) {
+ const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId) {
if (camera == 0) {
mCamera = Camera::connect(cameraId);
+ if (mCamera == 0) return -EBUSY;
+ // If proxy is not passed in by applications, still use the proxy of
+ // our own Camera to simplify the code.
+ mCameraRecordingProxy = mCamera->getRecordingProxy();
mCameraFlags &= ~FLAGS_HOT_CAMERA;
} else {
+ // We get the proxy from Camera, not ICamera. We need to get the proxy
+ // to the remote Camera owned by the application. Here mCamera is a
+ // local Camera object created by us. We cannot use the proxy from
+ // mCamera here.
mCamera = Camera::create(camera);
+ if (mCamera == 0) return -EBUSY;
+ mCameraRecordingProxy = proxy;
mCameraFlags |= FLAGS_HOT_CAMERA;
}
- // Is camera available?
- if (mCamera == 0) {
- LOGE("Camera connection could not be established.");
- return -EBUSY;
- }
- if (!(mCameraFlags & FLAGS_HOT_CAMERA)) {
- mCamera->lock();
- }
+ mCamera->lock();
+ mDeathNotifier = new DeathNotifier();
+ // isBinderAlive needs linkToDeath to work.
+ mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
+
return OK;
}
@@ -447,6 +456,7 @@ status_t CameraSource::checkFrameRate(
*/
status_t CameraSource::init(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
@@ -455,7 +465,8 @@ status_t CameraSource::init(
status_t err = OK;
int64_t token = IPCThreadState::self()->clearCallingIdentity();
- if ((err = isCameraAvailable(camera, cameraId)) != OK) {
+ if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
+ LOGE("Camera connection could not be established.");
return err;
}
CameraParameters params(mCamera->getParameters());
@@ -521,8 +532,14 @@ CameraSource::~CameraSource() {
}
void CameraSource::startCameraRecording() {
- CHECK_EQ(OK, mCamera->startRecording());
- CHECK(mCamera->recordingEnabled());
+ // Reset the identity to the current thread because media server owns the
+ // camera and recording is started by the applications. The applications
+ // will connect to the camera in ICameraRecordingProxy::startRecording.
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mCamera->unlock();
+ mCamera.clear();
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
}
status_t CameraSource::start(MetaData *meta) {
@@ -544,20 +561,14 @@ status_t CameraSource::start(MetaData *meta) {
mStartTimeUs = startTimeUs;
}
- // Call setListener first before calling startCameraRecording()
- // to avoid recording frames being dropped.
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- mCamera->setListener(new CameraSourceListener(this));
startCameraRecording();
- IPCThreadState::self()->restoreCallingIdentity(token);
mStarted = true;
return OK;
}
void CameraSource::stopCameraRecording() {
- mCamera->setListener(NULL);
- mCamera->stopRecording();
+ mCameraRecordingProxy->stopRecording();
}
void CameraSource::releaseCamera() {
@@ -566,9 +577,9 @@ void CameraSource::releaseCamera() {
LOGV("Camera was cold when we started, stopping preview");
mCamera->stopPreview();
}
- mCamera->unlock();
mCamera.clear();
- mCamera = 0;
+ mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
+ mCameraRecordingProxy.clear();
mCameraFlags = 0;
}
@@ -578,7 +589,6 @@ status_t CameraSource::stop() {
mStarted = false;
mFrameAvailableCondition.signal();
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
releaseQueuedFrames();
while (!mFramesBeingEncoded.empty()) {
if (NO_ERROR !=
@@ -589,7 +599,6 @@ status_t CameraSource::stop() {
}
stopCameraRecording();
releaseCamera();
- IPCThreadState::self()->restoreCallingIdentity(token);
if (mCollectStats) {
LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
@@ -607,8 +616,8 @@ status_t CameraSource::stop() {
}
void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
- if (mCamera != NULL) {
- mCamera->releaseRecordingFrame(frame);
+ if (mCameraRecordingProxy != NULL) {
+ mCameraRecordingProxy->releaseRecordingFrame(frame);
}
}
@@ -627,9 +636,7 @@ sp<MetaData> CameraSource::getFormat() {
}
void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
releaseRecordingFrame(frame);
- IPCThreadState::self()->restoreCallingIdentity(token);
}
void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
@@ -669,7 +676,11 @@ status_t CameraSource::read(
Mutex::Autolock autoLock(mLock);
while (mStarted && mFramesReceived.empty()) {
if (NO_ERROR !=
- mFrameAvailableCondition.waitRelative(mLock, 3000000000LL)) {
+ mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
+ if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+ LOGW("camera recording proxy is gone");
+ return ERROR_END_OF_STREAM;
+ }
LOGW("Timed out waiting for incoming camera video frames: %lld us",
mLastFrameTimestampUs);
}
@@ -745,4 +756,17 @@ bool CameraSource::isMetaDataStoredInVideoBuffers() const {
return mIsMetaDataStoredInVideoBuffers;
}
+CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
+ mSource = source;
+}
+
+void CameraSource::ProxyListener::dataCallbackTimestamp(
+ nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
+ mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
+}
+
+void CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
+ LOGI("Camera recording proxy died");
+}
+
} // namespace android
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index cc22574..fe78c46 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -39,6 +39,7 @@ namespace android {
// static
CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
@@ -46,7 +47,7 @@ CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
int64_t timeBetweenTimeLapseFrameCaptureUs) {
CameraSourceTimeLapse *source = new
- CameraSourceTimeLapse(camera, cameraId,
+ CameraSourceTimeLapse(camera, proxy, cameraId,
videoSize, videoFrameRate, surface,
timeBetweenTimeLapseFrameCaptureUs);
@@ -61,12 +62,13 @@ CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
CameraSourceTimeLapse::CameraSourceTimeLapse(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
int64_t timeBetweenTimeLapseFrameCaptureUs)
- : CameraSource(camera, cameraId, videoSize, videoFrameRate, surface, true),
+ : CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
mLastTimeLapseFrameRealTimestampUs(0),
@@ -315,7 +317,7 @@ void CameraSourceTimeLapse::startCameraRecording() {
pthread_attr_destroy(&attr);
} else {
LOGV("start time lapse recording using video camera");
- CHECK_EQ(OK, mCamera->startRecording());
+ CameraSource::startCameraRecording();
}
}
@@ -337,8 +339,7 @@ void CameraSourceTimeLapse::stopCameraRecording() {
// play the recording sound.
mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
} else {
- mCamera->setListener(NULL);
- mCamera->stopRecording();
+ CameraSource::stopCameraRecording();
}
if (mLastReadBufferCopy) {
mLastReadBufferCopy->release();
@@ -347,9 +348,8 @@ void CameraSourceTimeLapse::stopCameraRecording() {
}
void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
- if (!mUseStillCameraForTimeLapse &&
- mCamera != NULL) {
- mCamera->releaseRecordingFrame(frame);
+ if (!mUseStillCameraForTimeLapse) {
+ CameraSource::releaseRecordingFrame(frame);
}
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a011ae2..9b09983 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -420,6 +420,10 @@ status_t CameraService::Client::unlock() {
// allow anyone to use camera (after they lock the camera)
status_t result = checkPid();
if (result == NO_ERROR) {
+ if (mHardware->recordingEnabled()) {
+ LOGE("Not allowed to unlock camera during recording.");
+ return INVALID_OPERATION;
+ }
mClientPid = 0;
LOG1("clear mCameraClient (pid %d)", callingPid);
// we need to remove the reference to ICameraClient so that when the app
@@ -756,6 +760,11 @@ status_t CameraService::Client::takePicture(int msgType) {
status_t result = checkPidAndHardware();
if (result != NO_ERROR) return result;
+ if (mHardware->recordingEnabled()) {
+ LOGE("Cannot take picture during recording.");
+ return INVALID_OPERATION;
+ }
+
if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
(msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"