1 /*
2 ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
3 **
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
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
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.
15 */
16
17 /*#error uncomment this for compiler test!*/
18
19 #define LOG_NIDEBUG 0
20 //#define LOG_NDEBUG 0
21
22 #define LOG_TAG "QCameraHWI"
23 #include <utils/Log.h>
24 #include <utils/threads.h>
25 #include <cutils/properties.h>
26 #include <fcntl.h>
27 #include <sys/mman.h>
28
29 #include "QCameraHAL.h"
30 #include "QCameraHWI.h"
31
32 /* QCameraHardwareInterface class implementation goes here*/
33 /* following code implement the contol logic of this class*/
34
35 namespace android {
36
37 extern void stream_cb_routine(mm_camera_super_buf_t *bufs,
38 void *userdata);
39 extern void superbuf_cb_routine(mm_camera_super_buf_t *bufs,
40 void *userdata);
41
42
43 /*Command Thread startup function*/
44
command_thread(void * obj)45 void *command_thread(void *obj)
46 {
47 QCameraHardwareInterface *pme = (QCameraHardwareInterface *)obj;
48 ALOGD("%s: E", __func__);
49 if (pme != NULL) {
50 pme->runCommandThread(obj);
51 }
52 else ALOGW("not starting command thread: the object went away!");
53 ALOGD("%s: X", __func__);
54 return NULL;
55 }
56
tryRestartStreams(camera_metadata_entry_t & streams)57 int QCameraHardwareInterface::tryRestartStreams(
58 camera_metadata_entry_t& streams)
59 {
60 int rc = 0;
61 bool needRestart = false;
62 bool needRecordingHint = false;
63
64 for (uint32_t i = 0; i < streams.count; i++) {
65 int streamId = streams.data.u8[i];
66 QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
67 if (!stream->mInit) {
68 needRestart = true;
69 if (stream->mFormat == CAMERA_YUV_420_NV12)
70 needRecordingHint = true;
71 }
72 }
73
74 if (!needRestart)
75 goto end;
76
77 QCameraStream::streamOffAll();
78
79 if (needRecordingHint) {
80 uint32_t recordingHint = 1;
81 rc = mCameraHandle->ops->set_parm(mCameraHandle->camera_handle,
82 MM_CAMERA_PARM_RECORDING_HINT, &recordingHint);
83 if (rc < 0) {
84 ALOGE("set_parm MM_CAMERA_PARM_RECORDING_HINT returns %d", rc);
85 return rc;
86 }
87 }
88
89 end:
90 for (uint32_t i = 0; i < streams.count; i++) {
91 int streamId = streams.data.u8[i];
92 QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
93 if (!stream->mInit) {
94 rc = stream->prepareStream();
95 if (rc < 0) {
96 ALOGE("prepareStream for stream %d failed %d", streamId, rc);
97 return rc;
98 }
99 }
100 }
101 for (uint32_t i = 0; i < streams.count; i++) {
102 int streamId = streams.data.u8[i];
103 QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
104
105 if (!stream->mActive) {
106 rc = stream->streamOn();
107 if (rc < 0) {
108 ALOGE("streamOn for stream %d failed %d", streamId, rc);
109 return rc;
110 }
111 }
112 }
113 return rc;
114 }
115
runCommandThread(void * data)116 void QCameraHardwareInterface::runCommandThread(void *data)
117 {
118
119 /**
120 * This function implements the main service routine for the incoming
121 * frame requests, this thread routine is started everytime we get a
122 * notify_request_queue_not_empty trigger, this thread makes the
123 * assumption that once it receives a NULL on a dequest_request call
124 * there will be a fresh notify_request_queue_not_empty call that is
125 * invoked thereby launching a new instance of this thread. Therefore,
126 * once we get a NULL on a dequeue request we simply let this thread die
127 */
128 int res;
129 camera_metadata_t *request=NULL;
130 mPendingRequests=0;
131
132 while(mRequestQueueSrc) {
133 ALOGV("%s:Dequeue request using mRequestQueueSrc:%p",__func__,mRequestQueueSrc);
134 mRequestQueueSrc->dequeue_request(mRequestQueueSrc,&request);
135 if(request==NULL) {
136 ALOGE("%s:No more requests available from src command \
137 thread dying",__func__);
138 return;
139 }
140 mPendingRequests++;
141
142 /* Set the metadata values */
143
144 /* Wait for the SOF for the new metadata values to be applied */
145
146 /* Check the streams that need to be active in the stream request */
147 sort_camera_metadata(request);
148
149 camera_metadata_entry_t streams;
150 res = find_camera_metadata_entry(request,
151 ANDROID_REQUEST_OUTPUT_STREAMS,
152 &streams);
153 if (res != NO_ERROR) {
154 ALOGE("%s: error reading output stream tag", __FUNCTION__);
155 return;
156 }
157
158 res = tryRestartStreams(streams);
159 if (res != NO_ERROR) {
160 ALOGE("error tryRestartStreams %d", res);
161 return;
162 }
163
164 /* 3rd pass: Turn on all streams requested */
165 for (uint32_t i = 0; i < streams.count; i++) {
166 int streamId = streams.data.u8[i];
167 QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
168
169 /* Increment the frame pending count in each stream class */
170
171 /* Assuming we will have the stream obj in had at this point may be
172 * may be multiple objs in which case we loop through array of streams */
173 stream->onNewRequest();
174 }
175 ALOGV("%s:Freeing request using mRequestQueueSrc:%p",__func__,mRequestQueueSrc);
176 /* Free the request buffer */
177 mRequestQueueSrc->free_request(mRequestQueueSrc,request);
178 mPendingRequests--;
179 ALOGV("%s:Completed request",__func__);
180 }
181
182 QCameraStream::streamOffAll();
183 }
184
185 /*Mem Hooks*/
get_buffer_hook(uint32_t camera_handle,uint32_t ch_id,uint32_t stream_id,void * user_data,mm_camera_frame_len_offset * frame_offset_info,uint8_t num_bufs,uint8_t * initial_reg_flag,mm_camera_buf_def_t * bufs)186 int32_t get_buffer_hook(uint32_t camera_handle,
187 uint32_t ch_id, uint32_t stream_id,
188 void *user_data,
189 mm_camera_frame_len_offset *frame_offset_info,
190 uint8_t num_bufs,
191 uint8_t *initial_reg_flag,
192 mm_camera_buf_def_t *bufs)
193 {
194 QCameraHardwareInterface *pme=(QCameraHardwareInterface *)user_data;
195 return pme->getBuf(camera_handle, ch_id, stream_id,
196 user_data, frame_offset_info,
197 num_bufs,initial_reg_flag,
198 bufs);
199
200 }
201
put_buffer_hook(uint32_t camera_handle,uint32_t ch_id,uint32_t stream_id,void * user_data,uint8_t num_bufs,mm_camera_buf_def_t * bufs)202 int32_t put_buffer_hook(uint32_t camera_handle,
203 uint32_t ch_id, uint32_t stream_id,
204 void *user_data, uint8_t num_bufs,
205 mm_camera_buf_def_t *bufs)
206 {
207 QCameraHardwareInterface *pme=(QCameraHardwareInterface *)user_data;
208 return pme->putBuf(camera_handle, ch_id, stream_id,
209 user_data, num_bufs, bufs);
210
211 }
212
getBuf(uint32_t camera_handle,uint32_t ch_id,uint32_t mm_stream_id,void * user_data,mm_camera_frame_len_offset * frame_offset_info,uint8_t num_bufs,uint8_t * initial_reg_flag,mm_camera_buf_def_t * bufs)213 int QCameraHardwareInterface::getBuf(uint32_t camera_handle,
214 uint32_t ch_id, uint32_t mm_stream_id,
215 void *user_data,
216 mm_camera_frame_len_offset *frame_offset_info,
217 uint8_t num_bufs,
218 uint8_t *initial_reg_flag,
219 mm_camera_buf_def_t *bufs)
220 {
221 status_t ret=NO_ERROR;
222 ALOGE("%s: E, stream_id = %d\n", __func__, mm_stream_id);
223 QCameraStream_preview *stream = (QCameraStream_preview *)
224 QCameraStream::getStreamAtMmId(mm_stream_id);
225
226 ALOGE("%s: len:%d, y_off:%d, cbcr:%d num buffers: %d planes:%d streamid:%d",
227 __func__,
228 frame_offset_info->frame_len,
229 frame_offset_info->mp[0].len,
230 frame_offset_info->mp[1].len,
231 num_bufs,frame_offset_info->num_planes,
232 mm_stream_id);
233 /*************Preiew Stream*****************/
234 ALOGE("Interface requesting Preview Buffers");
235 stream->mFrameOffsetInfo=*frame_offset_info;
236 if(NO_ERROR!=stream->initBuffers()){
237 return BAD_VALUE;
238 }
239 ALOGE("Debug : %s : initDisplayBuffers",__func__);
240 for(int i=0;i<num_bufs;i++) {
241 bufs[i] = stream->mDisplayBuf[i];
242 initial_reg_flag[i] =
243 (stream->mPreviewMemory.local_flag[i] == BUFFER_OWNED);
244 ALOGE("initial_reg_flag[%d]:%d",i,initial_reg_flag[i]);
245 }
246 return 0;
247 }
248
putBuf(uint32_t camera_handle,uint32_t ch_id,uint32_t mm_stream_id,void * user_data,uint8_t num_bufs,mm_camera_buf_def_t * bufs)249 int QCameraHardwareInterface::putBuf(uint32_t camera_handle,
250 uint32_t ch_id, uint32_t mm_stream_id,
251 void *user_data, uint8_t num_bufs,
252 mm_camera_buf_def_t *bufs)
253 {
254 ALOGE("%s:E, stream_id = %d",__func__, mm_stream_id);
255 QCameraStream_preview *stream = (QCameraStream_preview *)
256 QCameraStream::getStreamAtMmId(mm_stream_id);
257 stream->deinitBuffers();
258 return 0;
259 }
260
261
262 QCameraHardwareInterface::
QCameraHardwareInterface(int cameraId,int mode)263 QCameraHardwareInterface(int cameraId, int mode)
264 : mCameraId(cameraId)
265 {
266
267 cam_ctrl_dimension_t mDimension;
268
269 /* Open camera stack! */
270 memset(&mMemHooks, 0, sizeof(mm_camear_mem_vtbl_t));
271 mMemHooks.user_data=this;
272 mMemHooks.get_buf=get_buffer_hook;
273 mMemHooks.put_buf=put_buffer_hook;
274
275 mCameraHandle=camera_open(mCameraId, &mMemHooks);
276 ALOGV("Cam open returned %p",mCameraHandle);
277 if(mCameraHandle == NULL) {
278 ALOGE("startCamera: cam_ops_open failed: id = %d", mCameraId);
279 return;
280 }
281 mCameraHandle->ops->sync(mCameraHandle->camera_handle);
282
283 mChannelId=mCameraHandle->ops->ch_acquire(mCameraHandle->camera_handle);
284 if(mChannelId<=0)
285 {
286 ALOGE("%s:Channel aquire failed",__func__);
287 mCameraHandle->ops->camera_close(mCameraHandle->camera_handle);
288 return;
289 }
290
291 /* Initialize # of frame requests the HAL is handling to zero*/
292 mPendingRequests=0;
293 }
294
~QCameraHardwareInterface()295 QCameraHardwareInterface::~QCameraHardwareInterface()
296 {
297 mCameraHandle->ops->camera_close(mCameraHandle->camera_handle);
298 }
299
release()300 void QCameraHardwareInterface::release()
301 {
302 }
303
isCameraReady()304 bool QCameraHardwareInterface::isCameraReady()
305 {
306 return true;
307 }
308
set_request_queue_src_ops(const camera2_request_queue_src_ops_t * request_src_ops)309 int QCameraHardwareInterface::set_request_queue_src_ops(
310 const camera2_request_queue_src_ops_t *request_src_ops)
311 {
312 ALOGE("%s:E mRequestQueueSrc:%p",__func__,request_src_ops);
313 mRequestQueueSrc = request_src_ops;
314 ALOGE("%s:X",__func__);
315 return 0;
316 }
317
notify_request_queue_not_empty()318 int QCameraHardwareInterface::notify_request_queue_not_empty()
319 {
320
321 pthread_attr_t attr;
322 if(pthread_attr_init(&attr)!=0) {
323 ALOGE("%s:pthread_attr_init failed",__func__);
324 return BAD_VALUE;
325 }
326 if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)!=0){
327 ALOGE("%s:pthread_attr_setdetachstate failed",__func__);
328 return BAD_VALUE;
329 }
330 if(pthread_create(&mCommandThread,&attr,
331 command_thread, (void *)this)!=0) {
332 ALOGE("%s:pthread_create failed to launch command_thread",__func__);
333 return BAD_VALUE;
334 }
335
336 return NO_ERROR;
337 }
338
set_frame_queue_dst_ops(const camera2_frame_queue_dst_ops_t * frame_dst_ops)339 int QCameraHardwareInterface::set_frame_queue_dst_ops(
340 const camera2_frame_queue_dst_ops_t *frame_dst_ops)
341 {
342 mFrameQueueDst = frame_dst_ops;
343 return OK;
344 }
345
get_in_progress_count()346 int QCameraHardwareInterface::get_in_progress_count()
347 {
348 return mPendingRequests;
349 }
350
construct_default_request(int request_template,camera_metadata_t ** request)351 int QCameraHardwareInterface::construct_default_request(
352 int request_template, camera_metadata_t **request)
353 {
354 status_t ret;
355 ALOGD("%s:E:request_template:%d ",__func__,request_template);
356
357 if (request == NULL)
358 return BAD_VALUE;
359 if (request_template < 0 || request_template >= CAMERA2_TEMPLATE_COUNT)
360 return BAD_VALUE;
361
362 ret = constructDefaultRequest(request_template, request, true);
363 if (ret != OK) {
364 ALOGE("%s: Unable to allocate default request: %s (%d)",
365 __FUNCTION__, strerror(-ret), ret);
366 return ret;
367 }
368 ret = constructDefaultRequest(request_template, request, false);
369 if (ret != OK) {
370 ALOGE("%s: Unable to fill in default request: %s (%d)",
371 __FUNCTION__, strerror(-ret), ret);
372 return ret;
373 }
374
375 ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_VIDEO");
376 mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
377 ret = mCameraHandle->ops->set_parm(
378 mCameraHandle->camera_handle,
379 MM_CAMERA_PARM_OP_MODE,
380 &op_mode);
381 ALOGE("OP Mode Set");
382
383 return ret;
384 }
385
allocate_stream(uint32_t width,uint32_t height,int format,const camera2_stream_ops_t * stream_ops,uint32_t * stream_id,uint32_t * format_actual,uint32_t * usage,uint32_t * max_buffers)386 int QCameraHardwareInterface::allocate_stream(
387 uint32_t width,
388 uint32_t height, int format,
389 const camera2_stream_ops_t *stream_ops,
390 uint32_t *stream_id,
391 uint32_t *format_actual,
392 uint32_t *usage,
393 uint32_t *max_buffers)
394 {
395 int ret = OK;
396 QCameraStream *stream = NULL;
397 camera_mode_t myMode = (camera_mode_t)(CAMERA_MODE_2D|CAMERA_NONZSL_MODE);
398 ALOGE("%s : BEGIN",__func__);
399
400 ALOGE("Mymode Preview = %d",myMode);
401 stream = QCameraStream_preview::createInstance(
402 mCameraHandle->camera_handle,
403 mChannelId,
404 width,
405 height,
406 format,
407 mCameraHandle,
408 myMode);
409 ALOGE("%s: createInstance done", __func__);
410 if (!stream) {
411 ALOGE("%s: error - can't creat preview stream!", __func__);
412 return BAD_VALUE;
413 }
414
415 stream->setPreviewWindow(stream_ops);
416 *stream_id = stream->getStreamId();
417 *max_buffers= stream->getMaxBuffers();
418 ALOGE("%s: stream_id = %d\n", __func__, *stream_id);
419 *usage = GRALLOC_USAGE_HW_CAMERA_WRITE | CAMERA_GRALLOC_HEAP_ID
420 | CAMERA_GRALLOC_FALLBACK_HEAP_ID;
421 /* Set to an arbitrary format SUPPORTED by gralloc */
422 //*format_actual = HAL_PIXEL_FORMAT_YCbCr_422_SP;
423 *format_actual = HAL_PIXEL_FORMAT_YCrCb_420_SP;
424 /*TODO: For hardware encoder, add CAMERA_GRALLOC_CACHING_ID */
425 stream->setHALCameraControl(this);
426
427 ALOGV("%s : END",__func__);
428 return ret;
429 }
430
register_stream_buffers(uint32_t stream_id,int num_buffers,buffer_handle_t * buffers)431 int QCameraHardwareInterface::register_stream_buffers(
432 uint32_t stream_id, int num_buffers,
433 buffer_handle_t *buffers)
434 {
435 struct private_handle_t *private_handle =
436 (struct private_handle_t *)buffers[0];
437 QCameraStream_preview *stream = (QCameraStream_preview *)
438 QCameraStream::getStreamAtId(stream_id);
439
440 if(!stream) {
441 ALOGE("%s: Request for unknown stream",__func__);
442 return BAD_VALUE;
443 }
444
445 if(NO_ERROR!=stream->registerStreamBuffers(num_buffers, buffers)) {
446 ALOGE("%s:registerStreamBuffers failed",__func__);
447 return BAD_VALUE;
448 }
449
450 return NO_ERROR;
451 }
452
release_stream(uint32_t stream_id)453 int QCameraHardwareInterface::release_stream(uint32_t stream_id)
454 {
455 QCameraStream *stream = QCameraStream::getStreamAtId(stream_id);
456
457 QCameraStream_preview::deleteInstance(stream);
458
459 return OK;
460 }
461
allocate_reprocess_stream(uint32_t width,uint32_t height,uint32_t format,const camera2_stream_in_ops_t * reprocess_stream_ops,uint32_t * stream_id,uint32_t * consumer_usage,uint32_t * max_buffers)462 int QCameraHardwareInterface::allocate_reprocess_stream(
463 uint32_t width,
464 uint32_t height,
465 uint32_t format,
466 const camera2_stream_in_ops_t *reprocess_stream_ops,
467 uint32_t *stream_id,
468 uint32_t *consumer_usage,
469 uint32_t *max_buffers)
470 {
471 return INVALID_OPERATION;
472 }
473
release_reprocess_stream(uint32_t stream_id)474 int QCameraHardwareInterface::release_reprocess_stream(uint32_t stream_id)
475 {
476 return INVALID_OPERATION;
477 }
478
get_metadata_vendor_tag_ops(vendor_tag_query_ops_t ** ops)479 int QCameraHardwareInterface::get_metadata_vendor_tag_ops(vendor_tag_query_ops_t **ops)
480 {
481 *ops = NULL;
482 return OK;
483 }
484
set_notify_callback(camera2_notify_callback notify_cb,void * user)485 int QCameraHardwareInterface::set_notify_callback(camera2_notify_callback notify_cb,
486 void *user)
487 {
488 mNotifyCb = notify_cb;
489 mNotifyUserPtr = user;
490 return OK;
491 }
492 }; // namespace android
493