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