1 /*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
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
18
19
20 #define LOG_TAG "CameraHAL"
21
22
23 #include "CameraHal.h"
24 #include "VideoMetadata.h"
25 #include "Encoder_libjpeg.h"
26 #include <MetadataBufferType.h>
27 #include <ui/GraphicBuffer.h>
28 #include <ui/GraphicBufferMapper.h>
29 #include "NV12_resize.h"
30
31 namespace android {
32
33 const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
34 KeyedVector<void*, sp<Encoder_libjpeg> > gEncoderQueue;
35
AppCallbackNotifierEncoderCallback(void * main_jpeg,void * thumb_jpeg,CameraFrame::FrameType type,void * cookie1,void * cookie2,void * cookie3,bool canceled)36 void AppCallbackNotifierEncoderCallback(void* main_jpeg,
37 void* thumb_jpeg,
38 CameraFrame::FrameType type,
39 void* cookie1,
40 void* cookie2,
41 void* cookie3,
42 bool canceled)
43 {
44 if (cookie1 && !canceled) {
45 AppCallbackNotifier* cb = (AppCallbackNotifier*) cookie1;
46 cb->EncoderDoneCb(main_jpeg, thumb_jpeg, type, cookie2, cookie3);
47 }
48
49 if (main_jpeg) {
50 free(main_jpeg);
51 }
52
53 if (thumb_jpeg) {
54 if (((Encoder_libjpeg::params *) thumb_jpeg)->dst) {
55 free(((Encoder_libjpeg::params *) thumb_jpeg)->dst);
56 }
57 free(thumb_jpeg);
58 }
59 }
60
61 /*--------------------NotificationHandler Class STARTS here-----------------------------*/
62
EncoderDoneCb(void * main_jpeg,void * thumb_jpeg,CameraFrame::FrameType type,void * cookie1,void * cookie2)63 void AppCallbackNotifier::EncoderDoneCb(void* main_jpeg, void* thumb_jpeg, CameraFrame::FrameType type, void* cookie1, void* cookie2)
64 {
65 camera_memory_t* encoded_mem = NULL;
66 Encoder_libjpeg::params *main_param = NULL, *thumb_param = NULL;
67 size_t jpeg_size;
68 uint8_t* src = NULL;
69 sp<Encoder_libjpeg> encoder = NULL;
70
71 LOG_FUNCTION_NAME;
72
73 camera_memory_t* picture = NULL;
74
75 {
76 Mutex::Autolock lock(mLock);
77
78 if (!main_jpeg) {
79 goto exit;
80 }
81
82 encoded_mem = (camera_memory_t*) cookie1;
83 main_param = (Encoder_libjpeg::params *) main_jpeg;
84 jpeg_size = main_param->jpeg_size;
85 src = main_param->src;
86
87 if(encoded_mem && encoded_mem->data && (jpeg_size > 0)) {
88 if (cookie2) {
89 ExifElementsTable* exif = (ExifElementsTable*) cookie2;
90 Section_t* exif_section = NULL;
91
92 exif->insertExifToJpeg((unsigned char*) encoded_mem->data, jpeg_size);
93
94 if(thumb_jpeg) {
95 thumb_param = (Encoder_libjpeg::params *) thumb_jpeg;
96 exif->insertExifThumbnailImage((const char*)thumb_param->dst,
97 (int)thumb_param->jpeg_size);
98 }
99
100 exif_section = FindSection(M_EXIF);
101
102 if (exif_section) {
103 picture = mRequestMemory(-1, jpeg_size + exif_section->Size, 1, NULL);
104 if (picture && picture->data) {
105 exif->saveJpeg((unsigned char*) picture->data, jpeg_size + exif_section->Size);
106 }
107 }
108 delete exif;
109 cookie2 = NULL;
110 } else {
111 picture = mRequestMemory(-1, jpeg_size, 1, NULL);
112 if (picture && picture->data) {
113 memcpy(picture->data, encoded_mem->data, jpeg_size);
114 }
115 }
116 }
117 } // scope for mutex lock
118
119 if (!mRawAvailable) {
120 dummyRaw();
121 } else {
122 mRawAvailable = false;
123 }
124
125 // Send the callback to the application only if the notifier is started and the message is enabled
126 if(picture && (mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED) &&
127 (mCameraHal->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE)))
128 {
129 Mutex::Autolock lock(mBurstLock);
130 #if 0 //TODO: enable burst mode later
131 if ( mBurst )
132 {
133 `(CAMERA_MSG_BURST_IMAGE, JPEGPictureMemBase, mCallbackCookie);
134 }
135 else
136 #endif
137 {
138 mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, picture, 0, NULL, mCallbackCookie);
139 }
140 }
141
142 exit:
143
144 if (picture) {
145 picture->release(picture);
146 }
147
148 if (mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) {
149 if (encoded_mem) {
150 encoded_mem->release(encoded_mem);
151 }
152 if (cookie2) {
153 delete (ExifElementsTable*) cookie2;
154 }
155 encoder = gEncoderQueue.valueFor(src);
156 if (encoder.get()) {
157 gEncoderQueue.removeItem(src);
158 encoder.clear();
159 }
160 mFrameProvider->returnFrame(src, type);
161 }
162
163 LOG_FUNCTION_NAME_EXIT;
164 }
165
166 /**
167 * NotificationHandler class
168 */
169
170 ///Initialization function for AppCallbackNotifier
initialize()171 status_t AppCallbackNotifier::initialize()
172 {
173 LOG_FUNCTION_NAME;
174
175 mMeasurementEnabled = false;
176
177 ///Create the app notifier thread
178 mNotificationThread = new NotificationThread(this);
179 if(!mNotificationThread.get())
180 {
181 CAMHAL_LOGEA("Couldn't create Notification thread");
182 return NO_MEMORY;
183 }
184
185 ///Start the display thread
186 status_t ret = mNotificationThread->run("NotificationThread", PRIORITY_URGENT_DISPLAY);
187 if(ret!=NO_ERROR)
188 {
189 CAMHAL_LOGEA("Couldn't run NotificationThread");
190 mNotificationThread.clear();
191 return ret;
192 }
193
194 mUseMetaDataBufferMode = true;
195 mRawAvailable = false;
196
197 LOG_FUNCTION_NAME_EXIT;
198
199 return ret;
200 }
201
setCallbacks(CameraHal * cameraHal,camera_notify_callback notify_cb,camera_data_callback data_cb,camera_data_timestamp_callback data_cb_timestamp,camera_request_memory get_memory,void * user)202 void AppCallbackNotifier::setCallbacks(CameraHal* cameraHal,
203 camera_notify_callback notify_cb,
204 camera_data_callback data_cb,
205 camera_data_timestamp_callback data_cb_timestamp,
206 camera_request_memory get_memory,
207 void *user)
208 {
209 Mutex::Autolock lock(mLock);
210
211 LOG_FUNCTION_NAME;
212
213 mCameraHal = cameraHal;
214 mNotifyCb = notify_cb;
215 mDataCb = data_cb;
216 mDataCbTimestamp = data_cb_timestamp;
217 mRequestMemory = get_memory;
218 mCallbackCookie = user;
219
220 LOG_FUNCTION_NAME_EXIT;
221 }
222
setMeasurements(bool enable)223 void AppCallbackNotifier::setMeasurements(bool enable)
224 {
225 Mutex::Autolock lock(mLock);
226
227 LOG_FUNCTION_NAME;
228
229 mMeasurementEnabled = enable;
230
231 if ( enable )
232 {
233 mFrameProvider->enableFrameNotification(CameraFrame::FRAME_DATA_SYNC);
234 }
235
236 LOG_FUNCTION_NAME_EXIT;
237 }
238
239
240 //All sub-components of Camera HAL call this whenever any error happens
errorNotify(int error)241 void AppCallbackNotifier::errorNotify(int error)
242 {
243 LOG_FUNCTION_NAME;
244
245 CAMHAL_LOGEB("AppCallbackNotifier received error %d", error);
246
247 // If it is a fatal error abort here!
248 if((error == CAMERA_ERROR_FATAL) || (error == CAMERA_ERROR_HARD)) {
249 //We kill media server if we encounter these errors as there is
250 //no point continuing and apps also don't handle errors other
251 //than media server death always.
252 abort();
253 return;
254 }
255
256 if ( ( NULL != mCameraHal ) &&
257 ( NULL != mNotifyCb ) &&
258 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ERROR) ) )
259 {
260 CAMHAL_LOGEB("AppCallbackNotifier mNotifyCb %d", error);
261 mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie);
262 }
263
264 LOG_FUNCTION_NAME_EXIT;
265 }
266
notificationThread()267 bool AppCallbackNotifier::notificationThread()
268 {
269 bool shouldLive = true;
270 status_t ret;
271
272 LOG_FUNCTION_NAME;
273
274 //CAMHAL_LOGDA("Notification Thread waiting for message");
275 ret = TIUTILS::MessageQueue::waitForMsg(&mNotificationThread->msgQ(),
276 &mEventQ,
277 &mFrameQ,
278 AppCallbackNotifier::NOTIFIER_TIMEOUT);
279
280 //CAMHAL_LOGDA("Notification Thread received message");
281
282 if (mNotificationThread->msgQ().hasMsg()) {
283 ///Received a message from CameraHal, process it
284 CAMHAL_LOGDA("Notification Thread received message from Camera HAL");
285 shouldLive = processMessage();
286 if(!shouldLive) {
287 CAMHAL_LOGDA("Notification Thread exiting.");
288 return shouldLive;
289 }
290 }
291
292 if(mEventQ.hasMsg()) {
293 ///Received an event from one of the event providers
294 CAMHAL_LOGDA("Notification Thread received an event from event provider (CameraAdapter)");
295 notifyEvent();
296 }
297
298 if(mFrameQ.hasMsg()) {
299 ///Received a frame from one of the frame providers
300 //CAMHAL_LOGDA("Notification Thread received a frame from frame provider (CameraAdapter)");
301 notifyFrame();
302 }
303
304 LOG_FUNCTION_NAME_EXIT;
305 return shouldLive;
306 }
307
notifyEvent()308 void AppCallbackNotifier::notifyEvent()
309 {
310 ///Receive and send the event notifications to app
311 TIUTILS::Message msg;
312 LOG_FUNCTION_NAME;
313 {
314 Mutex::Autolock lock(mLock);
315 if(!mEventQ.isEmpty()) {
316 mEventQ.get(&msg);
317 } else {
318 return;
319 }
320 }
321 bool ret = true;
322 CameraHalEvent *evt = NULL;
323 CameraHalEvent::FocusEventData *focusEvtData;
324 CameraHalEvent::ZoomEventData *zoomEvtData;
325 CameraHalEvent::FaceEventData faceEvtData;
326
327 if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED)
328 {
329 return;
330 }
331
332 switch(msg.command)
333 {
334 case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT:
335
336 evt = ( CameraHalEvent * ) msg.arg1;
337
338 if ( NULL == evt )
339 {
340 CAMHAL_LOGEA("Invalid CameraHalEvent");
341 return;
342 }
343
344 switch(evt->mEventType)
345 {
346 case CameraHalEvent::EVENT_SHUTTER:
347
348 if ( ( NULL != mCameraHal ) &&
349 ( NULL != mNotifyCb ) &&
350 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_SHUTTER) ) )
351 {
352 mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
353 }
354 mRawAvailable = false;
355
356 break;
357
358 case CameraHalEvent::EVENT_FOCUS_LOCKED:
359 case CameraHalEvent::EVENT_FOCUS_ERROR:
360 focusEvtData = &evt->mEventData->focusEvent;
361 if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_SUCCESS ) &&
362 ( NULL != mCameraHal ) &&
363 ( NULL != mNotifyCb ) &&
364 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) )
365 {
366 mCameraHal->disableMsgType(CAMERA_MSG_FOCUS);
367 mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
368 }
369 else if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_FAIL ) &&
370 ( NULL != mCameraHal ) &&
371 ( NULL != mNotifyCb ) &&
372 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) )
373 {
374 mCameraHal->disableMsgType(CAMERA_MSG_FOCUS);
375 mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
376 }
377 else if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_PENDING ) &&
378 ( NULL != mCameraHal ) &&
379 ( NULL != mNotifyCb ) &&
380 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS_MOVE) ) )
381 {
382 mNotifyCb(CAMERA_MSG_FOCUS_MOVE, true, 0, mCallbackCookie);
383 }
384 else if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_DONE ) &&
385 ( NULL != mCameraHal ) &&
386 ( NULL != mNotifyCb ) &&
387 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS_MOVE) ) )
388 {
389 mNotifyCb(CAMERA_MSG_FOCUS_MOVE, false, 0, mCallbackCookie);
390 }
391
392 break;
393
394 case CameraHalEvent::EVENT_ZOOM_INDEX_REACHED:
395
396 zoomEvtData = &evt->mEventData->zoomEvent;
397
398 if ( ( NULL != mCameraHal ) &&
399 ( NULL != mNotifyCb) &&
400 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ZOOM) ) )
401 {
402 mNotifyCb(CAMERA_MSG_ZOOM, zoomEvtData->currentZoomIndex, zoomEvtData->targetZoomIndexReached, mCallbackCookie);
403 }
404
405 break;
406
407 case CameraHalEvent::EVENT_FACE:
408
409 faceEvtData = evt->mEventData->faceEvent;
410
411 if ( ( NULL != mCameraHal ) &&
412 ( NULL != mNotifyCb) &&
413 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) ) )
414 {
415 // WA for an issue inside CameraService
416 camera_memory_t *tmpBuffer = mRequestMemory(-1, 1, 1, NULL);
417
418 mDataCb(CAMERA_MSG_PREVIEW_METADATA,
419 tmpBuffer,
420 0,
421 faceEvtData->getFaceResult(),
422 mCallbackCookie);
423
424 faceEvtData.clear();
425
426 if ( NULL != tmpBuffer ) {
427 tmpBuffer->release(tmpBuffer);
428 }
429
430 }
431
432 break;
433
434 case CameraHalEvent::ALL_EVENTS:
435 break;
436 default:
437 break;
438 }
439
440 break;
441 }
442
443 if ( NULL != evt )
444 {
445 delete evt;
446 }
447
448
449 LOG_FUNCTION_NAME_EXIT;
450
451 }
452
alignYV12(int width,int height,int & yStride,int & uvStride,int & ySize,int & uvSize,int & size)453 static void alignYV12(int width,
454 int height,
455 int &yStride,
456 int &uvStride,
457 int &ySize,
458 int &uvSize,
459 int &size)
460 {
461 yStride = ( width + 0xF ) & ~0xF;
462 uvStride = ( yStride / 2 + 0xF ) & ~0xF;
463 ySize = yStride * height;
464 uvSize = uvStride * height / 2;
465 size = ySize + uvSize * 2;
466 }
467
copy2Dto1D(void * dst,void * src,int width,int height,size_t stride,uint32_t offset,unsigned int bytesPerPixel,size_t length,const char * pixelFormat)468 static void copy2Dto1D(void *dst,
469 void *src,
470 int width,
471 int height,
472 size_t stride,
473 uint32_t offset,
474 unsigned int bytesPerPixel,
475 size_t length,
476 const char *pixelFormat)
477 {
478 unsigned int alignedRow, row;
479 unsigned char *bufferDst, *bufferSrc;
480 unsigned char *bufferDstEnd, *bufferSrcEnd;
481 uint16_t *bufferSrc_UV;
482
483 unsigned int *y_uv = (unsigned int *)src;
484
485 CAMHAL_LOGVB("copy2Dto1D() y= %p ; uv=%p.",y_uv[0], y_uv[1]);
486 CAMHAL_LOGVB("pixelFormat= %s; offset=%d", pixelFormat,offset);
487
488 if (pixelFormat!=NULL) {
489 if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
490 bytesPerPixel = 2;
491 bufferSrc = ( unsigned char * ) y_uv[0] + offset;
492 uint32_t xOff = offset % stride;
493 uint32_t yOff = offset / stride;
494 uint8_t *bufferSrcUV = ((uint8_t*)y_uv[1] + (stride/2)*yOff + xOff);
495 uint8_t *bufferSrcUVEven = bufferSrcUV;
496
497 uint8_t *bufferDstY = ( uint8_t * ) dst;
498 uint8_t *bufferDstU = bufferDstY + 1;
499 uint8_t *bufferDstV = bufferDstY + 3;
500
501 // going to convert from NV12 here and return
502 for ( int i = 0 ; i < height; i ++ ) {
503 for ( int j = 0 ; j < width / 2 ; j++ ) {
504
505 // Y
506 *bufferDstY = *bufferSrc;
507 bufferSrc++;
508 bufferDstY += 2;
509
510 *bufferDstY = *bufferSrc;
511 bufferSrc++;
512 bufferDstY += 2;
513
514 // V
515 *bufferDstV = *(bufferSrcUV + 1);
516 bufferDstV += 4;
517
518 // U
519 *bufferDstU = *bufferSrcUV;
520 bufferDstU += 4;
521
522 bufferSrcUV += 2;
523 }
524 if ( i % 2 ) {
525 bufferSrcUV += ( stride - width);
526 bufferSrcUVEven = bufferSrcUV;
527 } else {
528 bufferSrcUV = bufferSrcUVEven;
529 }
530 bufferSrc += ( stride - width);
531 }
532
533 return;
534 } else if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
535 strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
536 bytesPerPixel = 1;
537 bufferDst = ( unsigned char * ) dst;
538 bufferDstEnd = ( unsigned char * ) dst + width*height*bytesPerPixel;
539 bufferSrc = ( unsigned char * ) y_uv[0] + offset;
540 bufferSrcEnd = ( unsigned char * ) ( ( size_t ) y_uv[0] + length + offset);
541 row = width*bytesPerPixel;
542 alignedRow = stride-width;
543 int stride_bytes = stride / 8;
544 uint32_t xOff = offset % stride;
545 uint32_t yOff = offset / stride;
546
547 // going to convert from NV12 here and return
548 // Step 1: Y plane: iterate through each row and copy
549 for ( int i = 0 ; i < height ; i++) {
550 memcpy(bufferDst, bufferSrc, row);
551 bufferSrc += stride;
552 bufferDst += row;
553 if ( ( bufferSrc > bufferSrcEnd ) || ( bufferDst > bufferDstEnd ) ) {
554 break;
555 }
556 }
557
558 bufferSrc_UV = ( uint16_t * ) ((uint8_t*)y_uv[1] + (stride/2)*yOff + xOff);
559
560 if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
561 uint16_t *bufferDst_UV;
562
563 // Step 2: UV plane: convert NV12 to NV21 by swapping U & V
564 bufferDst_UV = (uint16_t *) (((uint8_t*)dst)+row*height);
565
566 for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) {
567 int n = width;
568 asm volatile (
569 " pld [%[src], %[src_stride], lsl #2] \n\t"
570 " cmp %[n], #32 \n\t"
571 " blt 1f \n\t"
572 "0: @ 32 byte swap \n\t"
573 " sub %[n], %[n], #32 \n\t"
574 " vld2.8 {q0, q1} , [%[src]]! \n\t"
575 " vswp q0, q1 \n\t"
576 " cmp %[n], #32 \n\t"
577 " vst2.8 {q0,q1},[%[dst]]! \n\t"
578 " bge 0b \n\t"
579 "1: @ Is there enough data? \n\t"
580 " cmp %[n], #16 \n\t"
581 " blt 3f \n\t"
582 "2: @ 16 byte swap \n\t"
583 " sub %[n], %[n], #16 \n\t"
584 " vld2.8 {d0, d1} , [%[src]]! \n\t"
585 " vswp d0, d1 \n\t"
586 " cmp %[n], #16 \n\t"
587 " vst2.8 {d0,d1},[%[dst]]! \n\t"
588 " bge 2b \n\t"
589 "3: @ Is there enough data? \n\t"
590 " cmp %[n], #8 \n\t"
591 " blt 5f \n\t"
592 "4: @ 8 byte swap \n\t"
593 " sub %[n], %[n], #8 \n\t"
594 " vld2.8 {d0, d1} , [%[src]]! \n\t"
595 " vswp d0, d1 \n\t"
596 " cmp %[n], #8 \n\t"
597 " vst2.8 {d0[0],d1[0]},[%[dst]]! \n\t"
598 " bge 4b \n\t"
599 "5: @ end \n\t"
600 #ifdef NEEDS_ARM_ERRATA_754319_754320
601 " vmov s0,s0 @ add noop for errata item \n\t"
602 #endif
603 : [dst] "+r" (bufferDst_UV), [src] "+r" (bufferSrc_UV), [n] "+r" (n)
604 : [src_stride] "r" (stride_bytes)
605 : "cc", "memory", "q0", "q1"
606 );
607 }
608 } else if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
609 uint16_t *bufferDst_U;
610 uint16_t *bufferDst_V;
611
612 // Step 2: UV plane: convert NV12 to YV12 by de-interleaving U & V
613 // TODO(XXX): This version of CameraHal assumes NV12 format it set at
614 // camera adapter to support YV12. Need to address for
615 // USBCamera
616
617 int yStride, uvStride, ySize, uvSize, size;
618 alignYV12(width, height, yStride, uvStride, ySize, uvSize, size);
619
620 bufferDst_V = (uint16_t *) (((uint8_t*)dst) + ySize);
621 bufferDst_U = (uint16_t *) (((uint8_t*)dst) + ySize + uvSize);
622 int inc = (uvStride - width/2)/2;
623
624 for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) {
625 int n = width;
626 asm volatile (
627 " pld [%[src], %[src_stride], lsl #2] \n\t"
628 " cmp %[n], #32 \n\t"
629 " blt 1f \n\t"
630 "0: @ 32 byte swap \n\t"
631 " sub %[n], %[n], #32 \n\t"
632 " vld2.8 {q0, q1} , [%[src]]! \n\t"
633 " cmp %[n], #32 \n\t"
634 " vst1.8 {q1},[%[dst_v]]! \n\t"
635 " vst1.8 {q0},[%[dst_u]]! \n\t"
636 " bge 0b \n\t"
637 "1: @ Is there enough data? \n\t"
638 " cmp %[n], #16 \n\t"
639 " blt 3f \n\t"
640 "2: @ 16 byte swap \n\t"
641 " sub %[n], %[n], #16 \n\t"
642 " vld2.8 {d0, d1} , [%[src]]! \n\t"
643 " cmp %[n], #16 \n\t"
644 " vst1.8 {d1},[%[dst_v]]! \n\t"
645 " vst1.8 {d0},[%[dst_u]]! \n\t"
646 " bge 2b \n\t"
647 "3: @ Is there enough data? \n\t"
648 " cmp %[n], #8 \n\t"
649 " blt 5f \n\t"
650 "4: @ 8 byte swap \n\t"
651 " sub %[n], %[n], #8 \n\t"
652 " vld2.8 {d0, d1} , [%[src]]! \n\t"
653 " cmp %[n], #8 \n\t"
654 " vst1.8 {d1[0]},[%[dst_v]]! \n\t"
655 " vst1.8 {d0[0]},[%[dst_u]]! \n\t"
656 " bge 4b \n\t"
657 "5: @ end \n\t"
658 #ifdef NEEDS_ARM_ERRATA_754319_754320
659 " vmov s0,s0 @ add noop for errata item \n\t"
660 #endif
661 : [dst_u] "+r" (bufferDst_U), [dst_v] "+r" (bufferDst_V),
662 [src] "+r" (bufferSrc_UV), [n] "+r" (n)
663 : [src_stride] "r" (stride_bytes)
664 : "cc", "memory", "q0", "q1"
665 );
666
667 bufferDst_U += inc;
668 bufferDst_V += inc;
669 }
670
671 }
672 return ;
673
674 } else if(strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
675 bytesPerPixel = 2;
676 }
677 }
678
679 bufferDst = ( unsigned char * ) dst;
680 bufferSrc = ( unsigned char * ) y_uv[0];
681 row = width*bytesPerPixel;
682 alignedRow = ( row + ( stride -1 ) ) & ( ~ ( stride -1 ) );
683
684 //iterate through each row
685 for ( int i = 0 ; i < height ; i++, bufferSrc += alignedRow, bufferDst += row) {
686 memcpy(bufferDst, bufferSrc, row);
687 }
688 }
689
copyAndSendPictureFrame(CameraFrame * frame,int32_t msgType)690 void AppCallbackNotifier::copyAndSendPictureFrame(CameraFrame* frame, int32_t msgType)
691 {
692 camera_memory_t* picture = NULL;
693 void *dest = NULL, *src = NULL;
694
695 // scope for lock
696 {
697 Mutex::Autolock lock(mLock);
698
699 if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) {
700 goto exit;
701 }
702
703 picture = mRequestMemory(-1, frame->mLength, 1, NULL);
704
705 if (NULL != picture) {
706 dest = picture->data;
707 if (NULL != dest) {
708 src = (void *) ((unsigned int) frame->mBuffer + frame->mOffset);
709 memcpy(dest, src, frame->mLength);
710 }
711 }
712 }
713
714 exit:
715 mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType);
716
717 if(picture) {
718 if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) &&
719 mCameraHal->msgTypeEnabled(msgType)) {
720 mDataCb(msgType, picture, 0, NULL, mCallbackCookie);
721 }
722 picture->release(picture);
723 }
724 }
725
copyAndSendPreviewFrame(CameraFrame * frame,int32_t msgType)726 void AppCallbackNotifier::copyAndSendPreviewFrame(CameraFrame* frame, int32_t msgType)
727 {
728 camera_memory_t* picture = NULL;
729 void* dest = NULL;
730
731 // scope for lock
732 {
733 Mutex::Autolock lock(mLock);
734
735 if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) {
736 goto exit;
737 }
738
739 if (!mPreviewMemory || !frame->mBuffer) {
740 CAMHAL_LOGDA("Error! One of the buffer is NULL");
741 goto exit;
742 }
743
744
745 dest = (void*) mPreviewBufs[mPreviewBufCount];
746
747 CAMHAL_LOGVB("%d:copy2Dto1D(%p, %p, %d, %d, %d, %d, %d,%s)",
748 __LINE__,
749 buf,
750 frame->mBuffer,
751 frame->mWidth,
752 frame->mHeight,
753 frame->mAlignment,
754 2,
755 frame->mLength,
756 mPreviewPixelFormat);
757
758 if ( NULL != dest ) {
759 // data sync frames don't need conversion
760 if (CameraFrame::FRAME_DATA_SYNC == frame->mFrameType) {
761 if ( (mPreviewMemory->size / MAX_BUFFERS) >= frame->mLength ) {
762 memcpy(dest, (void*) frame->mBuffer, frame->mLength);
763 } else {
764 memset(dest, 0, (mPreviewMemory->size / MAX_BUFFERS));
765 }
766 } else {
767 if ((NULL == frame->mYuv[0]) || (NULL == frame->mYuv[1])){
768 CAMHAL_LOGEA("Error! One of the YUV Pointer is NULL");
769 goto exit;
770 }
771 else{
772 copy2Dto1D(dest,
773 frame->mYuv,
774 frame->mWidth,
775 frame->mHeight,
776 frame->mAlignment,
777 frame->mOffset,
778 2,
779 frame->mLength,
780 mPreviewPixelFormat);
781 }
782 }
783 }
784 }
785
786 exit:
787 mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType);
788
789 if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) &&
790 mCameraHal->msgTypeEnabled(msgType) &&
791 (dest != NULL)) {
792 mDataCb(msgType, mPreviewMemory, mPreviewBufCount, NULL, mCallbackCookie);
793 }
794
795 // increment for next buffer
796 mPreviewBufCount = (mPreviewBufCount + 1) % AppCallbackNotifier::MAX_BUFFERS;
797 }
798
dummyRaw()799 status_t AppCallbackNotifier::dummyRaw()
800 {
801 LOG_FUNCTION_NAME;
802
803 if ( NULL == mRequestMemory ) {
804 CAMHAL_LOGEA("Can't allocate memory for dummy raw callback!");
805 return NO_INIT;
806 }
807
808 if ( ( NULL != mCameraHal ) &&
809 ( NULL != mDataCb) &&
810 ( NULL != mNotifyCb ) ){
811
812 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ) {
813 camera_memory_t *dummyRaw = mRequestMemory(-1, 1, 1, NULL);
814
815 if ( NULL == dummyRaw ) {
816 CAMHAL_LOGEA("Dummy raw buffer allocation failed!");
817 return NO_MEMORY;
818 }
819
820 mDataCb(CAMERA_MSG_RAW_IMAGE, dummyRaw, 0, NULL, mCallbackCookie);
821
822 dummyRaw->release(dummyRaw);
823 } else if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) {
824 mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
825 }
826 }
827
828 LOG_FUNCTION_NAME_EXIT;
829
830 return NO_ERROR;
831 }
832
notifyFrame()833 void AppCallbackNotifier::notifyFrame()
834 {
835 ///Receive and send the frame notifications to app
836 TIUTILS::Message msg;
837 CameraFrame *frame;
838 MemoryHeapBase *heap;
839 MemoryBase *buffer = NULL;
840 sp<MemoryBase> memBase;
841 void *buf = NULL;
842
843 LOG_FUNCTION_NAME;
844
845 {
846 Mutex::Autolock lock(mLock);
847 if(!mFrameQ.isEmpty()) {
848 mFrameQ.get(&msg);
849 } else {
850 return;
851 }
852 }
853
854 bool ret = true;
855
856 frame = NULL;
857 switch(msg.command)
858 {
859 case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME:
860
861 frame = (CameraFrame *) msg.arg1;
862 if(!frame)
863 {
864 break;
865 }
866
867 if ( (CameraFrame::RAW_FRAME == frame->mFrameType )&&
868 ( NULL != mCameraHal ) &&
869 ( NULL != mDataCb) &&
870 ( NULL != mNotifyCb ) )
871 {
872
873 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) )
874 {
875 #ifdef COPY_IMAGE_BUFFER
876 copyAndSendPictureFrame(frame, CAMERA_MSG_RAW_IMAGE);
877 #else
878 //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
879 #endif
880 }
881 else {
882 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) {
883 mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
884 }
885 mFrameProvider->returnFrame(frame->mBuffer,
886 (CameraFrame::FrameType) frame->mFrameType);
887 }
888
889 mRawAvailable = true;
890
891 }
892 else if ( (CameraFrame::IMAGE_FRAME == frame->mFrameType) &&
893 (NULL != mCameraHal) &&
894 (NULL != mDataCb) &&
895 (CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG & frame->mQuirks) )
896 {
897
898 int encode_quality = 100, tn_quality = 100;
899 int tn_width, tn_height;
900 unsigned int current_snapshot = 0;
901 Encoder_libjpeg::params *main_jpeg = NULL, *tn_jpeg = NULL;
902 void* exif_data = NULL;
903 camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
904
905 if(raw_picture) {
906 buf = raw_picture->data;
907 }
908
909 CameraParameters parameters;
910 char *params = mCameraHal->getParameters();
911 const String8 strParams(params);
912 parameters.unflatten(strParams);
913
914 encode_quality = parameters.getInt(CameraParameters::KEY_JPEG_QUALITY);
915 if (encode_quality < 0 || encode_quality > 100) {
916 encode_quality = 100;
917 }
918
919 tn_quality = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
920 if (tn_quality < 0 || tn_quality > 100) {
921 tn_quality = 100;
922 }
923
924 if (CameraFrame::HAS_EXIF_DATA & frame->mQuirks) {
925 exif_data = frame->mCookie2;
926 }
927
928 main_jpeg = (Encoder_libjpeg::params*)
929 malloc(sizeof(Encoder_libjpeg::params));
930
931 // Video snapshot with LDCNSF on adds a few bytes start offset
932 // and a few bytes on every line. They must be skipped.
933 int rightCrop = frame->mAlignment/2 - frame->mWidth;
934
935 CAMHAL_LOGDB("Video snapshot right crop = %d", rightCrop);
936 CAMHAL_LOGDB("Video snapshot offset = %d", frame->mOffset);
937
938 if (main_jpeg) {
939 main_jpeg->src = (uint8_t*) frame->mBuffer;
940 main_jpeg->src_size = frame->mLength;
941 main_jpeg->dst = (uint8_t*) buf;
942 main_jpeg->dst_size = frame->mLength;
943 main_jpeg->quality = encode_quality;
944 main_jpeg->in_width = frame->mAlignment/2; // use stride here
945 main_jpeg->in_height = frame->mHeight;
946 main_jpeg->out_width = frame->mAlignment/2;
947 main_jpeg->out_height = frame->mHeight;
948 main_jpeg->right_crop = rightCrop;
949 main_jpeg->start_offset = frame->mOffset;
950 main_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV422I;
951 }
952
953 tn_width = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
954 tn_height = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
955
956 if ((tn_width > 0) && (tn_height > 0)) {
957 tn_jpeg = (Encoder_libjpeg::params*)
958 malloc(sizeof(Encoder_libjpeg::params));
959 // if malloc fails just keep going and encode main jpeg
960 if (!tn_jpeg) {
961 tn_jpeg = NULL;
962 }
963 }
964
965 if (tn_jpeg) {
966 int width, height;
967 parameters.getPreviewSize(&width,&height);
968 current_snapshot = (mPreviewBufCount + MAX_BUFFERS - 1) % MAX_BUFFERS;
969 tn_jpeg->src = (uint8_t*) mPreviewBufs[current_snapshot];
970 tn_jpeg->src_size = mPreviewMemory->size / MAX_BUFFERS;
971 tn_jpeg->dst = (uint8_t*) malloc(tn_jpeg->src_size);
972 tn_jpeg->dst_size = tn_jpeg->src_size;
973 tn_jpeg->quality = tn_quality;
974 tn_jpeg->in_width = width;
975 tn_jpeg->in_height = height;
976 tn_jpeg->out_width = tn_width;
977 tn_jpeg->out_height = tn_height;
978 tn_jpeg->right_crop = 0;
979 tn_jpeg->start_offset = 0;
980 tn_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV420SP;;
981 }
982
983 sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg,
984 tn_jpeg,
985 AppCallbackNotifierEncoderCallback,
986 (CameraFrame::FrameType)frame->mFrameType,
987 this,
988 raw_picture,
989 exif_data);
990 encoder->run();
991 gEncoderQueue.add(frame->mBuffer, encoder);
992 encoder.clear();
993 if (params != NULL)
994 {
995 mCameraHal->putParameters(params);
996 }
997 }
998 else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) &&
999 ( NULL != mCameraHal ) &&
1000 ( NULL != mDataCb) )
1001 {
1002
1003 // CTS, MTS requirements: Every 'takePicture()' call
1004 // who registers a raw callback should receive one
1005 // as well. This is not always the case with
1006 // CameraAdapters though.
1007 if (!mRawAvailable) {
1008 dummyRaw();
1009 } else {
1010 mRawAvailable = false;
1011 }
1012
1013 #ifdef COPY_IMAGE_BUFFER
1014 {
1015 Mutex::Autolock lock(mBurstLock);
1016 #if 0 //TODO: enable burst mode later
1017 if ( mBurst )
1018 {
1019 `(CAMERA_MSG_BURST_IMAGE, JPEGPictureMemBase, mCallbackCookie);
1020 }
1021 else
1022 #endif
1023 {
1024 copyAndSendPictureFrame(frame, CAMERA_MSG_COMPRESSED_IMAGE);
1025 }
1026 }
1027 #else
1028 //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
1029 #endif
1030 }
1031 else if ( ( CameraFrame::VIDEO_FRAME_SYNC == frame->mFrameType ) &&
1032 ( NULL != mCameraHal ) &&
1033 ( NULL != mDataCb) &&
1034 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) ) )
1035 {
1036 mRecordingLock.lock();
1037 if(mRecording)
1038 {
1039 if(mUseMetaDataBufferMode)
1040 {
1041 camera_memory_t *videoMedatadaBufferMemory =
1042 (camera_memory_t *) mVideoMetadataBufferMemoryMap.valueFor((uint32_t) frame->mBuffer);
1043 video_metadata_t *videoMetadataBuffer = (video_metadata_t *) videoMedatadaBufferMemory->data;
1044
1045 if( (NULL == videoMedatadaBufferMemory) || (NULL == videoMetadataBuffer) || (NULL == frame->mBuffer) )
1046 {
1047 CAMHAL_LOGEA("Error! One of the video buffers is NULL");
1048 break;
1049 }
1050
1051 if ( mUseVideoBuffers )
1052 {
1053 int vBuf = mVideoMap.valueFor((uint32_t) frame->mBuffer);
1054 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
1055 Rect bounds;
1056 bounds.left = 0;
1057 bounds.top = 0;
1058 bounds.right = mVideoWidth;
1059 bounds.bottom = mVideoHeight;
1060
1061 void *y_uv[2];
1062 mapper.lock((buffer_handle_t)vBuf, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
1063
1064 structConvImage input = {frame->mWidth,
1065 frame->mHeight,
1066 4096,
1067 IC_FORMAT_YCbCr420_lp,
1068 (mmByte *)frame->mYuv[0],
1069 (mmByte *)frame->mYuv[1],
1070 frame->mOffset};
1071
1072 structConvImage output = {mVideoWidth,
1073 mVideoHeight,
1074 4096,
1075 IC_FORMAT_YCbCr420_lp,
1076 (mmByte *)y_uv[0],
1077 (mmByte *)y_uv[1],
1078 0};
1079
1080 VT_resizeFrame_Video_opt2_lp(&input, &output, NULL, 0);
1081 mapper.unlock((buffer_handle_t)vBuf);
1082 videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource;
1083 videoMetadataBuffer->handle = (void *)vBuf;
1084 videoMetadataBuffer->offset = 0;
1085 }
1086 else
1087 {
1088 videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource;
1089 videoMetadataBuffer->handle = frame->mBuffer;
1090 videoMetadataBuffer->offset = frame->mOffset;
1091 }
1092
1093 CAMHAL_LOGVB("mDataCbTimestamp : frame->mBuffer=0x%x, videoMetadataBuffer=0x%x, videoMedatadaBufferMemory=0x%x",
1094 frame->mBuffer, videoMetadataBuffer, videoMedatadaBufferMemory);
1095
1096 mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME,
1097 videoMedatadaBufferMemory, 0, mCallbackCookie);
1098 }
1099 else
1100 {
1101 //TODO: Need to revisit this, should ideally be mapping the TILER buffer using mRequestMemory
1102 camera_memory_t* fakebuf = mRequestMemory(-1, 4, 1, NULL);
1103 if( (NULL == fakebuf) || ( NULL == fakebuf->data) || ( NULL == frame->mBuffer))
1104 {
1105 CAMHAL_LOGEA("Error! One of the video buffers is NULL");
1106 break;
1107 }
1108
1109 fakebuf->data = frame->mBuffer;
1110 mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME, fakebuf, 0, mCallbackCookie);
1111 fakebuf->release(fakebuf);
1112 }
1113 }
1114 mRecordingLock.unlock();
1115
1116 }
1117 else if(( CameraFrame::SNAPSHOT_FRAME == frame->mFrameType ) &&
1118 ( NULL != mCameraHal ) &&
1119 ( NULL != mDataCb) &&
1120 ( NULL != mNotifyCb)) {
1121 //When enabled, measurement data is sent instead of video data
1122 if ( !mMeasurementEnabled ) {
1123 copyAndSendPreviewFrame(frame, CAMERA_MSG_POSTVIEW_FRAME);
1124 } else {
1125 mFrameProvider->returnFrame(frame->mBuffer,
1126 (CameraFrame::FrameType) frame->mFrameType);
1127 }
1128 }
1129 else if ( ( CameraFrame::PREVIEW_FRAME_SYNC== frame->mFrameType ) &&
1130 ( NULL != mCameraHal ) &&
1131 ( NULL != mDataCb) &&
1132 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
1133 //When enabled, measurement data is sent instead of video data
1134 if ( !mMeasurementEnabled ) {
1135 copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
1136 } else {
1137 mFrameProvider->returnFrame(frame->mBuffer,
1138 (CameraFrame::FrameType) frame->mFrameType);
1139 }
1140 }
1141 else if ( ( CameraFrame::FRAME_DATA_SYNC == frame->mFrameType ) &&
1142 ( NULL != mCameraHal ) &&
1143 ( NULL != mDataCb) &&
1144 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
1145 copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
1146 } else {
1147 mFrameProvider->returnFrame(frame->mBuffer,
1148 ( CameraFrame::FrameType ) frame->mFrameType);
1149 CAMHAL_LOGDB("Frame type 0x%x is still unsupported!", frame->mFrameType);
1150 }
1151
1152 break;
1153
1154 default:
1155
1156 break;
1157
1158 };
1159
1160 exit:
1161
1162 if ( NULL != frame )
1163 {
1164 delete frame;
1165 }
1166
1167 LOG_FUNCTION_NAME_EXIT;
1168 }
1169
frameCallbackRelay(CameraFrame * caFrame)1170 void AppCallbackNotifier::frameCallbackRelay(CameraFrame* caFrame)
1171 {
1172 LOG_FUNCTION_NAME;
1173 AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (caFrame->mCookie);
1174 appcbn->frameCallback(caFrame);
1175 LOG_FUNCTION_NAME_EXIT;
1176 }
1177
frameCallback(CameraFrame * caFrame)1178 void AppCallbackNotifier::frameCallback(CameraFrame* caFrame)
1179 {
1180 ///Post the event to the event queue of AppCallbackNotifier
1181 TIUTILS::Message msg;
1182 CameraFrame *frame;
1183
1184 LOG_FUNCTION_NAME;
1185
1186 if ( NULL != caFrame )
1187 {
1188
1189 frame = new CameraFrame(*caFrame);
1190 if ( NULL != frame )
1191 {
1192 msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME;
1193 msg.arg1 = frame;
1194 mFrameQ.put(&msg);
1195 }
1196 else
1197 {
1198 CAMHAL_LOGEA("Not enough resources to allocate CameraFrame");
1199 }
1200
1201 }
1202
1203 LOG_FUNCTION_NAME_EXIT;
1204 }
1205
flushAndReturnFrames()1206 void AppCallbackNotifier::flushAndReturnFrames()
1207 {
1208 TIUTILS::Message msg;
1209 CameraFrame *frame;
1210
1211 Mutex::Autolock lock(mLock);
1212 while (!mFrameQ.isEmpty()) {
1213 mFrameQ.get(&msg);
1214 frame = (CameraFrame*) msg.arg1;
1215 if (frame) {
1216 mFrameProvider->returnFrame(frame->mBuffer,
1217 (CameraFrame::FrameType) frame->mFrameType);
1218 }
1219 }
1220
1221 LOG_FUNCTION_NAME_EXIT;
1222 }
1223
eventCallbackRelay(CameraHalEvent * chEvt)1224 void AppCallbackNotifier::eventCallbackRelay(CameraHalEvent* chEvt)
1225 {
1226 LOG_FUNCTION_NAME;
1227 AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (chEvt->mCookie);
1228 appcbn->eventCallback(chEvt);
1229 LOG_FUNCTION_NAME_EXIT;
1230 }
1231
eventCallback(CameraHalEvent * chEvt)1232 void AppCallbackNotifier::eventCallback(CameraHalEvent* chEvt)
1233 {
1234
1235 ///Post the event to the event queue of AppCallbackNotifier
1236 TIUTILS::Message msg;
1237 CameraHalEvent *event;
1238
1239
1240 LOG_FUNCTION_NAME;
1241
1242 if ( NULL != chEvt )
1243 {
1244
1245 event = new CameraHalEvent(*chEvt);
1246 if ( NULL != event )
1247 {
1248 msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT;
1249 msg.arg1 = event;
1250 {
1251 Mutex::Autolock lock(mLock);
1252 mEventQ.put(&msg);
1253 }
1254 }
1255 else
1256 {
1257 CAMHAL_LOGEA("Not enough resources to allocate CameraHalEvent");
1258 }
1259
1260 }
1261
1262 LOG_FUNCTION_NAME_EXIT;
1263 }
1264
1265
flushEventQueue()1266 void AppCallbackNotifier::flushEventQueue()
1267 {
1268
1269 {
1270 Mutex::Autolock lock(mLock);
1271 mEventQ.clear();
1272 }
1273 }
1274
1275
processMessage()1276 bool AppCallbackNotifier::processMessage()
1277 {
1278 ///Retrieve the command from the command queue and process it
1279 TIUTILS::Message msg;
1280
1281 LOG_FUNCTION_NAME;
1282
1283 CAMHAL_LOGDA("+Msg get...");
1284 mNotificationThread->msgQ().get(&msg);
1285 CAMHAL_LOGDA("-Msg get...");
1286 bool ret = true;
1287
1288 switch(msg.command)
1289 {
1290 case NotificationThread::NOTIFIER_EXIT:
1291 {
1292 CAMHAL_LOGDA("Received NOTIFIER_EXIT command from Camera HAL");
1293 mNotifierState = AppCallbackNotifier::NOTIFIER_EXITED;
1294 ret = false;
1295 break;
1296 }
1297 default:
1298 {
1299 CAMHAL_LOGEA("Error: ProcessMsg() command from Camera HAL");
1300 break;
1301 }
1302 }
1303
1304 LOG_FUNCTION_NAME_EXIT;
1305
1306 return ret;
1307
1308
1309 }
1310
~AppCallbackNotifier()1311 AppCallbackNotifier::~AppCallbackNotifier()
1312 {
1313 LOG_FUNCTION_NAME;
1314
1315 ///Stop app callback notifier if not already stopped
1316 stop();
1317
1318 ///Unregister with the frame provider
1319 if ( NULL != mFrameProvider )
1320 {
1321 mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
1322 }
1323
1324 //unregister with the event provider
1325 if ( NULL != mEventProvider )
1326 {
1327 mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS);
1328 }
1329
1330 TIUTILS::Message msg = {0,0,0,0,0,0};
1331 msg.command = NotificationThread::NOTIFIER_EXIT;
1332
1333 ///Post the message to display thread
1334 mNotificationThread->msgQ().put(&msg);
1335
1336 //Exit and cleanup the thread
1337 mNotificationThread->requestExit();
1338 mNotificationThread->join();
1339
1340 //Delete the display thread
1341 mNotificationThread.clear();
1342
1343
1344 ///Free the event and frame providers
1345 if ( NULL != mEventProvider )
1346 {
1347 ///Deleting the event provider
1348 CAMHAL_LOGDA("Stopping Event Provider");
1349 delete mEventProvider;
1350 mEventProvider = NULL;
1351 }
1352
1353 if ( NULL != mFrameProvider )
1354 {
1355 ///Deleting the frame provider
1356 CAMHAL_LOGDA("Stopping Frame Provider");
1357 delete mFrameProvider;
1358 mFrameProvider = NULL;
1359 }
1360
1361 releaseSharedVideoBuffers();
1362
1363 LOG_FUNCTION_NAME_EXIT;
1364 }
1365
1366 //Free all video heaps and buffers
releaseSharedVideoBuffers()1367 void AppCallbackNotifier::releaseSharedVideoBuffers()
1368 {
1369 LOG_FUNCTION_NAME;
1370
1371 if(mUseMetaDataBufferMode)
1372 {
1373 camera_memory_t* videoMedatadaBufferMemory;
1374 for (unsigned int i = 0; i < mVideoMetadataBufferMemoryMap.size(); i++)
1375 {
1376 videoMedatadaBufferMemory = (camera_memory_t*) mVideoMetadataBufferMemoryMap.valueAt(i);
1377 if(NULL != videoMedatadaBufferMemory)
1378 {
1379 videoMedatadaBufferMemory->release(videoMedatadaBufferMemory);
1380 CAMHAL_LOGDB("Released videoMedatadaBufferMemory=0x%x", videoMedatadaBufferMemory);
1381 }
1382 }
1383
1384 mVideoMetadataBufferMemoryMap.clear();
1385 mVideoMetadataBufferReverseMap.clear();
1386 if (mUseVideoBuffers)
1387 {
1388 mVideoMap.clear();
1389 }
1390 }
1391
1392 LOG_FUNCTION_NAME_EXIT;
1393 }
1394
setEventProvider(int32_t eventMask,MessageNotifier * eventNotifier)1395 void AppCallbackNotifier::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier)
1396 {
1397
1398 LOG_FUNCTION_NAME;
1399 ///@remarks There is no NULL check here. We will check
1400 ///for NULL when we get start command from CameraHal
1401 ///@Remarks Currently only one event provider (CameraAdapter) is supported
1402 ///@todo Have an array of event providers for each event bitmask
1403 mEventProvider = new EventProvider(eventNotifier, this, eventCallbackRelay);
1404 if ( NULL == mEventProvider )
1405 {
1406 CAMHAL_LOGEA("Error in creating EventProvider");
1407 }
1408 else
1409 {
1410 mEventProvider->enableEventNotification(eventMask);
1411 }
1412
1413 LOG_FUNCTION_NAME_EXIT;
1414 }
1415
setFrameProvider(FrameNotifier * frameNotifier)1416 void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier)
1417 {
1418 LOG_FUNCTION_NAME;
1419 ///@remarks There is no NULL check here. We will check
1420 ///for NULL when we get the start command from CameraAdapter
1421 mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);
1422 if ( NULL == mFrameProvider )
1423 {
1424 CAMHAL_LOGEA("Error in creating FrameProvider");
1425 }
1426 else
1427 {
1428 //Register only for captured images and RAW for now
1429 //TODO: Register for and handle all types of frames
1430 mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME);
1431 mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
1432 }
1433
1434 LOG_FUNCTION_NAME_EXIT;
1435 }
1436
startPreviewCallbacks(CameraParameters & params,void * buffers,uint32_t * offsets,int fd,size_t length,size_t count)1437 status_t AppCallbackNotifier::startPreviewCallbacks(CameraParameters ¶ms, void *buffers, uint32_t *offsets, int fd, size_t length, size_t count)
1438 {
1439 sp<MemoryHeapBase> heap;
1440 sp<MemoryBase> buffer;
1441 unsigned int *bufArr;
1442 int size = 0;
1443
1444 LOG_FUNCTION_NAME;
1445
1446 Mutex::Autolock lock(mLock);
1447
1448 if ( NULL == mFrameProvider )
1449 {
1450 CAMHAL_LOGEA("Trying to start video recording without FrameProvider");
1451 return -EINVAL;
1452 }
1453
1454 if ( mPreviewing )
1455 {
1456 CAMHAL_LOGDA("+Already previewing");
1457 return NO_INIT;
1458 }
1459
1460 int w,h;
1461 ///Get preview size
1462 params.getPreviewSize(&w, &h);
1463
1464 //Get the preview pixel format
1465 mPreviewPixelFormat = params.getPreviewFormat();
1466
1467 if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
1468 {
1469 size = w*h*2;
1470 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV422I;
1471 }
1472 else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 )
1473 {
1474 size = (w*h*3)/2;
1475 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV420SP;
1476 }
1477 else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
1478 {
1479 size = w*h*2;
1480 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_RGB565;
1481 }
1482 else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420P) == 0)
1483 {
1484 int yStride, uvStride, ySize, uvSize;
1485 alignYV12(w, h, yStride, uvStride, ySize, uvSize, size);
1486 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV420P;
1487 }
1488
1489 mPreviewMemory = mRequestMemory(-1, size, AppCallbackNotifier::MAX_BUFFERS, NULL);
1490 if (!mPreviewMemory) {
1491 return NO_MEMORY;
1492 }
1493
1494 for (int i=0; i < AppCallbackNotifier::MAX_BUFFERS; i++) {
1495 mPreviewBufs[i] = (unsigned char*) mPreviewMemory->data + (i*size);
1496 }
1497
1498 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME ) ) {
1499 mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
1500 }
1501
1502 mPreviewBufCount = 0;
1503
1504 mPreviewing = true;
1505
1506 LOG_FUNCTION_NAME;
1507
1508 return NO_ERROR;
1509 }
1510
setBurst(bool burst)1511 void AppCallbackNotifier::setBurst(bool burst)
1512 {
1513 LOG_FUNCTION_NAME;
1514
1515 Mutex::Autolock lock(mBurstLock);
1516
1517 mBurst = burst;
1518
1519 LOG_FUNCTION_NAME_EXIT;
1520 }
1521
useVideoBuffers(bool useVideoBuffers)1522 void AppCallbackNotifier::useVideoBuffers(bool useVideoBuffers)
1523 {
1524 LOG_FUNCTION_NAME;
1525
1526 mUseVideoBuffers = useVideoBuffers;
1527
1528 LOG_FUNCTION_NAME_EXIT;
1529 }
1530
getUesVideoBuffers()1531 bool AppCallbackNotifier::getUesVideoBuffers()
1532 {
1533 return mUseVideoBuffers;
1534 }
1535
setVideoRes(int width,int height)1536 void AppCallbackNotifier::setVideoRes(int width, int height)
1537 {
1538 LOG_FUNCTION_NAME;
1539
1540 mVideoWidth = width;
1541 mVideoHeight = height;
1542
1543 LOG_FUNCTION_NAME_EXIT;
1544 }
1545
stopPreviewCallbacks()1546 status_t AppCallbackNotifier::stopPreviewCallbacks()
1547 {
1548 sp<MemoryHeapBase> heap;
1549 sp<MemoryBase> buffer;
1550
1551 LOG_FUNCTION_NAME;
1552
1553 if ( NULL == mFrameProvider )
1554 {
1555 CAMHAL_LOGEA("Trying to stop preview callbacks without FrameProvider");
1556 return -EINVAL;
1557 }
1558
1559 if ( !mPreviewing )
1560 {
1561 return NO_INIT;
1562 }
1563
1564 mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
1565
1566 {
1567 Mutex::Autolock lock(mLock);
1568 mPreviewMemory->release(mPreviewMemory);
1569 }
1570
1571 mPreviewing = false;
1572
1573 LOG_FUNCTION_NAME_EXIT;
1574
1575 return NO_ERROR;
1576
1577 }
1578
useMetaDataBufferMode(bool enable)1579 status_t AppCallbackNotifier::useMetaDataBufferMode(bool enable)
1580 {
1581 mUseMetaDataBufferMode = enable;
1582
1583 return NO_ERROR;
1584 }
1585
1586
startRecording()1587 status_t AppCallbackNotifier::startRecording()
1588 {
1589 status_t ret = NO_ERROR;
1590
1591 LOG_FUNCTION_NAME;
1592
1593 Mutex::Autolock lock(mRecordingLock);
1594
1595 if ( NULL == mFrameProvider )
1596 {
1597 CAMHAL_LOGEA("Trying to start video recording without FrameProvider");
1598 ret = -1;
1599 }
1600
1601 if(mRecording)
1602 {
1603 return NO_INIT;
1604 }
1605
1606 if ( NO_ERROR == ret )
1607 {
1608 mFrameProvider->enableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC);
1609 }
1610
1611 mRecording = true;
1612
1613 LOG_FUNCTION_NAME_EXIT;
1614
1615 return ret;
1616 }
1617
1618 //Allocate metadata buffers for video recording
initSharedVideoBuffers(void * buffers,uint32_t * offsets,int fd,size_t length,size_t count,void * vidBufs)1619 status_t AppCallbackNotifier::initSharedVideoBuffers(void *buffers, uint32_t *offsets, int fd, size_t length, size_t count, void *vidBufs)
1620 {
1621 status_t ret = NO_ERROR;
1622 LOG_FUNCTION_NAME;
1623
1624 if(mUseMetaDataBufferMode)
1625 {
1626 uint32_t *bufArr = NULL;
1627 camera_memory_t* videoMedatadaBufferMemory = NULL;
1628
1629 if(NULL == buffers)
1630 {
1631 CAMHAL_LOGEA("Error! Video buffers are NULL");
1632 return BAD_VALUE;
1633 }
1634 bufArr = (uint32_t *) buffers;
1635
1636 for (uint32_t i = 0; i < count; i++)
1637 {
1638 videoMedatadaBufferMemory = mRequestMemory(-1, sizeof(video_metadata_t), 1, NULL);
1639 if((NULL == videoMedatadaBufferMemory) || (NULL == videoMedatadaBufferMemory->data))
1640 {
1641 CAMHAL_LOGEA("Error! Could not allocate memory for Video Metadata Buffers");
1642 return NO_MEMORY;
1643 }
1644
1645 mVideoMetadataBufferMemoryMap.add(bufArr[i], (uint32_t)(videoMedatadaBufferMemory));
1646 mVideoMetadataBufferReverseMap.add((uint32_t)(videoMedatadaBufferMemory->data), bufArr[i]);
1647 CAMHAL_LOGDB("bufArr[%d]=0x%x, videoMedatadaBufferMemory=0x%x, videoMedatadaBufferMemory->data=0x%x",
1648 i, bufArr[i], videoMedatadaBufferMemory, videoMedatadaBufferMemory->data);
1649
1650 if (vidBufs != NULL)
1651 {
1652 uint32_t *vBufArr = (uint32_t *) vidBufs;
1653 mVideoMap.add(bufArr[i], vBufArr[i]);
1654 CAMHAL_LOGVB("bufArr[%d]=0x%x, vBuffArr[%d]=0x%x", i, bufArr[i], i, vBufArr[i]);
1655 }
1656 }
1657 }
1658
1659 exit:
1660 LOG_FUNCTION_NAME_EXIT;
1661
1662 return ret;
1663 }
1664
stopRecording()1665 status_t AppCallbackNotifier::stopRecording()
1666 {
1667 status_t ret = NO_ERROR;
1668
1669 LOG_FUNCTION_NAME;
1670
1671 Mutex::Autolock lock(mRecordingLock);
1672
1673 if ( NULL == mFrameProvider )
1674 {
1675 CAMHAL_LOGEA("Trying to stop video recording without FrameProvider");
1676 ret = -1;
1677 }
1678
1679 if(!mRecording)
1680 {
1681 return NO_INIT;
1682 }
1683
1684 if ( NO_ERROR == ret )
1685 {
1686 mFrameProvider->disableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC);
1687 }
1688
1689 ///Release the shared video buffers
1690 releaseSharedVideoBuffers();
1691
1692 mRecording = false;
1693
1694 LOG_FUNCTION_NAME_EXIT;
1695
1696 return ret;
1697 }
1698
releaseRecordingFrame(const void * mem)1699 status_t AppCallbackNotifier::releaseRecordingFrame(const void* mem)
1700 {
1701 status_t ret = NO_ERROR;
1702 void *frame = NULL;
1703
1704 LOG_FUNCTION_NAME;
1705 if ( NULL == mFrameProvider )
1706 {
1707 CAMHAL_LOGEA("Trying to stop video recording without FrameProvider");
1708 ret = -1;
1709 }
1710
1711 if ( NULL == mem )
1712 {
1713 CAMHAL_LOGEA("Video Frame released is invalid");
1714 ret = -1;
1715 }
1716
1717 if( NO_ERROR != ret )
1718 {
1719 return ret;
1720 }
1721
1722 if(mUseMetaDataBufferMode)
1723 {
1724 video_metadata_t *videoMetadataBuffer = (video_metadata_t *) mem ;
1725 frame = (void*) mVideoMetadataBufferReverseMap.valueFor((uint32_t) videoMetadataBuffer);
1726 CAMHAL_LOGVB("Releasing frame with videoMetadataBuffer=0x%x, videoMetadataBuffer->handle=0x%x & frame handle=0x%x\n",
1727 videoMetadataBuffer, videoMetadataBuffer->handle, frame);
1728 }
1729 else
1730 {
1731 frame = (void*)(*((uint32_t *)mem));
1732 }
1733
1734 if ( NO_ERROR == ret )
1735 {
1736 ret = mFrameProvider->returnFrame(frame, CameraFrame::VIDEO_FRAME_SYNC);
1737 }
1738
1739 LOG_FUNCTION_NAME_EXIT;
1740
1741 return ret;
1742 }
1743
enableMsgType(int32_t msgType)1744 status_t AppCallbackNotifier::enableMsgType(int32_t msgType)
1745 {
1746 if( msgType & (CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_PREVIEW_FRAME) ) {
1747 mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
1748 }
1749
1750 return NO_ERROR;
1751 }
1752
disableMsgType(int32_t msgType)1753 status_t AppCallbackNotifier::disableMsgType(int32_t msgType)
1754 {
1755 if( msgType & (CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_POSTVIEW_FRAME) ) {
1756 mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
1757 }
1758
1759 return NO_ERROR;
1760
1761 }
1762
start()1763 status_t AppCallbackNotifier::start()
1764 {
1765 LOG_FUNCTION_NAME;
1766 if(mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED)
1767 {
1768 CAMHAL_LOGDA("AppCallbackNotifier already running");
1769 LOG_FUNCTION_NAME_EXIT;
1770 return ALREADY_EXISTS;
1771 }
1772
1773 ///Check whether initial conditions are met for us to start
1774 ///A frame provider should be available, if not return error
1775 if(!mFrameProvider)
1776 {
1777 ///AppCallbackNotifier not properly initialized
1778 CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Frame provider is NULL");
1779 LOG_FUNCTION_NAME_EXIT;
1780 return NO_INIT;
1781 }
1782
1783 ///At least one event notifier should be available, if not return error
1784 ///@todo Modify here when there is an array of event providers
1785 if(!mEventProvider)
1786 {
1787 CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Event provider is NULL");
1788 LOG_FUNCTION_NAME_EXIT;
1789 ///AppCallbackNotifier not properly initialized
1790 return NO_INIT;
1791 }
1792
1793 mNotifierState = AppCallbackNotifier::NOTIFIER_STARTED;
1794 CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STARTED \n");
1795
1796 gEncoderQueue.clear();
1797
1798 LOG_FUNCTION_NAME_EXIT;
1799
1800 return NO_ERROR;
1801
1802 }
1803
stop()1804 status_t AppCallbackNotifier::stop()
1805 {
1806 LOG_FUNCTION_NAME;
1807
1808 if(mNotifierState!=AppCallbackNotifier::NOTIFIER_STARTED)
1809 {
1810 CAMHAL_LOGDA("AppCallbackNotifier already in stopped state");
1811 LOG_FUNCTION_NAME_EXIT;
1812 return ALREADY_EXISTS;
1813 }
1814 {
1815 Mutex::Autolock lock(mLock);
1816
1817 mNotifierState = AppCallbackNotifier::NOTIFIER_STOPPED;
1818 CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STOPPED \n");
1819 }
1820
1821 while(!gEncoderQueue.isEmpty()) {
1822 sp<Encoder_libjpeg> encoder = gEncoderQueue.valueAt(0);
1823 camera_memory_t* encoded_mem = NULL;
1824 ExifElementsTable* exif = NULL;
1825
1826 if(encoder.get()) {
1827 encoder->cancel();
1828
1829 encoder->getCookies(NULL, (void**) &encoded_mem, (void**) &exif);
1830 if (encoded_mem) {
1831 encoded_mem->release(encoded_mem);
1832 }
1833 if (exif) {
1834 delete exif;
1835 }
1836
1837 encoder.clear();
1838 }
1839 gEncoderQueue.removeItemsAt(0);
1840 }
1841
1842 LOG_FUNCTION_NAME_EXIT;
1843 return NO_ERROR;
1844 }
1845
1846
1847 /*--------------------NotificationHandler Class ENDS here-----------------------------*/
1848
1849
1850
1851 };
1852