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