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 "base/basictypes.h"
19 #include "GonkCameraHwMgr.h"
20 #include "GonkNativeWindow.h"
22 #define DOM_CAMERA_LOG_LEVEL 3
23 #include "CameraCommon.h"
25 using namespace mozilla
;
26 using namespace mozilla::layers
;
27 using namespace android
;
29 #if GIHM_TIMING_RECEIVEFRAME
30 #define INCLUDE_TIME_H 1
32 #if GIHM_TIMING_OVERALL
33 #define INCLUDE_TIME_H 1
39 static __inline
void timespecSubtract(struct timespec
* a
, struct timespec
* b
)
42 if (b
->tv_nsec
< a
->tv_nsec
) {
43 b
->tv_nsec
+= 1000000000;
46 a
->tv_nsec
= b
->tv_nsec
- a
->tv_nsec
;
47 a
->tv_sec
= b
->tv_sec
- a
->tv_sec
;
51 GonkCameraHardware::GonkCameraHardware(GonkCamera
* aTarget
, PRUint32 aCamera
)
54 , mPreviewFormat(PREVIEW_FORMAT_UNKNOWN
)
56 , mMonitor("GonkCameraHardware.Monitor")
61 DOM_CAMERA_LOGI( "%s: this = %p (aTarget = %p)\n", __func__
, (void* )this, (void* )aTarget
);
66 GonkCameraHardware::OnNewFrame()
71 GonkNativeWindow
* window
= static_cast<GonkNativeWindow
*>(mWindow
.get());
72 nsRefPtr
<GraphicBufferLocked
> buffer
= window
->getCurrentBuffer();
73 ReceiveFrame(mTarget
, buffer
);
76 // Android data callback
78 GonkCameraHardware::DataCallback(int32_t aMsgType
, const sp
<IMemory
> &aDataPtr
, camera_frame_metadata_t
* aMetadata
, void* aUser
)
80 GonkCameraHardware
* hw
= GetHardware((PRUint32
)aUser
);
82 DOM_CAMERA_LOGW("%s:aUser = %d resolved to no camera hw\n", __func__
, (PRUint32
)aUser
);
89 GonkCamera
* camera
= hw
->mTarget
;
92 case CAMERA_MSG_PREVIEW_FRAME
:
96 case CAMERA_MSG_COMPRESSED_IMAGE
:
97 ReceiveImage(camera
, (PRUint8
*)aDataPtr
->pointer(), aDataPtr
->size());
101 DOM_CAMERA_LOGE("Unhandled data callback event %d\n", aMsgType
);
105 DOM_CAMERA_LOGW("%s: hw = %p (camera = NULL)\n", __func__
, hw
);
109 // Android notify callback
111 GonkCameraHardware::NotifyCallback(int32_t aMsgType
, int32_t ext1
, int32_t ext2
, void* aUser
)
114 GonkCameraHardware
* hw
= GetHardware((PRUint32
)aUser
);
116 DOM_CAMERA_LOGW("%s:aUser = %d resolved to no camera hw\n", __func__
, (PRUint32
)aUser
);
123 GonkCamera
* camera
= hw
->mTarget
;
129 case CAMERA_MSG_FOCUS
:
131 DOM_CAMERA_LOGI("Autofocus complete");
134 DOM_CAMERA_LOGW("Autofocus failed");
137 AutoFocusComplete(camera
, bSuccess
);
140 case CAMERA_MSG_SHUTTER
:
141 DOM_CAMERA_LOGW("Shutter event not handled yet\n");
145 DOM_CAMERA_LOGE("Unhandled notify callback event %d\n", aMsgType
);
151 GonkCameraHardware::init()
153 DOM_CAMERA_LOGI("%s: this = %p\n", __func__
, (void* )this);
155 if (hw_get_module(CAMERA_HARDWARE_MODULE_ID
, (const hw_module_t
**)&mModule
) < 0) {
158 char cameraDeviceName
[4];
159 snprintf(cameraDeviceName
, sizeof(cameraDeviceName
), "%d", mCamera
);
160 mHardware
= new CameraHardwareInterface(cameraDeviceName
);
161 if (mHardware
->initialize(&mModule
->common
) != OK
) {
166 mWindow
= new GonkNativeWindow(this);
168 if (sHwHandle
== 0) {
169 sHwHandle
= 1; // don't use 0
171 mHardware
->setCallbacks(GonkCameraHardware::NotifyCallback
, GonkCameraHardware::DataCallback
, NULL
, (void*)sHwHandle
);
173 // initialize the local camera parameter database
174 mParams
= mHardware
->getParameters();
176 mHardware
->setPreviewWindow(mWindow
);
181 GonkCameraHardware::~GonkCameraHardware()
183 DOM_CAMERA_LOGI( "%s:%d : this = %p\n", __func__
, __LINE__
, (void*)this );
187 GonkCameraHardware
* GonkCameraHardware::sHw
= nullptr;
188 PRUint32
GonkCameraHardware::sHwHandle
= 0;
191 GonkCameraHardware::ReleaseHandle(PRUint32 aHwHandle
)
193 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
194 DOM_CAMERA_LOGI("%s: aHwHandle = %d, hw = %p (sHwHandle = %d)\n", __func__
, aHwHandle
, (void*)hw
, sHwHandle
);
199 DOM_CAMERA_LOGI("%s: before: sHwHandle = %d\n", __func__
, sHwHandle
);
200 sHwHandle
+= 1; // invalidate old handles before deleting
202 hw
->mHardware
->disableMsgType(CAMERA_MSG_ALL_MSGS
);
203 hw
->mHardware
->stopPreview();
204 hw
->mHardware
->release();
205 GonkNativeWindow
* window
= static_cast<GonkNativeWindow
*>(hw
->mWindow
.get());
207 DOM_CAMERA_LOGI("%s: after: sHwHandle = %d\n", __func__
, sHwHandle
);
208 delete hw
; // destroy the camera hardware instance
212 GonkCameraHardware::GetHandle(GonkCamera
* aTarget
, PRUint32 aCamera
)
214 ReleaseHandle(sHwHandle
);
216 sHw
= new GonkCameraHardware(aTarget
, aCamera
);
218 if (sHw
->IsInitialized()) {
222 DOM_CAMERA_LOGE("failed to initialize camera hardware\n");
229 GonkCameraHardware::GetFps(PRUint32 aHwHandle
)
231 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
240 GonkCameraHardware::GetPreviewSize(PRUint32 aHwHandle
, PRUint32
* aWidth
, PRUint32
* aHeight
)
242 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
244 *aWidth
= hw
->mWidth
;
245 *aHeight
= hw
->mHeight
;
253 GonkCameraHardware::SetPreviewSize(PRUint32 aWidth
, PRUint32 aHeight
)
255 Vector
<Size
> previewSizes
;
256 PRUint32 bestWidth
= aWidth
;
257 PRUint32 bestHeight
= aHeight
;
258 PRUint32 minSizeDelta
= PR_UINT32_MAX
;
262 mParams
.getSupportedPreviewSizes(previewSizes
);
264 if (!aWidth
&& !aHeight
) {
265 // no size specified, take the first supported size
266 size
= previewSizes
[0];
267 bestWidth
= size
.width
;
268 bestHeight
= size
.height
;
269 } else if (aWidth
&& aHeight
) {
270 // both height and width specified, find the supported size closest to requested size
271 for (PRUint32 i
= 0; i
< previewSizes
.size(); i
++) {
272 Size size
= previewSizes
[i
];
273 PRUint32 delta
= abs((long int)(size
.width
* size
.height
- aWidth
* aHeight
));
274 if (delta
< minSizeDelta
) {
275 minSizeDelta
= delta
;
276 bestWidth
= size
.width
;
277 bestHeight
= size
.height
;
280 } else if (!aWidth
) {
281 // width not specified, find closest height match
282 for (PRUint32 i
= 0; i
< previewSizes
.size(); i
++) {
283 size
= previewSizes
[i
];
284 delta
= abs((long int)(size
.height
- aHeight
));
285 if (delta
< minSizeDelta
) {
286 minSizeDelta
= delta
;
287 bestWidth
= size
.width
;
288 bestHeight
= size
.height
;
291 } else if (!aHeight
) {
292 // height not specified, find closest width match
293 for (PRUint32 i
= 0; i
< previewSizes
.size(); i
++) {
294 size
= previewSizes
[i
];
295 delta
= abs((long int)(size
.width
- aWidth
));
296 if (delta
< minSizeDelta
) {
297 minSizeDelta
= delta
;
298 bestWidth
= size
.width
;
299 bestHeight
= size
.height
;
305 mHeight
= bestHeight
;
306 mParams
.setPreviewSize(mWidth
, mHeight
);
310 GonkCameraHardware::SetPreviewSize(PRUint32 aHwHandle
, PRUint32 aWidth
, PRUint32 aHeight
)
312 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
314 hw
->SetPreviewSize(aWidth
, aHeight
);
319 GonkCameraHardware::AutoFocus(PRUint32 aHwHandle
)
321 DOM_CAMERA_LOGI("%s: aHwHandle = %d\n", __func__
, aHwHandle
);
322 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
327 hw
->mHardware
->enableMsgType(CAMERA_MSG_FOCUS
);
328 return hw
->mHardware
->autoFocus();
332 GonkCameraHardware::CancelAutoFocus(PRUint32 aHwHandle
)
334 DOM_CAMERA_LOGI("%s: aHwHandle = %d\n", __func__
, aHwHandle
);
335 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
337 hw
->mHardware
->cancelAutoFocus();
342 GonkCameraHardware::TakePicture(PRUint32 aHwHandle
)
344 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
349 hw
->mHardware
->enableMsgType(CAMERA_MSG_COMPRESSED_IMAGE
);
350 return hw
->mHardware
->takePicture();
354 GonkCameraHardware::CancelTakePicture(PRUint32 aHwHandle
)
356 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
358 hw
->mHardware
->cancelPicture();
363 GonkCameraHardware::PushParameters(PRUint32 aHwHandle
, const CameraParameters
& aParams
)
365 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
370 return hw
->mHardware
->setParameters(aParams
);
374 GonkCameraHardware::PullParameters(PRUint32 aHwHandle
, CameraParameters
& aParams
)
376 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
378 aParams
= hw
->mHardware
->getParameters();
383 GonkCameraHardware::StartPreview()
387 DOM_CAMERA_LOGI("Preview formats: %s\n", mParams
.get(mParams
.KEY_SUPPORTED_PREVIEW_FORMATS
));
389 // try to set preferred image format and frame rate
390 const char* const PREVIEW_FORMAT
= "yuv420p";
391 const char* const BAD_PREVIEW_FORMAT
= "yuv420sp";
392 mParams
.setPreviewFormat(PREVIEW_FORMAT
);
393 mParams
.setPreviewFrameRate(mFps
);
394 mHardware
->setParameters(mParams
);
396 // check that our settings stuck
397 mParams
= mHardware
->getParameters();
398 format
= mParams
.getPreviewFormat();
399 if (strcmp(format
, PREVIEW_FORMAT
) == 0) {
400 mPreviewFormat
= PREVIEW_FORMAT_YUV420P
; /* \o/ */
401 } else if (strcmp(format
, BAD_PREVIEW_FORMAT
) == 0) {
402 mPreviewFormat
= PREVIEW_FORMAT_YUV420SP
;
403 DOM_CAMERA_LOGA("Camera ignored our request for '%s' preview, will have to convert (from %d)\n", PREVIEW_FORMAT
, mPreviewFormat
);
405 mPreviewFormat
= PREVIEW_FORMAT_UNKNOWN
;
406 DOM_CAMERA_LOGE("Camera ignored our request for '%s' preview, returned UNSUPPORTED format '%s'\n", PREVIEW_FORMAT
, format
);
409 // Check the frame rate and log if the camera ignored our setting
410 PRUint32 fps
= mParams
.getPreviewFrameRate();
412 DOM_CAMERA_LOGA("We asked for %d fps but camera returned %d fps, using it", mFps
, fps
);
416 return mHardware
->startPreview();
420 GonkCameraHardware::StartPreview(PRUint32 aHwHandle
)
422 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
423 DOM_CAMERA_LOGI("%s:%d : aHwHandle = %d, hw = %p\n", __func__
, __LINE__
, aHwHandle
, hw
);
428 return hw
->StartPreview();
432 GonkCameraHardware::StopPreview(PRUint32 aHwHandle
)
434 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
436 hw
->mHardware
->stopPreview();
441 GonkCameraHardware::GetPreviewFormat(PRUint32 aHwHandle
)
443 GonkCameraHardware
* hw
= GetHardware(aHwHandle
);
445 return PREVIEW_FORMAT_UNKNOWN
;
448 return hw
->mPreviewFormat
;