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