2 * Copyright (C) 2012 Mozilla Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <binder/IPCThreadState.h>
18 #include <sys/system_properties.h>
20 #include "base/basictypes.h"
22 #include "GonkCameraControl.h"
23 #include "GonkCameraHwMgr.h"
24 #include "GonkNativeWindow.h"
25 #include "CameraCommon.h"
27 using namespace mozilla
;
28 using namespace mozilla::layers
;
29 using namespace android
;
31 #if GIHM_TIMING_RECEIVEFRAME
32 #define INCLUDE_TIME_H 1
34 #if GIHM_TIMING_OVERALL
35 #define INCLUDE_TIME_H 1
41 static __inline
void timespecSubtract(struct timespec
* a
, struct timespec
* b
)
44 if (b
->tv_nsec
< a
->tv_nsec
) {
45 b
->tv_nsec
+= 1000000000;
48 a
->tv_nsec
= b
->tv_nsec
- a
->tv_nsec
;
49 a
->tv_sec
= b
->tv_sec
- a
->tv_sec
;
53 GonkCameraHardware::GonkCameraHardware(mozilla::nsGonkCameraControl
* aTarget
, uint32_t aCameraId
, const sp
<Camera
>& aCamera
)
54 : mCameraId(aCameraId
)
56 , mMonitor("GonkCameraHardware.Monitor")
61 , mSensorOrientation(0)
63 DOM_CAMERA_LOGT( "%s:%d : this=%p (aTarget=%p)\n", __func__
, __LINE__
, (void*)this, (void*)aTarget
);
68 GonkCameraHardware::OnNewFrame()
73 nsRefPtr
<GraphicBufferLocked
> buffer
= mNativeWindow
->getCurrentBuffer();
75 DOM_CAMERA_LOGW("received null frame");
78 ReceiveFrame(mTarget
, buffer
);
81 // Android data callback
83 GonkCameraHardware::postData(int32_t aMsgType
, const sp
<IMemory
>& aDataPtr
, camera_frame_metadata_t
* metadata
)
90 case CAMERA_MSG_PREVIEW_FRAME
:
94 case CAMERA_MSG_COMPRESSED_IMAGE
:
95 if (aDataPtr
!= nullptr) {
96 ReceiveImage(mTarget
, (uint8_t*)aDataPtr
->pointer(), aDataPtr
->size());
98 ReceiveImageError(mTarget
);
103 DOM_CAMERA_LOGE("Unhandled data callback event %d\n", aMsgType
);
108 // Android notify callback
110 GonkCameraHardware::notify(int32_t aMsgType
, int32_t ext1
, int32_t ext2
)
118 case CAMERA_MSG_FOCUS
:
120 DOM_CAMERA_LOGI("Autofocus complete");
123 DOM_CAMERA_LOGW("Autofocus failed");
126 AutoFocusComplete(mTarget
, bSuccess
);
129 case CAMERA_MSG_SHUTTER
:
134 DOM_CAMERA_LOGE("Unhandled notify callback event %d\n", aMsgType
);
140 GonkCameraHardware::postDataTimestamp(nsecs_t aTimestamp
, int32_t aMsgType
, const sp
<IMemory
>& aDataPtr
)
142 DOM_CAMERA_LOGI("%s",__func__
);
147 if (mListener
.get()) {
148 DOM_CAMERA_LOGI("Listener registered, posting recording frame!");
149 mListener
->postDataTimestamp(aTimestamp
, aMsgType
, aDataPtr
);
151 DOM_CAMERA_LOGW("No listener was set. Drop a recording frame.");
152 mCamera
->releaseRecordingFrame(aDataPtr
);
157 GonkCameraHardware::Init()
159 DOM_CAMERA_LOGT("%s: this=%p\n", __func__
, (void* )this);
162 int rv
= Camera::getCameraInfo(mCameraId
, &info
);
164 DOM_CAMERA_LOGE("%s: failed to get CameraInfo mCameraId %d\n", __func__
, mCameraId
);
168 mRawSensorOrientation
= info
.orientation
;
169 mSensorOrientation
= mRawSensorOrientation
;
172 * Non-V4L2-based camera driver adds extra offset onto picture orientation
173 * set by gecko, so we have to adjust it back.
175 char propname
[PROP_NAME_MAX
];
176 char prop
[PROP_VALUE_MAX
];
178 snprintf(propname
, sizeof(propname
), "ro.moz.cam.%d.sensor_offset", mCameraId
);
179 if (__system_property_get(propname
, prop
) > 0) {
180 offset
= clamped(atoi(prop
), 0, 270);
181 mSensorOrientation
+= offset
;
182 mSensorOrientation
%= 360;
184 DOM_CAMERA_LOGI("Sensor orientation: base=%d, offset=%d, final=%d\n", info
.orientation
, offset
, mSensorOrientation
);
186 // Disable shutter sound in android CameraService because gaia camera app will play it
187 mCamera
->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND
, 0, 0);
189 mNativeWindow
= new GonkNativeWindow();
190 mNativeWindow
->setNewFrameCallback(this);
191 mCamera
->setListener(this);
192 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
193 mCamera
->setPreviewTexture(mNativeWindow
->getBufferQueue());
195 mCamera
->setPreviewTexture(mNativeWindow
);
200 sp
<GonkCameraHardware
>
201 GonkCameraHardware::Connect(mozilla::nsGonkCameraControl
* aTarget
, uint32_t aCameraId
)
203 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
204 sp
<Camera
> camera
= Camera::connect(aCameraId
, /* clientPackageName */String16("gonk.camera"), Camera::USE_CALLING_UID
);
206 sp
<Camera
> camera
= Camera::connect(aCameraId
);
210 if (camera
.get() == nullptr) {
213 sp
<GonkCameraHardware
> cameraHardware
= new GonkCameraHardware(aTarget
, aCameraId
, camera
);
214 return cameraHardware
;
218 GonkCameraHardware::Close()
220 DOM_CAMERA_LOGT( "%s:%d : this=%p\n", __func__
, __LINE__
, (void*)this );
223 mCamera
->stopPreview();
224 mCamera
->disconnect();
225 if (mNativeWindow
.get()) {
226 mNativeWindow
->abandon();
229 mNativeWindow
.clear();
231 // Ensure that ICamera's destructor is actually executed
232 IPCThreadState::self()->flushCommands();
235 GonkCameraHardware::~GonkCameraHardware()
237 DOM_CAMERA_LOGT( "%s:%d : this=%p\n", __func__
, __LINE__
, (void*)this );
239 mNativeWindow
.clear();
246 * Trigger the OnClosed event; the upper layers can't do anything
247 * with the hardware layer once they receive this event.
255 GonkCameraHardware::GetSensorOrientation(uint32_t aType
)
257 DOM_CAMERA_LOGI("%s\n", __func__
);
260 case OFFSET_SENSOR_ORIENTATION
:
261 return mSensorOrientation
;
263 case RAW_SENSOR_ORIENTATION
:
264 return mRawSensorOrientation
;
267 DOM_CAMERA_LOGE("%s:%d : unknown aType=%d\n", __func__
, __LINE__
, aType
);
273 GonkCameraHardware::AutoFocus()
275 DOM_CAMERA_LOGI("%s\n", __func__
);
276 return mCamera
->autoFocus();
280 GonkCameraHardware::CancelAutoFocus()
282 DOM_CAMERA_LOGI("%s\n", __func__
);
283 mCamera
->cancelAutoFocus();
287 GonkCameraHardware::TakePicture()
289 return mCamera
->takePicture(CAMERA_MSG_SHUTTER
| CAMERA_MSG_COMPRESSED_IMAGE
);
293 GonkCameraHardware::CancelTakePicture()
295 DOM_CAMERA_LOGW("%s: android::Camera do not provide this capability\n", __func__
);
299 GonkCameraHardware::PushParameters(const CameraParameters
& aParams
)
301 String8 s
= aParams
.flatten();
302 return mCamera
->setParameters(s
);
306 GonkCameraHardware::PullParameters(CameraParameters
& aParams
)
308 const String8 s
= mCamera
->getParameters();
309 aParams
.unflatten(s
);
313 GonkCameraHardware::StartPreview()
315 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__
, __LINE__
, this);
316 return mCamera
->startPreview();
320 GonkCameraHardware::StopPreview()
322 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__
, __LINE__
, this);
323 return mCamera
->stopPreview();
327 GonkCameraHardware::StartRecording()
329 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__
, __LINE__
, this);
332 rv
= mCamera
->startRecording();
334 DOM_CAMERA_LOGE("mHardware->startRecording() failed with status %d", rv
);
340 GonkCameraHardware::StopRecording()
342 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__
, __LINE__
, this);
343 mCamera
->stopRecording();
348 GonkCameraHardware::SetListener(const sp
<GonkCameraListener
>& aListener
)
350 mListener
= aListener
;
355 GonkCameraHardware::ReleaseRecordingFrame(const sp
<IMemory
>& aFrame
)
357 mCamera
->releaseRecordingFrame(aFrame
);
361 GonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled
)
363 return mCamera
->storeMetaDataInBuffers(aEnabled
);