blob: a54aae723ac72c6a40a1b45cb7d0ebefb5b86f6b [file] [log] [blame]
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "CameraHardware"
19
20#include <utils/Log.h>
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +080021#include <cutils/properties.h>
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080022#include <fcntl.h>
23#include <sys/mman.h>
24#include <sys/stat.h> /* for mode definitions */
25
26#include <ui/Rect.h>
27#include <ui/GraphicBufferMapper.h>
28#include "CameraHardware.h"
29#include "Converter.h"
30
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080031#define MIN_WIDTH 320
32#define MIN_HEIGHT 240
33
34#ifndef PIXEL_FORMAT_RGB_888
35#define PIXEL_FORMAT_RGB_888 3 /* */
36#endif
37
38#ifndef PIXEL_FORMAT_RGBA_8888
39#define PIXEL_FORMAT_RGBA_8888 1 /* [ov] */
40#endif
41
42#ifndef PIXEL_FORMAT_RGBX_8888
43#define PIXEL_FORMAT_RGBX_8888 2
44#endif
45
46#ifndef PIXEL_FORMAT_BGRA_8888
47#define PIXEL_FORMAT_BGRA_8888 5 /* [ov] */
48#endif
49
50#ifndef PIXEL_FORMAT_RGB_565
51#define PIXEL_FORMAT_RGB_565 4 /* [ov] */
52#endif
53
54// We need this format to allow special preview modes
55#ifndef PIXEL_FORMAT_YCrCb_422_I
56#define PIXEL_FORMAT_YCrCb_422_I 100
57#endif
58
59#ifndef PIXEL_FORMAT_YCbCr_422_SP
60#define PIXEL_FORMAT_YCbCr_422_SP 0x10 /* NV16 [ov] */
61#endif
62
63#ifndef PIXEL_FORMAT_YCbCr_420_SP
64#define PIXEL_FORMAT_YCbCr_420_SP 0x21 /* NV12 */
65#endif
66
67#ifndef PIXEL_FORMAT_UNKNOWN
68#define PIXEL_FORMAT_UNKNOWN 0
69#endif
70
71 /*
72 * Android YUV format:
73 *
74 * This format is exposed outside of the HAL to software
75 * decoders and applications.
76 * EGLImageKHR must support it in conjunction with the
77 * OES_EGL_image_external extension.
78 *
79 * YV12 is 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
80 * by (W/2) x (H/2) Cr and Cb planes.
81 *
82 * This format assumes
83 * - an even width
84 * - an even height
85 * - a horizontal stride multiple of 16 pixels
86 * - a vertical stride equal to the height
87 *
88 * y_size = stride * height
89 * c_size = ALIGN(stride/2, 16) * height/2
90 * size = y_size + c_size * 2
91 * cr_offset = y_size
92 * cb_offset = y_size + c_size
93 *
94 */
95#ifndef PIXEL_FORMAT_YV12
96#define PIXEL_FORMAT_YV12 0x32315659 /* YCrCb 4:2:0 Planar */
97#endif
98
99#ifndef PIXEL_FORMAT_YV16
100#define PIXEL_FORMAT_YV16 0x36315659 /* YCrCb 4:2:2 Planar */
101#endif
102
103// File to control camera power
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800104#define CAMERA_POWER_FILE "camera.power_file"
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800105
106namespace android {
107
108bool CameraHardware::PowerOn()
109{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800110 ALOGD("CameraHardware::PowerOn: Power ON camera.");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800111
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800112 mCameraPowerFile = new char[PROPERTY_VALUE_MAX];
113 if (!property_get(CAMERA_POWER_FILE, mCameraPowerFile, "")) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800114 ALOGD("CameraHardware::PowerOn: no power_file set");
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800115 delete [] mCameraPowerFile;
116 mCameraPowerFile = 0;
117 return true;
118 }
119
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800120 // power on camera
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800121 int handle = ::open(mCameraPowerFile,O_RDWR);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800122 if (handle >= 0) {
123 ::write(handle,"1\n",2);
124 ::close(handle);
125 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800126 ALOGE("Could not open %s for writing.", mCameraPowerFile);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800127 return false;
128 }
129
130 // Wait until the camera is recognized or timed out
131 int timeOut = 500;
132 do {
133 // Try to open the video capture device
Andres Rodriguez937775c2012-04-19 23:38:00 +0800134 handle = ::open(mVideoDevice,O_RDWR);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800135 if (handle >= 0)
136 break;
137 // Wait a bit
138 ::usleep(10000);
139 } while (--timeOut > 0);
140
141 if (handle >= 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800142 ALOGD("Camera powered on");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800143 ::close(handle);
144 return true;
145 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800146 ALOGE("Unable to power camera");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800147 }
148
149 return false;
150}
151
152bool CameraHardware::PowerOff()
153{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800154 ALOGD("CameraHardware::PowerOff: Power OFF camera.");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800155
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800156 if (!mCameraPowerFile)
157 return true;
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800158 // power on camera
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800159 int handle = ::open(mCameraPowerFile,O_RDWR);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800160 if (handle >= 0) {
161 ::write(handle,"0\n",2);
162 ::close(handle);
163 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800164 ALOGE("Could not open %s for writing.", mCameraPowerFile);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800165 return false;
166 }
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800167 delete [] mCameraPowerFile;
168 mCameraPowerFile = 0;
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800169 return true;
170}
171
Andres Rodriguez937775c2012-04-19 23:38:00 +0800172CameraHardware::CameraHardware(const hw_module_t* module, char* devLocation) :
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800173 mWin(0),
174 mPreviewWinFmt(PIXEL_FORMAT_UNKNOWN),
175 mPreviewWinWidth(0),
176 mPreviewWinHeight(0),
177
178 mParameters(),
179
180 mRawPreviewHeap(0),
181 mRawPreviewFrameSize(0),
182
183 mRawPreviewWidth(0),
184 mRawPreviewHeight(0),
185
186 mPreviewHeap(0),
187 mPreviewFrameSize(0),
188 mPreviewFmt(PIXEL_FORMAT_UNKNOWN),
189
190 mRawPictureHeap(0),
191 mRawPictureBufferSize(0),
192
193 mRecordingHeap(0),
194 mRecordingFrameSize(0),
195 mRecFmt(PIXEL_FORMAT_UNKNOWN),
196
197 mJpegPictureHeap(0),
198 mJpegPictureBufferSize(0),
199
200 mRecordingEnabled(0),
201
202 mNotifyCb(0),
203 mDataCb(0),
204 mDataCbTimestamp(0),
205 mRequestMemory(0),
206 mCallbackCookie(0),
207
208 mMsgEnabled(0),
209 mCurrentPreviewFrame(0),
Chih-Wei Huang47e3f0e2012-02-07 17:29:05 +0800210 mCurrentRecordingFrame(0),
211 mCameraPowerFile(0)
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800212{
Andres Rodriguez937775c2012-04-19 23:38:00 +0800213 //Store the video device location
214 mVideoDevice = devLocation;
215
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800216 /*
217 * Initialize camera_device descriptor for this object.
218 */
219
220 /* Common header */
221 common.tag = HARDWARE_DEVICE_TAG;
222 common.version = 0;
223 common.module = const_cast<hw_module_t*>(module);
224 common.close = CameraHardware::close;
225
226 /* camera_device fields. */
227 ops = &mDeviceOps;
228 priv = this;
229
230 // Power on camera
231 PowerOn();
232
233 // Init default parameters
234 initDefaultParameters();
235}
236
237CameraHardware::~CameraHardware()
238{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800239 ALOGD("CameraHardware::destruct");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800240 if (mPreviewThread != 0) {
241 stopPreview();
242 }
243
244 // Release all memory heaps
245 if (mRawPreviewHeap) {
246 mRawPreviewHeap->release(mRawPreviewHeap);
247 mRawPreviewHeap = NULL;
248 }
249
250 if (mPreviewHeap) {
251 mPreviewHeap->release(mPreviewHeap);
252 mPreviewHeap = NULL;
253 }
254
255 if (mRawPictureHeap) {
256 mRawPictureHeap->release(mRawPictureHeap);
257 mRawPictureHeap = NULL;
258 }
259
260 if (mRecordingHeap) {
261 mRecordingHeap->release(mRecordingHeap);
262 mRecordingHeap = NULL;
263 }
264
265 if (mJpegPictureHeap) {
266 mJpegPictureHeap->release(mJpegPictureHeap);
267 mJpegPictureHeap = NULL;
268 }
269
270 // Power off camera
271 PowerOff();
272}
273
274bool CameraHardware::NegotiatePreviewFormat(struct preview_stream_ops* win)
275{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800276 ALOGD("CameraHardware::NegotiatePreviewFormat");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800277
278 // Get the preview size... If we are recording, use the recording video size instead of the preview size
279 int pw, ph;
280 if (mRecordingEnabled && mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
281 mParameters.getVideoSize(&pw, &ph);
282 } else {
283 mParameters.getPreviewSize(&pw, &ph);
284 }
285
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800286 ALOGD("Trying to set preview window geometry to %dx%d",pw,ph);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800287 mPreviewWinFmt = PIXEL_FORMAT_UNKNOWN;
288 mPreviewWinWidth = 0;
289 mPreviewWinHeight = 0;
290
291 // Set the buffer geometry of the surface and YV12 as the preview format
292 if (win->set_buffers_geometry(win,pw,ph,PIXEL_FORMAT_RGBA_8888) != NO_ERROR) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800293 ALOGE("Unable to set buffer geometry");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800294 return false;
295 }
296
297 // Store the preview window format
298 mPreviewWinFmt = PIXEL_FORMAT_RGBA_8888;
299 mPreviewWinWidth = pw;
300 mPreviewWinHeight = ph;
301
302 return true;
303}
304
305/****************************************************************************
306 * Camera API implementation.
307 ***************************************************************************/
308
309status_t CameraHardware::connectCamera(hw_device_t** device)
310{
Chih-Wei Huang342584c2018-06-20 18:04:58 +0800311 ALOGD("CameraHardware::connectCamera: %s", mVideoDevice);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800312
313 *device = &common;
314 return NO_ERROR;
315}
316
317status_t CameraHardware::closeCamera()
318{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800319 ALOGD("CameraHardware::closeCamera");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800320 releaseCamera();
321 return NO_ERROR;
322}
323
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200324status_t CameraHardware::getCameraInfo(struct camera_info* info, int facing,
325 int orientation)
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800326{
Chih-Wei Huang342584c2018-06-20 18:04:58 +0800327 ALOGV("CameraHardware::getCameraInfo");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800328
Andres Rodriguez937775c2012-04-19 23:38:00 +0800329 info->facing = facing;
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200330 info->orientation = orientation;
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800331
332 return NO_ERROR;
333}
334
335status_t CameraHardware::setPreviewWindow(struct preview_stream_ops* window)
336{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800337 ALOGD("CameraHardware::setPreviewWindow: preview_stream_ops: %p", window);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800338 {
339 Mutex::Autolock lock(mLock);
340
341 if (window != NULL) {
342 /* The CPU will write each frame to the preview window buffer.
343 * Note that we delay setting preview window buffer geometry until
344 * frames start to come in. */
345 status_t res = window->set_usage(window, GRALLOC_USAGE_SW_WRITE_OFTEN);
346 if (res != NO_ERROR) {
347 res = -res; // set_usage returns a negative errno.
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800348 ALOGE("%s: Error setting preview window usage %d -> %s",
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800349 __FUNCTION__, res, strerror(res));
350 return res;
351 }
352 }
353
354 mWin = window;
355
356 // setup the preview window geometry to be able to use the full preview window
357 if (mPreviewThread != 0 && mWin != 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800358 ALOGD("CameraHardware::setPreviewWindow - Negotiating preview format");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800359 NegotiatePreviewFormat(mWin);
360 }
361
362 }
363 return NO_ERROR;
364}
365
366void CameraHardware::setCallbacks(camera_notify_callback notify_cb,
367 camera_data_callback data_cb,
368 camera_data_timestamp_callback data_cb_timestamp,
369 camera_request_memory get_memory,
370 void* user)
371{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800372 ALOGD("CameraHardware::setCallbacks");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800373 {
374 Mutex::Autolock lock(mLock);
375 mNotifyCb = notify_cb;
376 mDataCb = data_cb;
377 mDataCbTimestamp = data_cb_timestamp;
378 mRequestMemory = get_memory;
379 mCallbackCookie = user;
380 }
381}
382
383
384void CameraHardware::enableMsgType(int32_t msgType)
385{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800386 ALOGD("CameraHardware::enableMsgType: %d", msgType);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800387 {
388 Mutex::Autolock lock(mLock);
389 int32_t old = mMsgEnabled;
390 mMsgEnabled |= msgType;
391
392 // If something changed related to the starting or stopping of
393 // the recording process...
394 if ((msgType & CAMERA_MSG_VIDEO_FRAME) &&
395 (mMsgEnabled ^ old) & CAMERA_MSG_VIDEO_FRAME && mRecordingEnabled) {
396
397 // Recreate the heaps if toggling recording changes the raw preview size
398 // and also restart the preview so we use the new size if needed
399 initHeapLocked();
400 }
401 }
402}
403
404
405void CameraHardware::disableMsgType(int32_t msgType)
406{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800407 ALOGD("CameraHardware::disableMsgType: %d", msgType);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800408 {
409 Mutex::Autolock lock(mLock);
410 int32_t old = mMsgEnabled;
411 mMsgEnabled &= ~msgType;
412
413 // If something changed related to the starting or stopping of
414 // the recording process...
415 if ((msgType & CAMERA_MSG_VIDEO_FRAME) &&
416 (mMsgEnabled ^ old) & CAMERA_MSG_VIDEO_FRAME && mRecordingEnabled) {
417
418 // Recreate the heaps if toggling recording changes the raw preview size
419 // and also restart the preview so we use the new size if needed
420 initHeapLocked();
421 }
422 }
423}
424
425/**
426 * Query whether a message, or a set of messages, is enabled.
427 * Note that this is operates as an AND, if any of the messages
428 * queried are off, this will return false.
429 */
430int CameraHardware::isMsgTypeEnabled(int32_t msgType)
431{
432 Mutex::Autolock lock(mLock);
433
434 // All messages queried must be enabled to return true
435 int enabled = (mMsgEnabled & msgType) == msgType;
436
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800437 ALOGD("CameraHardware::isMsgTypeEnabled(%d): %d", msgType, enabled);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800438 return enabled;
439}
440
441CameraHardware::PreviewThread::PreviewThread(CameraHardware* hw) :
442 Thread(false),
443 mHardware(hw)
444{
445}
446
447
448void CameraHardware::PreviewThread::onFirstRef()
449{
450 run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
451}
452
453bool CameraHardware::PreviewThread::threadLoop()
454{
455 mHardware->previewThread();
456 // loop until we need to quit
457 return true;
458}
459
460status_t CameraHardware::startPreviewLocked()
461{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800462 ALOGD("CameraHardware::startPreviewLocked");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800463
464 if (mPreviewThread != 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800465 ALOGD("CameraHardware::startPreviewLocked: preview already running");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800466 return NO_ERROR;
467 }
468
469 int width, height;
470
471 // If we are recording, use the recording video size instead of the preview size
472 if (mRecordingEnabled && mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
473 mParameters.getVideoSize(&width, &height);
474 } else {
475 mParameters.getPreviewSize(&width, &height);
476 }
477
Michael Goffioul8cf00b62018-06-08 13:02:21 -0700478 int fps = getPreviewFrameRate(mParameters);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800479
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800480 ALOGD("CameraHardware::startPreviewLocked: Open, %dx%d", width, height);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800481
Andres Rodriguez937775c2012-04-19 23:38:00 +0800482 status_t ret = camera.Open(mVideoDevice);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800483 if (ret != NO_ERROR) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800484 ALOGE("Failed to initialize Camera");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800485 return ret;
486 }
487
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800488 ALOGD("CameraHardware::startPreviewLocked: Init");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800489
490 ret = camera.Init(width, height, fps);
491 if (ret != NO_ERROR) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800492 ALOGE("Failed to setup streaming");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800493 return ret;
494 }
495
496 /* Retrieve the real size being used */
497 camera.getSize(width, height);
498
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800499 ALOGD("CameraHardware::startPreviewLocked: effective size: %dx%d",width, height);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800500
501 // If we are recording, use the recording video size instead of the preview size
502 if (mRecordingEnabled && mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
503 /* Store it as the video size to use */
504 mParameters.setVideoSize(width, height);
505 } else {
506 /* Store it as the preview size to use */
507 mParameters.setPreviewSize(width, height);
508 }
509
510 /* And reinit the memory heaps to reflect the real used size if needed */
511 initHeapLocked();
512
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800513 ALOGD("CameraHardware::startPreviewLocked: StartStreaming");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800514
515 ret = camera.StartStreaming();
516 if (ret != NO_ERROR) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800517 ALOGE("Failed to start streaming");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800518 return ret;
519 }
520
521 // setup the preview window geometry in order to use it to zoom the image
522 if (mWin != 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800523 ALOGD("CameraHardware::setPreviewWindow - Negotiating preview format");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800524 NegotiatePreviewFormat(mWin);
525 }
526
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800527 ALOGD("CameraHardware::startPreviewLocked: starting PreviewThread");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800528
529 mPreviewThread = new PreviewThread(this);
530
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800531 ALOGD("CameraHardware::startPreviewLocked: O - this:0x%p",this);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800532
533 return NO_ERROR;
534}
535
536status_t CameraHardware::startPreview()
537{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800538 ALOGD("CameraHardware::startPreview");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800539
540 Mutex::Autolock lock(mLock);
541 return startPreviewLocked();
542}
543
544
545void CameraHardware::stopPreviewLocked()
546{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800547 ALOGD("CameraHardware::stopPreviewLocked");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800548
549 if (mPreviewThread != 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800550 ALOGD("CameraHardware::stopPreviewLocked: stopping PreviewThread");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800551
552 mPreviewThread->requestExitAndWait();
553 mPreviewThread.clear();
554
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800555 ALOGD("CameraHardware::stopPreviewLocked: Uninit");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800556 camera.Uninit();
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800557 ALOGD("CameraHardware::stopPreviewLocked: StopStreaming");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800558 camera.StopStreaming();
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800559 ALOGD("CameraHardware::stopPreviewLocked: Close");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800560 camera.Close();
561 }
562
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800563 ALOGD("CameraHardware::stopPreviewLocked: OK");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800564}
565
566void CameraHardware::stopPreview()
567{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800568 ALOGD("CameraHardware::stopPreview");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800569
570 Mutex::Autolock lock(mLock);
571 stopPreviewLocked();
572}
573
574int CameraHardware::isPreviewEnabled()
575{
576 int enabled = 0;
577 {
578 Mutex::Autolock lock(mLock);
579 enabled = (mPreviewThread != 0);
580 }
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800581 ALOGD("CameraHardware::isPreviewEnabled: %d", enabled);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800582
583 return enabled;
584}
585
586status_t CameraHardware::storeMetaDataInBuffers(int value)
587{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800588 ALOGD("CameraHardware::storeMetaDataInBuffers: %d", value);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800589
590 // Do not accept to store metadata in buffers - We will always store
591 // YUV data on video buffers. Metadata, in the case of Nvidia Tegra2
592 // is a descriptor of an OpenMax endpoint that was filled with the
593 // data.
594 return (value) ? INVALID_OPERATION : NO_ERROR;
595}
596
597status_t CameraHardware::startRecording()
598{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800599 ALOGD("CameraHardware::startRecording");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800600 {
601 Mutex::Autolock lock(mLock);
602 if (!mRecordingEnabled) {
603 mRecordingEnabled = true;
604
605 // If something changed related to the starting or stopping of
606 // the recording process...
607 if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
608
609 // Recreate the heaps if toggling recording changes the raw preview size
610 // and also restart the preview so we use the new size if needed
611 initHeapLocked();
612 }
613 }
614 }
615 return NO_ERROR;
616}
617
618void CameraHardware::stopRecording()
619{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800620 ALOGD("CameraHardware::stopRecording");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800621 {
622 Mutex::Autolock lock(mLock);
623 if (mRecordingEnabled) {
624 mRecordingEnabled = false;
625
626 // If something changed related to the starting or stopping of
627 // the recording process...
628 if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
629
630 // Recreate the heaps if toggling recording changes the raw preview size
631 // and also restart the preview so we use the new size if needed
632 initHeapLocked();
633 }
634 }
635 }
636}
637
638int CameraHardware::isRecordingEnabled()
639{
640 int enabled;
641 {
642 Mutex::Autolock lock(mLock);
643 enabled = mRecordingEnabled;
644 }
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800645 ALOGD("CameraHardware::isRecordingEnabled: %d", mRecordingEnabled);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800646 return enabled;
647}
648
649void CameraHardware::releaseRecordingFrame(const void* mem)
650{
Chih-Wei Huangb4777d82019-02-26 17:59:11 +0800651 ALOGD("CameraHardware::releaseRecordingFrame: %p", mem);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800652}
653
654
655status_t CameraHardware::setAutoFocus()
656{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800657 ALOGD("CameraHardware::setAutoFocus");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800658 Mutex::Autolock lock(mLock);
659 if (createThread(beginAutoFocusThread, this) == false)
660 return UNKNOWN_ERROR;
661 return NO_ERROR;
662}
663
664status_t CameraHardware::cancelAutoFocus()
665{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800666 ALOGD("CameraHardware::cancelAutoFocus");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800667 return NO_ERROR;
668}
669
670status_t CameraHardware::takePicture()
671{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800672 ALOGD("CameraHardware::takePicture");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800673 if (createThread(beginPictureThread, this) == false)
674 return UNKNOWN_ERROR;
675
676 return NO_ERROR;
677}
678
679status_t CameraHardware::cancelPicture()
680{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800681 ALOGD("CameraHardware::cancelPicture");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800682 return NO_ERROR;
683}
684
685status_t CameraHardware::setParameters(const char* parms)
686{
Chih-Wei Huang342584c2018-06-20 18:04:58 +0800687 ALOGV("CameraHardware::setParameters");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800688
689 CameraParameters params;
690 String8 str8_param(parms);
691 params.unflatten(str8_param);
692
693 Mutex::Autolock lock(mLock);
694
695 // If no changes, trivially accept it!
696 if (params.flatten() == mParameters.flatten()) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800697 ALOGD("Trivially accept it. No changes detected");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800698 return NO_ERROR;
699 }
700
701 if (strcmp(params.getPreviewFormat(),"yuv422i-yuyv") &&
702 strcmp(params.getPreviewFormat(),"yuv422sp") &&
703 strcmp(params.getPreviewFormat(),"yuv420sp") &&
704 strcmp(params.getPreviewFormat(),"yuv420p")) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800705 ALOGE("CameraHardware::setParameters: Unsupported format '%s' for preview",params.getPreviewFormat());
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800706 return BAD_VALUE;
707 }
708
709 if (strcmp(params.getPictureFormat(), CameraParameters::PIXEL_FORMAT_JPEG)) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800710 ALOGE("CameraHardware::setParameters: Only jpeg still pictures are supported");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800711 return BAD_VALUE;
712 }
713
714 if (strcmp(params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv422i-yuyv") &&
715 strcmp(params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv422sp") &&
716 strcmp(params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv420sp") &&
717 strcmp(params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv420p")) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800718 ALOGE("CameraHardware::setParameters: Unsupported format '%s' for recording",params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT));
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800719 return BAD_VALUE;
720 }
721
722 int w, h;
723
724 params.getPreviewSize(&w, &h);
Michael Goffioul8cf00b62018-06-08 13:02:21 -0700725 ALOGD("CameraHardware::setParameters: PREVIEW: Size %dx%d, %d fps, format: %s", w, h, getPreviewFrameRate(params), params.getPreviewFormat());
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800726
727 params.getPictureSize(&w, &h);
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800728 ALOGD("CameraHardware::setParameters: PICTURE: Size %dx%d, format: %s", w, h, params.getPictureFormat());
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800729
730 params.getVideoSize(&w, &h);
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800731 ALOGD("CameraHardware::setParameters: VIDEO: Size %dx%d, format: %s", w, h, params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT));
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800732
733 // Store the new parameters
734 mParameters = params;
735
736 // Recreate the heaps if toggling recording changes the raw preview size
737 // and also restart the preview so we use the new size if needed
738 initHeapLocked();
739
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800740 ALOGD("CameraHardware::setParameters: OK");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800741
742 return NO_ERROR;
743}
744
745/* A dumb variable indicating "no params" / error on the exit from
746 * EmulatedCamera::getParameters(). */
747static char lNoParam = '\0';
748char* CameraHardware::getParameters()
749{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800750 ALOGD("CameraHardware::getParameters");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800751
752 String8 params;
753 {
754 Mutex::Autolock lock(mLock);
755 params = mParameters.flatten();
756 }
757
758 char* ret_str = reinterpret_cast<char*>(malloc(sizeof(char) * (params.length()+1)));
759 memset(ret_str, 0, params.length()+1);
760 if (ret_str != NULL) {
761 strncpy(ret_str, params.string(), params.length()+1);
762 return ret_str;
763 }
764
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800765 ALOGE("%s: Unable to allocate string for %s", __FUNCTION__, params.string());
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800766 /* Apparently, we can't return NULL fron this routine. */
767 return &lNoParam;
768}
769
770void CameraHardware::putParameters(char* params)
771{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800772 ALOGD("CameraHardware::putParameters");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800773 /* This method simply frees parameters allocated in getParameters(). */
774 if (params != NULL && params != &lNoParam) {
775 free(params);
776 }
777}
778
779status_t CameraHardware::sendCommand(int32_t command, int32_t arg1, int32_t arg2)
780{
Chih-Wei Huangb4777d82019-02-26 17:59:11 +0800781 ALOGD("CameraHardware::sendCommand: %d (%d, %d)", command, arg1, arg2);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800782 return 0;
783}
784
785void CameraHardware::releaseCamera()
786{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800787 ALOGD("CameraHardware::releaseCamera");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800788 if (mPreviewThread != 0) {
789 stopPreview();
790 }
791}
792
793status_t CameraHardware::dumpCamera(int fd)
794{
Chih-Wei Huangb4777d82019-02-26 17:59:11 +0800795 ALOGV("%s: %d", __FUNCTION__, fd);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800796 return -EINVAL;
797}
798
799// ---------------------------------------------------------------------------
800
801void CameraHardware::initDefaultParameters()
802{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800803 ALOGD("CameraHardware::initDefaultParameters");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800804
805 CameraParameters p;
806 unsigned int i;
807
808 int pw = MIN_WIDTH;
809 int ph = MIN_HEIGHT;
810 int pfps = 30;
811 int fw = MIN_WIDTH;
812 int fh = MIN_HEIGHT;
813 SortedVector<SurfaceSize> avSizes;
814 SortedVector<int> avFps;
815
Andres Rodriguez937775c2012-04-19 23:38:00 +0800816 if (camera.Open(mVideoDevice) != NO_ERROR) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800817 ALOGE("cannot open device.");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800818 } else {
819
820 // Get the default preview format
821 pw = camera.getBestPreviewFmt().getWidth();
822 ph = camera.getBestPreviewFmt().getHeight();
823 pfps = camera.getBestPreviewFmt().getFps();
824
825 // Get the default picture format
826 fw = camera.getBestPictureFmt().getWidth();
827 fh = camera.getBestPictureFmt().getHeight();
828
829 // Get all the available sizes
830 avSizes = camera.getAvailableSizes();
831
832 // Add some sizes that some specific apps expect to find:
833 // GTalk expects 320x200
834 // Fring expects 240x160
835 // And also add standard resolutions found in low end cameras, as
836 // android apps could be expecting to find them
837 // The V4LCamera handles those resolutions by choosing the next
838 // larger one and cropping the captured frames to the requested size
839
840 avSizes.add(SurfaceSize(480,320)); // HVGA
841 avSizes.add(SurfaceSize(432,320)); // 1.35-to-1, for photos. (Rounded up from 1.3333 to 1)
842 avSizes.add(SurfaceSize(352,288)); // CIF
843 avSizes.add(SurfaceSize(320,240)); // QVGA
844 avSizes.add(SurfaceSize(320,200));
845 avSizes.add(SurfaceSize(240,160)); // SQVGA
846 avSizes.add(SurfaceSize(176,144)); // QCIF
847
848 // Get all the available Fps
849 avFps = camera.getAvailableFps();
850 }
851
852
853 // Convert the sizes to text
854 String8 szs("");
855 for (i = 0; i < avSizes.size(); i++) {
856 char descr[32];
857 SurfaceSize ss = avSizes[i];
858 sprintf(descr,"%dx%d",ss.getWidth(),ss.getHeight());
859 szs.append(descr);
860 if (i < avSizes.size() - 1) {
861 szs.append(",");
862 }
863 }
864
865 // Convert the fps to ranges in text
866 String8 fpsranges("");
867 for (i = 0; i < avFps.size(); i++) {
868 char descr[32];
Michael Goffioul8cf00b62018-06-08 13:02:21 -0700869 int ss = avFps[i] * 1000;
870 sprintf(descr, "(%d,%d)", ss, ss);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800871 fpsranges.append(descr);
872 if (i < avFps.size() - 1) {
873 fpsranges.append(",");
874 }
875 }
876
877 // Convert the fps to text
878 String8 fps("");
879 for (i = 0; i < avFps.size(); i++) {
880 char descr[32];
881 int ss = avFps[i];
882 sprintf(descr,"%d",ss);
883 fps.append(descr);
884 if (i < avFps.size() - 1) {
885 fps.append(",");
886 }
887 }
888
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800889 ALOGI("Default preview size: (%d x %d), fps:%d\n",pw,ph,pfps);
890 ALOGI("All available formats: %s",(const char*)szs);
891 ALOGI("All available fps: %s",(const char*)fpsranges);
892 ALOGI("Default picture size: (%d x %d)\n",fw,fh);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800893
894 // Now store the data
895
896 // Antibanding
897 p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,"auto");
898 p.set(CameraParameters::KEY_ANTIBANDING,"auto");
899
900 // Effects
901 p.set(CameraParameters::KEY_SUPPORTED_EFFECTS,"none"); // "none,mono,sepia,negative,solarize"
902 p.set(CameraParameters::KEY_EFFECT,"none");
903
904 // Flash modes
905 p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,"off");
906 p.set(CameraParameters::KEY_FLASH_MODE,"off");
907
908 // Focus modes
909 p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,"fixed");
910 p.set(CameraParameters::KEY_FOCUS_MODE,"fixed");
911
912#if 0
913 p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,0);
914 p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,75);
915 p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,"0x0");
916 p.set("jpeg-thumbnail-size","0x0");
917 p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,0);
918#endif
919
920 // Picture - Only JPEG supported
921 p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,CameraParameters::PIXEL_FORMAT_JPEG); // ONLY jpeg
922 p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
923 p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, szs);
924 p.setPictureSize(fw,fh);
925 p.set(CameraParameters::KEY_JPEG_QUALITY, 85);
926
927 // Preview - Supporting yuv422i-yuyv,yuv422sp,yuv420sp, defaulting to yuv420sp, as that is the android Defacto default
928 p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,"yuv422i-yuyv,yuv422sp,yuv420sp,yuv420p"); // All supported preview formats
929 p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV422SP); // For compatibility sake ... Default to the android standard
930 p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, fpsranges);
931 p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, fps);
932 p.setPreviewFrameRate( pfps );
933 p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, szs);
934 p.setPreviewSize(pw,ph);
935
936 // Video - Supporting yuv422i-yuyv,yuv422sp,yuv420sp and defaulting to yuv420p
937 p.set("video-size-values"/*CameraParameters::KEY_SUPPORTED_VIDEO_SIZES*/, szs);
938 p.setVideoSize(pw,ph);
939 p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420P);
940 p.set("preferred-preview-size-for-video", "640x480");
941
942 // supported rotations
943 p.set("rotation-values","0");
944 p.set(CameraParameters::KEY_ROTATION,"0");
945
946 // scenes modes
947 p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,"auto");
948 p.set(CameraParameters::KEY_SCENE_MODE,"auto");
949
950 // white balance
951 p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,"auto");
952 p.set(CameraParameters::KEY_WHITE_BALANCE,"auto");
953
954 // zoom
955 p.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED,"false");
956 p.set("max-video-continuous-zoom", 0 );
957 p.set(CameraParameters::KEY_ZOOM, "0");
958 p.set(CameraParameters::KEY_MAX_ZOOM, "100");
959 p.set(CameraParameters::KEY_ZOOM_RATIOS, "100");
960 p.set(CameraParameters::KEY_ZOOM_SUPPORTED, "false");
961
Edgardo Gho92edd742015-04-24 16:25:40 +0800962 // missing parameters for Camera2
Chih-Wei Huangc55e86f2019-02-26 18:01:40 +0800963 p.setFloat(CameraParameters::KEY_FOCAL_LENGTH, 4.31);
964 p.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, 90);
965 p.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, 90);
Edgardo Gho92edd742015-04-24 16:25:40 +0800966 p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, "640x480,0x0");
meijjaa53838dc2015-12-31 11:27:37 +0100967 p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "6");
968 p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5");
Edgardo Gho92edd742015-04-24 16:25:40 +0800969
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800970 if (setParameters(p.flatten()) != NO_ERROR) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800971 ALOGE("CameraHardware::initDefaultParameters: Failed to set default parameters.");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800972 }
973}
974
975void CameraHardware::initHeapLocked()
976{
Chih-Wei Huang342584c2018-06-20 18:04:58 +0800977 ALOGV("CameraHardware::initHeapLocked");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800978
979 int preview_width, preview_height;
980 int picture_width, picture_height;
981 int video_width, video_height;
982
983 if (!mRequestMemory) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800984 ALOGE("No memory allocator available");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800985 return;
986 }
987
988 bool restart_preview = false;
989
990 mParameters.getPreviewSize(&preview_width, &preview_height);
991 mParameters.getPictureSize(&picture_width, &picture_height);
992 mParameters.getVideoSize(&video_width, &video_height);
993
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800994 ALOGD("CameraHardware::initHeapLocked: preview size=%dx%d", preview_width, preview_height);
995 ALOGD("CameraHardware::initHeapLocked: picture size=%dx%d", picture_width, picture_height);
996 ALOGD("CameraHardware::initHeapLocked: video size=%dx%d", video_width, video_height);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800997
998 int how_raw_preview_big = 0;
999
1000 // If we are recording, use the recording video size instead of the preview size
1001 if (mRecordingEnabled && mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
1002 how_raw_preview_big = video_width * video_height << 1; // Raw preview heap always in YUYV
1003
1004 // If something changed ...
1005 if (mRawPreviewWidth != video_width || mRawPreviewHeight != video_height) {
1006
1007 // Stop the preview thread if needed
1008 if (mPreviewThread != 0) {
1009 restart_preview = true;
1010 stopPreviewLocked();
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001011 ALOGD("Stopping preview to allow changes");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001012 }
1013
1014 // Store the new effective size
1015 mRawPreviewWidth = video_width;
1016 mRawPreviewHeight = video_height;
1017 }
1018
1019 } else {
1020 how_raw_preview_big = preview_width * preview_height << 1; // Raw preview heap always in YUYV
1021
1022 // If something changed ...
1023 if (mRawPreviewWidth != preview_width ||
1024 mRawPreviewHeight != preview_height) {
1025
1026 // Stop the preview thread if needed
1027 if (mPreviewThread != 0) {
1028 restart_preview = true;
1029 stopPreviewLocked();
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001030 ALOGD("Stopping preview to allow changes");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001031 }
1032
1033 // Store the effective size
1034 mRawPreviewWidth = preview_width;
1035 mRawPreviewHeight = preview_height;
1036 }
1037 }
1038
1039 if (how_raw_preview_big != mRawPreviewFrameSize) {
1040
1041 // Stop the preview thread if needed
1042 if (!restart_preview && mPreviewThread != 0) {
1043 restart_preview = true;
1044 stopPreviewLocked();
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001045 ALOGD("Stopping preview to allow changes");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001046 }
1047
1048 mRawPreviewFrameSize = how_raw_preview_big;
1049
1050 // Create raw picture heap.
1051 if (mRawPreviewHeap) {
1052 mRawPreviewHeap->release(mRawPreviewHeap);
1053 mRawPreviewHeap = NULL;
1054 }
1055 mRawPreviewBuffer = NULL;
1056
1057 mRawPreviewHeap = mRequestMemory(-1,mRawPreviewFrameSize,1,mCallbackCookie);
1058 if (mRawPreviewHeap) {
1059 mRawPreviewBuffer = mRawPreviewHeap->data;
1060 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001061 ALOGE("Unable to allocate memory for RawPreview");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001062 }
1063
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001064 ALOGD("CameraHardware::initHeapLocked: Raw preview heap allocated");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001065 }
1066
1067 int how_preview_big = 0;
1068 if (!strcmp(mParameters.getPreviewFormat(),"yuv422i-yuyv")) {
1069 mPreviewFmt = PIXEL_FORMAT_YCrCb_422_I;
1070 how_preview_big = preview_width * preview_height << 1; // 2 bytes per pixel
1071 } else if (!strcmp(mParameters.getPreviewFormat(),"yuv422sp")) {
1072 mPreviewFmt = PIXEL_FORMAT_YCbCr_422_SP;
1073 how_preview_big = (preview_width * preview_height * 3) >> 1; // 1.5 bytes per pixel
1074 } else if (!strcmp(mParameters.getPreviewFormat(),"yuv420sp")) {
1075 mPreviewFmt = PIXEL_FORMAT_YCbCr_420_SP;
1076 how_preview_big = (preview_width * preview_height * 3) >> 1; // 1.5 bytes per pixel
1077 } else if (!strcmp(mParameters.getPreviewFormat(),"yuv420p")) {
1078 mPreviewFmt = PIXEL_FORMAT_YV12;
1079
1080 /*
1081 * This format assumes
1082 * - an even width
1083 * - an even height
1084 * - a horizontal stride multiple of 16 pixels
1085 * - a vertical stride equal to the height
1086 *
1087 * y_size = stride * height
1088 * c_size = ALIGN(stride/2, 16) * height/2
1089 * cr_offset = y_size
1090 * cb_offset = y_size + c_size
1091 * size = y_size + c_size * 2
1092 */
1093
1094 int stride = (preview_width + 15) & (-16); // Round to 16 pixels
1095 int y_size = stride * preview_height;
1096 int c_stride = ((stride >> 1) + 15) & (-16); // Round to 16 pixels
1097 int c_size = c_stride * preview_height >> 1;
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001098 int size = y_size + (c_size << 1);
1099
1100 how_preview_big = size;
1101 }
1102
1103 if (how_preview_big != mPreviewFrameSize) {
1104
1105 // Stop the preview thread if needed
1106 if (!restart_preview && mPreviewThread != 0) {
1107 restart_preview = true;
1108 stopPreviewLocked();
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001109 ALOGD("Stopping preview to allow changes");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001110 }
1111
1112 mPreviewFrameSize = how_preview_big;
1113
1114 // Make a new mmap'ed heap that can be shared across processes.
1115 // use code below to test with pmem
1116 if (mPreviewHeap) {
1117 mPreviewHeap->release(mPreviewHeap);
1118 mPreviewHeap = NULL;
1119 }
1120 memset(mPreviewBuffer,0,sizeof(mPreviewBuffer));
1121
1122 mPreviewHeap = mRequestMemory(-1,mPreviewFrameSize,kBufferCount,mCallbackCookie);
1123 if (mPreviewHeap) {
1124 // Make an IMemory for each frame so that we can reuse them in callbacks.
1125 for (int i = 0; i < kBufferCount; i++) {
1126 mPreviewBuffer[i] = (char*)mPreviewHeap->data + (i * mPreviewFrameSize);
1127 }
1128 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001129 ALOGE("Unable to allocate memory for Preview");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001130 }
1131
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001132 ALOGD("CameraHardware::initHeapLocked: preview heap allocated");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001133 }
1134
1135 int how_recording_big = 0;
1136 if (!strcmp(mParameters.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv422i-yuyv")) {
1137 mRecFmt = PIXEL_FORMAT_YCrCb_422_I;
1138 how_recording_big = video_width * video_height << 1; // 2 bytes per pixel
1139 } else if (!strcmp(mParameters.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv422sp")) {
1140 mRecFmt = PIXEL_FORMAT_YCbCr_422_SP;
1141 how_recording_big = (video_width * video_height * 3) >> 1; // 1.5 bytes per pixel
1142 } else if (!strcmp(mParameters.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv420sp")) {
1143 mRecFmt = PIXEL_FORMAT_YCbCr_420_SP;
1144 how_recording_big = (video_width * video_height * 3) >> 1; // 1.5 bytes per pixel
1145 } else if (!strcmp(mParameters.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT),"yuv420p")) {
1146 mRecFmt = PIXEL_FORMAT_YV12;
1147
1148 /*
1149 * This format assumes
1150 * - an even width
1151 * - an even height
1152 * - a horizontal stride multiple of 16 pixels
1153 * - a vertical stride equal to the height
1154 *
1155 * y_size = stride * height
1156 * c_size = ALIGN(stride/2, 16) * height/2
1157 * cr_offset = y_size
1158 * cb_offset = y_size + c_size
1159 * size = y_size + c_size * 2
1160 */
1161
1162 int stride = (video_width + 15) & (-16); // Round to 16 pixels
1163 int y_size = stride * video_height;
1164 int c_stride = ((stride >> 1) + 15) & (-16); // Round to 16 pixels
1165 int c_size = c_stride * video_height >> 1;
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001166 int size = y_size + (c_size << 1);
1167
1168 how_recording_big = size;
1169 }
1170
1171 if (how_recording_big != mRecordingFrameSize) {
1172
1173 // Stop the preview thread if needed
1174 if (!restart_preview && mPreviewThread != 0) {
1175 restart_preview = true;
1176 stopPreviewLocked();
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001177 ALOGD("Stopping preview to allow changes");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001178 }
1179
1180 mRecordingFrameSize = how_recording_big;
1181
1182 if (mRecordingHeap) {
1183 mRecordingHeap->release(mRecordingHeap);
1184 mRecordingHeap = NULL;
1185 }
1186 memset(mRecBuffers,0,sizeof(mRecBuffers));
1187
1188 mRecordingHeap = mRequestMemory(-1,mRecordingFrameSize,kBufferCount,mCallbackCookie);
1189 if (mRecordingHeap) {
1190 // Make an IMemory for each frame so that we can reuse them in callbacks.
1191 for (int i = 0; i < kBufferCount; i++) {
1192 mRecBuffers[i] = (char*)mRecordingHeap->data + (i * mRecordingFrameSize);
1193 }
1194 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001195 ALOGE("Unable to allocate memory for Recording");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001196 }
1197
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001198 ALOGD("CameraHardware::initHeapLocked: recording heap allocated");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001199 }
1200
1201 int how_picture_big = picture_width * picture_height << 1; // Raw picture heap always in YUYV
1202 if (how_picture_big != mRawPictureBufferSize) {
1203
1204 // Picture does not need to stop the preview, as the mutex ensures
1205 // the picture memory pool is not being used, and the camera is not
1206 // capturing pictures right now
1207
1208 mRawPictureBufferSize = how_picture_big;
1209
1210 // Create raw picture heap.
1211 if (mRawPictureHeap) {
1212 mRawPictureHeap->release(mRawPictureHeap);
1213 mRawPictureHeap = NULL;
1214 }
1215 mRawBuffer = NULL;
1216
1217 mRawPictureHeap = mRequestMemory(-1,mRawPictureBufferSize,1,mCallbackCookie);
1218 if (mRawPictureHeap) {
1219 mRawBuffer = mRawPictureHeap->data;
1220 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001221 ALOGE("Unable to allocate memory for RawPicture");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001222 }
1223
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001224 ALOGD("CameraHardware::initHeapLocked: Raw picture heap allocated");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001225 }
1226
1227 int how_jpeg_big = picture_width * picture_height << 1; // jpeg maximum size
1228 if (how_jpeg_big != mJpegPictureBufferSize) {
1229
1230 // Picture does not need to stop the preview, as the mutex ensures
1231 // the picture memory pool is not being used, and the camera is not
1232 // capturing pictures right now
1233
1234 mJpegPictureBufferSize = how_jpeg_big;
1235
1236 // Create Jpeg picture heap.
1237 if (mJpegPictureHeap) {
1238 mJpegPictureHeap->release(mJpegPictureHeap);
1239 mJpegPictureHeap = NULL;
1240 }
1241 mJpegPictureHeap = mRequestMemory(-1,how_jpeg_big,1,mCallbackCookie);
1242 if (!mJpegPictureHeap) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001243 ALOGE("Unable to allocate memory for RawPicture");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001244 }
1245
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001246 ALOGD("CameraHardware::initHeapLocked: Jpeg picture heap allocated");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001247 }
1248
1249 // Don't forget to restart the preview if it was stopped...
1250 if (restart_preview) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001251 ALOGD("Restarting preview");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001252 startPreviewLocked();
1253 }
1254
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001255 ALOGD("CameraHardware::initHeapLocked: OK");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001256}
1257
1258int CameraHardware::previewThread()
1259{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001260 ALOGV("CameraHardware::previewThread: this=%p",this);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001261
Michael Goffioul8cf00b62018-06-08 13:02:21 -07001262 int previewFrameRate = getPreviewFrameRate(mParameters);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001263
1264 // Calculate how long to wait between frames.
1265 int delay = (int)(1000000 / previewFrameRate);
1266
1267 // Buffers to send messages
1268 int recBufferIdx = 0;
1269 int previewBufferIdx = 0;
1270
1271 bool record = false;
1272 bool preview = false;
1273
1274 // Get the current timestamp
1275 nsecs_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
1276
1277 // We must avoid a race condition here when destroying the thread...
1278 // So, if we fail to lock the mutex, just retry a bit later, but
1279 // let the android thread end if requested!
1280 if (mLock.tryLock() == NO_ERROR) {
1281
1282 // If no raw preview buffer, we can't do anything...
1283 if (mRawPreviewBuffer == 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001284 ALOGE("No Raw preview buffer!");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001285 mLock.unlock();
1286 return NO_ERROR;
1287 }
1288
1289 // Get the preview buffer for the current frame
1290 // This is always valid, even if the client died -- the memory
1291 // is still mapped in our process.
1292 uint8_t *frame = (uint8_t *)mPreviewBuffer[mCurrentPreviewFrame];
1293
1294 // If no preview buffer, we cant do anything...
1295 if (frame == 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001296 ALOGE("No preview buffer!");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001297 mLock.unlock();
1298 return NO_ERROR;
1299 }
1300
1301
1302 // Get a pointer to the memory area to use... In case of previewing in YUV422I, we
1303 // can save a buffer copy by directly using the output buffer. But ONLY if NOT recording
1304 // or, in case of recording, when size matches
1305 uint8_t* rawBase = (mPreviewFmt == PIXEL_FORMAT_YCrCb_422_I &&
1306 (!mRecordingEnabled || mRawPreviewFrameSize == mPreviewFrameSize))
1307 ? frame : (uint8_t*)mRawPreviewBuffer;
1308
1309 // Grab a frame in the raw format YUYV
1310 camera.GrabRawFrame(rawBase, mRawPreviewFrameSize);
1311
1312 // If the recording is enabled...
1313 if (mRecordingEnabled && mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001314 //ALOGD("CameraHardware::previewThread: posting video frame...");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001315
1316 // Get the video size. We are warrantied here that the current capture
1317 // size IS exacty equal to the video size, as this condition is enforced
1318 // by this driver, that priorizes recording size over preview size requirements
1319
1320 uint8_t *recFrame = (uint8_t *) mRecBuffers[mCurrentRecordingFrame];
1321 if (recFrame != 0) {
1322
1323 // Convert from our raw frame to the one the Record requires
1324 switch (mRecFmt) {
1325
1326 // Note: Apparently, Android's "YCbCr_422_SP" is merely an arbitrary label
1327 // The preview data comes in a YUV 4:2:0 format, with Y plane, then VU plane
1328 case PIXEL_FORMAT_YCbCr_422_SP:
1329 yuyv_to_yvu420sp(recFrame, mRawPreviewWidth, mRawPreviewHeight, rawBase, (mRawPreviewWidth<<1), mRawPreviewWidth, mRawPreviewHeight);
1330 break;
1331
1332 case PIXEL_FORMAT_YCbCr_420_SP:
1333 yuyv_to_yvu420sp(recFrame, mRawPreviewWidth, mRawPreviewHeight, rawBase, (mRawPreviewWidth<<1), mRawPreviewWidth, mRawPreviewHeight);
1334 break;
1335
1336 case PIXEL_FORMAT_YV12:
1337 /* OMX recorder needs YUV */
1338 yuyv_to_yuv420p(recFrame, mRawPreviewWidth, mRawPreviewHeight, rawBase, (mRawPreviewWidth<<1), mRawPreviewWidth, mRawPreviewHeight);
1339 break;
1340
1341 case PIXEL_FORMAT_YCrCb_422_I:
1342 memcpy(recFrame, rawBase, mRecordingFrameSize);
1343 break;
1344 }
1345
1346 // Remember we must schedule the callback
1347 record = true;
1348
1349 // Advance the buffer pointer.
1350 recBufferIdx = mCurrentRecordingFrame;
1351 mCurrentRecordingFrame = (mCurrentRecordingFrame + 1) % kBufferCount;
1352 }
1353 }
1354
1355 if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001356 //ALOGD("CameraHardware::previewThread: posting preview frame...");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001357
1358 // Here we could eventually have a problem: If we are recording, the recording size
1359 // takes precedence over the preview size. So, the rawBase buffer could be of a
1360 // different size than the preview buffer. Handle this situation by centering/cropping
1361 // if needed.
1362
1363 // Get the preview size
1364 int width = 0, height = 0;
1365 mParameters.getPreviewSize(&width,&height);
1366
1367 // Assume we will be able to copy at least those pixels
1368 int cwidth = width;
1369 int cheight = height;
1370
1371 // If we are trying to display a preview larger than the effective capture, truncate to it
1372 if (cwidth > mRawPreviewWidth)
1373 cwidth = mRawPreviewWidth;
1374 if (cheight > mRawPreviewHeight)
1375 cheight = mRawPreviewHeight;
1376
1377 // Convert from our raw frame to the one the Preview requires
1378 switch (mPreviewFmt) {
1379
1380 // Note: Apparently, Android's "YCbCr_422_SP" is merely an arbitrary label
1381 // The preview data comes in a YUV 4:2:0 format, with Y plane, then VU plane
1382 case PIXEL_FORMAT_YCbCr_422_SP: // This is misused by android...
1383 yuyv_to_yvu420sp(frame, width, height, rawBase, (mRawPreviewWidth<<1), cwidth, cheight);
1384 break;
1385
1386 case PIXEL_FORMAT_YCbCr_420_SP:
1387 yuyv_to_yvu420sp(frame, width, height, rawBase, (mRawPreviewWidth<<1), cwidth, cheight);
1388 break;
1389
1390 case PIXEL_FORMAT_YV12:
1391 yuyv_to_yvu420p(frame, width, height, rawBase, (mRawPreviewWidth<<1), cwidth, cheight);
1392 break;
1393
1394 case PIXEL_FORMAT_YCrCb_422_I:
1395 // Nothing to do here. Is is handled as a special case without buffer copies...
1396 // but ONLY in special cases... Otherwise, handle the copy!
1397 if (mRecordingEnabled && mRawPreviewFrameSize != mPreviewFrameSize) {
1398 // We need to copy ... do it
1399 uint8_t* dst = frame;
1400 uint8_t* src = rawBase;
1401 int h;
1402 for (h = 0; h < cheight; h++) {
1403 memcpy(dst,src,cwidth<<1);
1404 dst += width << 1;
1405 src += mRawPreviewWidth<<1;
1406 }
1407 }
1408 break;
1409
1410 default:
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001411 ALOGE("Unhandled pixel format");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001412
1413 }
1414
1415 // Remember we must schedule the callback
1416 preview = true;
1417
1418 // Advance the buffer pointer.
1419 previewBufferIdx = mCurrentPreviewFrame;
1420 mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
1421 }
1422
1423 // Display the preview image
1424 fillPreviewWindow(rawBase, mRawPreviewWidth, mRawPreviewHeight);
1425
1426 // Release the lock
1427 mLock.unlock();
1428
1429 } else {
1430
1431 // Delay a little ... and reattempt the lock on the next iteration
1432 delay >>= 7;
1433 }
1434
1435 // We must schedule the callbacks Outside the lock, or the caller
1436 // could call us and cause a deadlock!
1437 if (preview) {
1438 mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, previewBufferIdx, NULL, mCallbackCookie);
1439 }
1440
1441 if (record) {
1442 // Record callback uses a timestamped frame
1443 mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, mRecordingHeap, recBufferIdx, mCallbackCookie);
1444 }
1445
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001446 ALOGV("previewThread OK");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001447
1448 // Wait for it...
1449 usleep(delay);
1450
1451 return NO_ERROR;
1452}
1453
1454void CameraHardware::fillPreviewWindow(uint8_t* yuyv, int srcWidth, int srcHeight)
1455{
1456 // Preview to a preview window...
1457 if (mWin == 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001458 ALOGE("%s: No preview window",__FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001459 return;
1460 }
1461
1462 // Get a videobuffer
1463 buffer_handle_t* buf = NULL;
1464 int stride = 0;
1465 status_t res = mWin->dequeue_buffer(mWin, &buf, &stride);
1466 if (res != NO_ERROR || buf == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001467 ALOGE("%s: Unable to dequeue preview window buffer: %d -> %s",
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001468 __FUNCTION__, -res, strerror(-res));
1469 return;
1470 }
1471
1472 /* Let the preview window to lock the buffer. */
1473 res = mWin->lock_buffer(mWin, buf);
1474 if (res != NO_ERROR) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001475 ALOGE("%s: Unable to lock preview window buffer: %d -> %s",
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001476 __FUNCTION__, -res, strerror(-res));
1477 mWin->cancel_buffer(mWin, buf);
1478 return;
1479 }
1480
1481 /* Now let the graphics framework to lock the buffer, and provide
1482 * us with the framebuffer data address. */
1483 void* vaddr = NULL;
1484
1485 const Rect bounds(srcWidth, srcHeight);
1486 GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get());
1487 res = grbuffer_mapper.lock(*buf, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &vaddr);
1488 if (res != NO_ERROR || vaddr == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001489 ALOGE("%s: grbuffer_mapper.lock failure: %d -> %s",
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001490 __FUNCTION__, res, strerror(res));
1491 mWin->cancel_buffer(mWin, buf);
1492 return;
1493 }
1494
1495 // Calculate the source stride...
1496 int srcStride = srcWidth<<1;
1497 uint8_t* src = (uint8_t*)yuyv;
1498
1499 // Center into the preview surface if needed
1500 int xStart = (mPreviewWinWidth - srcWidth ) >> 1;
1501 int yStart = (mPreviewWinHeight - srcHeight) >> 1;
1502
1503 // Make sure not to overflow the preview surface
1504 if (xStart < 0 || yStart < 0) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001505 ALOGE("Preview window is smaller than video preview size - Cropping image.");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001506
1507 if (xStart < 0) {
1508 srcWidth += xStart;
1509 src += ((-xStart) >> 1) << 1; // Center the crop rectangle
1510 xStart = 0;
1511 }
1512
1513 if (yStart < 0) {
1514 srcHeight += yStart;
1515 src += ((-yStart) >> 1) * srcStride; // Center the crop rectangle
1516 yStart = 0;
1517 }
1518 }
1519
1520 // Calculate the bytes per pixel
1521 int bytesPerPixel = 2;
1522 if (mPreviewWinFmt == PIXEL_FORMAT_YCbCr_422_SP ||
1523 mPreviewWinFmt == PIXEL_FORMAT_YCbCr_420_SP ||
1524 mPreviewWinFmt == PIXEL_FORMAT_YV12 ||
1525 mPreviewWinFmt == PIXEL_FORMAT_YV16 ) {
1526 bytesPerPixel = 1; // Planar Y
1527 } else if (mPreviewWinFmt == PIXEL_FORMAT_RGB_888) {
1528 bytesPerPixel = 3;
1529 } else if (mPreviewWinFmt == PIXEL_FORMAT_RGBA_8888 ||
1530 mPreviewWinFmt == PIXEL_FORMAT_RGBX_8888 ||
1531 mPreviewWinFmt == PIXEL_FORMAT_BGRA_8888) {
1532 bytesPerPixel = 4;
1533 } else if (mPreviewWinFmt == PIXEL_FORMAT_YCrCb_422_I) {
1534 bytesPerPixel = 2;
1535 }
1536
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001537 ALOGV("ANativeWindow: bits:%p, stride in pixels:%d, w:%d, h: %d, format: %d",vaddr,stride,mPreviewWinWidth,mPreviewWinHeight,mPreviewWinFmt);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001538
1539 // Based on the destination pixel type, we must convert from YUYV to it
1540 int dstStride = bytesPerPixel * stride;
1541 uint8_t* dst = ((uint8_t*)vaddr) + (xStart * bytesPerPixel) + (dstStride * yStart);
1542
1543 switch (mPreviewWinFmt) {
1544 case PIXEL_FORMAT_YCbCr_422_SP: // This is misused by android...
1545 yuyv_to_yvu420sp( dst, dstStride, mPreviewWinHeight, src, srcStride, srcWidth, srcHeight);
1546 break;
1547
1548 case PIXEL_FORMAT_YCbCr_420_SP:
1549 yuyv_to_yvu420sp( dst, dstStride, mPreviewWinHeight,src, srcStride, srcWidth, srcHeight);
1550 break;
1551
1552 case PIXEL_FORMAT_YV12:
1553 yuyv_to_yvu420p( dst, dstStride, mPreviewWinHeight, src, srcStride, srcWidth, srcHeight);
1554 break;
1555
1556 case PIXEL_FORMAT_YV16:
1557 yuyv_to_yvu422p( dst, dstStride, mPreviewWinHeight, src, srcStride, srcWidth, srcHeight);
1558 break;
1559
1560 case PIXEL_FORMAT_YCrCb_422_I:
1561 {
1562 // We need to copy ... do it
1563 uint8_t* pdst = dst;
1564 uint8_t* psrc = src;
1565 int h;
1566 for (h = 0; h < srcHeight; h++) {
1567 memcpy(pdst,psrc,srcWidth<<1);
1568 pdst += dstStride;
1569 psrc += srcStride;
1570 }
1571 break;
1572 }
1573
1574 case PIXEL_FORMAT_RGB_888:
1575 yuyv_to_rgb24(src, srcStride, dst, dstStride, srcWidth, srcHeight);
1576 break;
1577
1578 case PIXEL_FORMAT_RGBA_8888:
1579 yuyv_to_rgb32(src, srcStride, dst, dstStride, srcWidth, srcHeight);
1580 break;
1581
1582 case PIXEL_FORMAT_RGBX_8888:
1583 yuyv_to_rgb32(src, srcStride, dst, dstStride, srcWidth, srcHeight);
1584 break;
1585
1586 case PIXEL_FORMAT_BGRA_8888:
1587 yuyv_to_bgr32(src, srcStride, dst, dstStride, srcWidth, srcHeight);
1588 break;
1589
1590 case PIXEL_FORMAT_RGB_565:
1591 yuyv_to_rgb565(src, srcStride, dst, dstStride, srcWidth, srcHeight);
1592 break;
1593
1594 default:
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001595 ALOGE("Unhandled pixel format");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001596 }
1597
1598 /* Show it. */
1599 mWin->enqueue_buffer(mWin, buf);
1600
1601 // Post the filled buffer!
1602 grbuffer_mapper.unlock(*buf);
1603}
1604
1605int CameraHardware::beginAutoFocusThread(void *cookie)
1606{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001607 ALOGD("CameraHardware::beginAutoFocusThread");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001608 CameraHardware *c = (CameraHardware *)cookie;
1609 return c->autoFocusThread();
1610}
1611
1612int CameraHardware::autoFocusThread()
1613{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001614 ALOGD("CameraHardware::autoFocusThread");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001615 if (mMsgEnabled & CAMERA_MSG_FOCUS)
1616 mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
1617 return NO_ERROR;
1618}
1619
1620
1621int CameraHardware::beginPictureThread(void *cookie)
1622{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001623 ALOGD("CameraHardware::beginPictureThread");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001624 CameraHardware *c = (CameraHardware *)cookie;
1625 return c->pictureThread();
1626}
1627
1628int CameraHardware::pictureThread()
1629{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001630 ALOGD("CameraHardware::pictureThread");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001631
1632 bool raw = false;
1633 bool jpeg = false;
1634 bool shutter = false;
1635 {
1636 Mutex::Autolock lock(mLock);
1637
1638 int w, h;
1639 mParameters.getPictureSize(&w, &h);
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001640 ALOGD("CameraHardware::pictureThread: taking picture of %dx%d", w, h);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001641
1642 /* Make sure to remember if the shutter must be enabled or not */
1643 if (mMsgEnabled & CAMERA_MSG_SHUTTER) {
1644 shutter = true;
1645 }
1646
1647 /* The camera application will restart preview ... */
1648 if (mPreviewThread != 0) {
1649 stopPreviewLocked();
1650 }
1651
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001652 ALOGD("CameraHardware::pictureThread: taking picture (%d x %d)", w, h);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001653
Andres Rodriguez937775c2012-04-19 23:38:00 +08001654 if (camera.Open(mVideoDevice) == NO_ERROR) {
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001655 camera.Init(w, h, 1);
1656
1657 /* Retrieve the real size being used */
1658 camera.getSize(w,h);
1659
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001660 ALOGD("CameraHardware::pictureThread: effective size: %dx%d",w, h);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001661
1662 /* Store it as the picture size to use */
1663 mParameters.setPictureSize(w, h);
1664
1665 /* And reinit the capture heap to reflect the real used size if needed */
1666 initHeapLocked();
1667
1668 camera.StartStreaming();
1669
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001670 ALOGD("CameraHardware::pictureThread: waiting until camera picture stabilizes...");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001671
1672 int maxFramesToWait = 8;
1673 int luminanceStableFor = 0;
1674 int prevLuminance = 0;
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001675 int stride = w << 1;
1676 int thresh = (w >> 4) * (h >> 4) * 12; // 5% of full range
1677
1678 while (maxFramesToWait > 0 && luminanceStableFor < 4) {
1679 uint8_t* ptr = (uint8_t *)mRawBuffer;
1680
1681 // Get the image
1682 camera.GrabRawFrame(ptr, (w * h << 1)); // Always YUYV
1683
1684 // luminance metering points
1685 int luminance = 0;
1686 for (int x = 0; x < (w<<1); x += 32) {
1687 for (int y = 0; y < h*stride; y += 16*stride) {
1688 luminance += ptr[y + x];
1689 }
1690 }
1691
1692 // Calculate variation of luminance
1693 int dif = prevLuminance - luminance;
1694 if (dif < 0) dif = -dif;
1695 prevLuminance = luminance;
1696
1697 // Wait until variation is less than 5%
1698 if (dif > thresh) {
1699 luminanceStableFor = 1;
1700 } else {
1701 luminanceStableFor++;
1702 }
1703
1704 maxFramesToWait--;
1705
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001706 ALOGD("luminance: %4d, dif: %4d, thresh: %d, stableFor: %d, maxWait: %d", luminance, dif, thresh, luminanceStableFor, maxFramesToWait);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001707 }
1708
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001709 ALOGD("CameraHardware::pictureThread: picture taken");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001710
1711 if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
1712
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001713 ALOGD("CameraHardware::pictureThread: took raw picture");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001714 raw = true;
1715 }
1716
1717 if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
1718
1719 int quality = mParameters.getInt(CameraParameters::KEY_JPEG_QUALITY);
1720
1721 uint8_t* jpegBuff = (uint8_t*) malloc(mJpegPictureBufferSize);
1722 if (jpegBuff) {
1723
1724 // Compress the raw captured image to our buffer
1725 int fileSize = yuyv_to_jpeg((uint8_t *)mRawBuffer, jpegBuff, mJpegPictureBufferSize, w, h, w << 1,quality);
1726
1727 // Create a buffer with the exact compressed size
1728 if (mJpegPictureHeap) {
1729 mJpegPictureHeap->release(mJpegPictureHeap);
1730 mJpegPictureHeap = NULL;
1731 }
1732
1733 mJpegPictureHeap = mRequestMemory(-1,fileSize,1,mCallbackCookie);
1734 if (mJpegPictureHeap) {
1735 memcpy(mJpegPictureHeap->data,jpegBuff,fileSize);
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001736 ALOGD("CameraHardware::pictureThread: took jpeg picture compressed to %d bytes, q=%d", fileSize, quality);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001737 jpeg = true;
1738 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001739 ALOGE("Unable to allocate memory for RawPicture");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001740 }
1741 free(jpegBuff);
1742
1743 } else {
1744
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001745 ALOGE("Unable to allocate temporary memory for Jpeg compression");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001746 }
1747
1748 }
1749
1750 camera.Uninit();
1751 camera.StopStreaming();
1752 camera.Close();
1753
1754 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001755 ALOGE("CameraHardware::pictureThread: failed to grab image");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001756 }
1757 }
1758
1759 /* All this callbacks can potentially call one of our methods.
1760 Make sure to dispatch them OUTSIDE the lock! */
1761 if (shutter) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001762 ALOGD("Sending the Shutter message");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001763 mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
1764 }
1765
1766 if (raw) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001767 ALOGD("Sending the raw message");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001768 mDataCb(CAMERA_MSG_RAW_IMAGE, mRawPictureHeap, 0, NULL, mCallbackCookie);
1769 }
1770
1771 if (jpeg) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001772 ALOGD("Sending the jpeg message");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001773 mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mJpegPictureHeap, 0, NULL, mCallbackCookie);
1774 }
1775
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001776 ALOGD("CameraHardware::pictureThread OK");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001777
1778 return NO_ERROR;
1779}
1780
Michael Goffioul8cf00b62018-06-08 13:02:21 -07001781int CameraHardware::getPreviewFrameRate(const CameraParameters& params)
1782{
1783 int min_fps = -1, max_fps = -1;
1784 params.getPreviewFpsRange(&min_fps, &max_fps);
1785 if (max_fps == -1) {
1786 max_fps = params.getPreviewFrameRate();
1787 } else {
1788 max_fps /= 1000;
1789 }
1790 return max_fps;
1791}
1792
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001793/****************************************************************************
1794 * Camera API callbacks as defined by camera_device_ops structure.
1795 *
1796 * Callbacks here simply dispatch the calls to an appropriate method inside
1797 * CameraHardware instance, defined by the 'dev' parameter.
1798 ***************************************************************************/
1799
1800int CameraHardware::set_preview_window(struct camera_device* dev,
1801 struct preview_stream_ops* window)
1802{
1803 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1804 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001805 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001806 return -EINVAL;
1807 }
1808 return ec->setPreviewWindow(window);
1809}
1810
1811void CameraHardware::set_callbacks(
1812 struct camera_device* dev,
1813 camera_notify_callback notify_cb,
1814 camera_data_callback data_cb,
1815 camera_data_timestamp_callback data_cb_timestamp,
1816 camera_request_memory get_memory,
1817 void* user)
1818{
1819 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1820 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001821 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001822 return;
1823 }
1824 ec->setCallbacks(notify_cb, data_cb, data_cb_timestamp, get_memory, user);
1825}
1826
1827void CameraHardware::enable_msg_type(struct camera_device* dev, int32_t msg_type)
1828{
1829 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1830 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001831 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001832 return;
1833 }
1834 ec->enableMsgType(msg_type);
1835}
1836
1837void CameraHardware::disable_msg_type(struct camera_device* dev, int32_t msg_type)
1838{
1839 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1840 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001841 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001842 return;
1843 }
1844 ec->disableMsgType(msg_type);
1845}
1846
1847int CameraHardware::msg_type_enabled(struct camera_device* dev, int32_t msg_type)
1848{
1849 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1850 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001851 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001852 return -EINVAL;
1853 }
1854 return ec->isMsgTypeEnabled(msg_type);
1855}
1856
1857int CameraHardware::start_preview(struct camera_device* dev)
1858{
1859 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1860 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001861 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001862 return -EINVAL;
1863 }
1864 return ec->startPreview();
1865}
1866
1867void CameraHardware::stop_preview(struct camera_device* dev)
1868{
1869 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1870 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001871 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001872 return;
1873 }
1874 ec->stopPreview();
1875}
1876
1877int CameraHardware::preview_enabled(struct camera_device* dev)
1878{
1879 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1880 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001881 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001882 return -EINVAL;
1883 }
1884 return ec->isPreviewEnabled();
1885}
1886
1887int CameraHardware::store_meta_data_in_buffers(struct camera_device* dev,
1888 int enable)
1889{
1890 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1891 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001892 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001893 return -EINVAL;
1894 }
1895 return ec->storeMetaDataInBuffers(enable);
1896}
1897
1898int CameraHardware::start_recording(struct camera_device* dev)
1899{
1900 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1901 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001902 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001903 return -EINVAL;
1904 }
1905 return ec->startRecording();
1906}
1907
1908void CameraHardware::stop_recording(struct camera_device* dev)
1909{
1910 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1911 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001912 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001913 return;
1914 }
1915 ec->stopRecording();
1916}
1917
1918int CameraHardware::recording_enabled(struct camera_device* dev)
1919{
1920 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1921 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001922 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001923 return -EINVAL;
1924 }
1925 return ec->isRecordingEnabled();
1926}
1927
1928void CameraHardware::release_recording_frame(struct camera_device* dev,
1929 const void* opaque)
1930{
1931 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1932 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001933 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001934 return;
1935 }
1936 ec->releaseRecordingFrame(opaque);
1937}
1938
1939int CameraHardware::auto_focus(struct camera_device* dev)
1940{
1941 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1942 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001943 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001944 return -EINVAL;
1945 }
1946 return ec->setAutoFocus();
1947}
1948
1949int CameraHardware::cancel_auto_focus(struct camera_device* dev)
1950{
1951 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1952 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001953 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001954 return -EINVAL;
1955 }
1956 return ec->cancelAutoFocus();
1957}
1958
1959int CameraHardware::take_picture(struct camera_device* dev)
1960{
1961 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1962 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001963 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001964 return -EINVAL;
1965 }
1966 return ec->takePicture();
1967}
1968
1969int CameraHardware::cancel_picture(struct camera_device* dev)
1970{
1971 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1972 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001973 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001974 return -EINVAL;
1975 }
1976 return ec->cancelPicture();
1977}
1978
1979int CameraHardware::set_parameters(struct camera_device* dev, const char* parms)
1980{
1981 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1982 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001983 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001984 return -EINVAL;
1985 }
1986 return ec->setParameters(parms);
1987}
1988
1989char* CameraHardware::get_parameters(struct camera_device* dev)
1990{
1991 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
1992 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08001993 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001994 return NULL;
1995 }
1996 return ec->getParameters();
1997}
1998
1999void CameraHardware::put_parameters(struct camera_device* dev, char* params)
2000{
2001 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
2002 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08002003 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08002004 return;
2005 }
2006 ec->putParameters(params);
2007}
2008
2009int CameraHardware::send_command(struct camera_device* dev,
2010 int32_t cmd,
2011 int32_t arg1,
2012 int32_t arg2)
2013{
2014 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
2015 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08002016 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08002017 return -EINVAL;
2018 }
2019 return ec->sendCommand(cmd, arg1, arg2);
2020}
2021
2022void CameraHardware::release(struct camera_device* dev)
2023{
2024 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
2025 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08002026 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08002027 return;
2028 }
2029 ec->releaseCamera();
2030}
2031
2032int CameraHardware::dump(struct camera_device* dev, int fd)
2033{
2034 CameraHardware* ec = reinterpret_cast<CameraHardware*>(dev->priv);
2035 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08002036 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08002037 return -EINVAL;
2038 }
2039 return ec->dumpCamera(fd);
2040}
2041
2042int CameraHardware::close(struct hw_device_t* device)
2043{
2044 CameraHardware* ec =
2045 reinterpret_cast<CameraHardware*>(reinterpret_cast<struct camera_device*>(device)->priv);
2046 if (ec == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +08002047 ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08002048 return -EINVAL;
2049 }
2050 return ec->closeCamera();
2051}
2052
2053/****************************************************************************
2054 * Static initializer for the camera callback API
2055 ****************************************************************************/
2056
2057camera_device_ops_t CameraHardware::mDeviceOps = {
2058 CameraHardware::set_preview_window,
2059 CameraHardware::set_callbacks,
2060 CameraHardware::enable_msg_type,
2061 CameraHardware::disable_msg_type,
2062 CameraHardware::msg_type_enabled,
2063 CameraHardware::start_preview,
2064 CameraHardware::stop_preview,
2065 CameraHardware::preview_enabled,
2066 CameraHardware::store_meta_data_in_buffers,
2067 CameraHardware::start_recording,
2068 CameraHardware::stop_recording,
2069 CameraHardware::recording_enabled,
2070 CameraHardware::release_recording_frame,
2071 CameraHardware::auto_focus,
2072 CameraHardware::cancel_auto_focus,
2073 CameraHardware::take_picture,
2074 CameraHardware::cancel_picture,
2075 CameraHardware::set_parameters,
2076 CameraHardware::get_parameters,
2077 CameraHardware::put_parameters,
2078 CameraHardware::send_command,
2079 CameraHardware::release,
2080 CameraHardware::dump
2081};
2082
2083}; // namespace android