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