blob: 66ea6b9f8a41e512b24310d2b5f96b94a47d175d [file] [log] [blame]
Iliyan Malchev6d016452013-03-27 16:27:56 -07001/*
2** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17/*#error uncomment this for compiler test!*/
18
19#define ALOG_NDEBUG 0
20#define ALOG_NDDEBUG 0
21#define ALOG_NIDEBUG 0
22#define LOG_TAG "QCameraHWI_Still"
23#include <utils/Log.h>
24#include <utils/threads.h>
25#include <fcntl.h>
26#include <sys/mman.h>
27#include <media/mediarecorder.h>
28#include <math.h>
29#include "QCameraHAL.h"
30#include "QCameraHWI.h"
31
32#define THUMBNAIL_DEFAULT_WIDTH 512
33#define THUMBNAIL_DEFAULT_HEIGHT 384
34/* following code implement the still image capture & encoding logic of this class*/
35namespace android {
36
37typedef enum {
38 SNAPSHOT_STATE_ERROR,
39 SNAPSHOT_STATE_UNINIT,
40 SNAPSHOT_STATE_CH_ACQUIRED,
41 SNAPSHOT_STATE_BUF_NOTIF_REGD,
42 SNAPSHOT_STATE_BUF_INITIALIZED,
43 SNAPSHOT_STATE_INITIALIZED,
44 SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD,
45 SNAPSHOT_STATE_YUV_RECVD,
46 SNAPSHOT_STATE_JPEG_ENCODING,
47 SNAPSHOT_STATE_JPEG_ENCODE_DONE,
48 SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE,
49
50 /*Add any new state above*/
51 SNAPSHOT_STATE_MAX
52} snapshot_state_type_t;
53
54
55//-----------------------------------------------------------------------
56// Constants
57//----------------------------------------------------------------------
58static const int PICTURE_FORMAT_JPEG = 1;
59static const int PICTURE_FORMAT_RAW = 2;
60static const int POSTVIEW_SMALL_HEIGHT = 144;
61
62// ---------------------------------------------------------------------------
63/* static functions*/
64// ---------------------------------------------------------------------------
65
66
67
68/* TBD: Temp: to be removed*/
69static pthread_mutex_t g_s_mutex;
70static int g_status = 0;
71static pthread_cond_t g_s_cond_v;
72
73static void mm_app_snapshot_done()
74{
75 pthread_mutex_lock(&g_s_mutex);
76 g_status = true;
77 pthread_cond_signal(&g_s_cond_v);
78 pthread_mutex_unlock(&g_s_mutex);
79}
80
81static void mm_app_snapshot_wait()
82{
83 pthread_mutex_lock(&g_s_mutex);
84 if(false == g_status) pthread_cond_wait(&g_s_cond_v, &g_s_mutex);
85 pthread_mutex_unlock(&g_s_mutex);
86 g_status = false;
87}
88
89static int mm_app_dump_snapshot_frame(char *filename,
90 const void *buffer,
91 uint32_t len)
92{
93 char bufp[128];
94 int file_fdp;
95 int rc = 0;
96
97 file_fdp = open(filename, O_RDWR | O_CREAT, 0777);
98
99 if (file_fdp < 0) {
100 rc = -1;
101 goto end;
102 }
103 write(file_fdp,
104 (const void *)buffer, len);
105 close(file_fdp);
106end:
107 return rc;
108}
109
110/* Callback received when a frame is available after snapshot*/
111static void snapshot_notify_cb(mm_camera_ch_data_buf_t *recvd_frame,
112 void *user_data)
113{
114 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data;
115
116 ALOGV("%s: E", __func__);
117
118 if (pme != NULL) {
119 pme->receiveRawPicture(recvd_frame);
120 }
121 else{
122 ALOGW("%s: Snapshot obj NULL in callback", __func__);
123 }
124
125 ALOGV("%s: X", __func__);
126
127}
128
129/* Once we give frame for encoding, we get encoded jpeg image
130 fragments by fragment. We'll need to store them in a buffer
131 to form complete JPEG image */
132static void snapshot_jpeg_fragment_cb(uint8_t *ptr,
133 uint32_t size,
134 void *user_data)
135{
136 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data;
137
138 ALOGV("%s: E",__func__);
139 if (pme != NULL) {
140 pme->receiveJpegFragment(ptr,size);
141 }
142 else
143 ALOGW("%s: Receive jpeg fragment cb obj Null", __func__);
144
145 ALOGV("%s: X",__func__);
146}
147
148/* This callback is received once the complete JPEG encoding is done */
149static void snapshot_jpeg_cb(jpeg_event_t event, void *user_data)
150{
151 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data;
152 ALOGV("%s: E ",__func__);
153
154 switch(event) {
155 case JPEG_EVENT_DONE:
156 break;
157 case JPEG_EVENT_THUMBNAIL_DROPPED:
158 ALOGE("%s: Error in thumbnail encoding (event: %d) : X !!!",
159 __func__, event);
160 return;
161 case JPEG_EVENT_ERROR:
162 case JPEG_EVENT_ABORTED:
163 if (NULL != pme) {
164 pme->jpegErrorHandler(event);
165 if (!(pme->isZSLMode())) {
166 pme->stop();
167 }
168 }
169 ALOGE("Error event handled from JPEG \n");
170 return;
171 default:
172 ALOGE("Unsupported JPEG event %d \n", event);
173 break;
174 }
175
176 if (event != JPEG_EVENT_DONE) {
177 if (event == JPEG_EVENT_THUMBNAIL_DROPPED) {
178 ALOGE("%s: Error in thumbnail encoding (event: %d)!!!",
179 __func__, event);
180 ALOGV("%s: X",__func__);
181 return;
182 }
183 else {
184 ALOGE("%s: Error (event: %d) while jpeg encoding!!!",
185 __func__, event);
186 }
187 }
188
189 if (pme != NULL) {
190 pme->receiveCompleteJpegPicture(event);
191 ALOGV(" Completed issuing JPEG callback");
192 /* deinit only if we are done taking requested number of snapshots */
193 if (pme->getSnapshotState() == SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE) {
194 ALOGV(" About to issue deinit callback");
195 /* If it's ZSL Mode, we don't deinit now. We'll stop the polling thread and
196 deinit the channel/buffers only when we change the mode from zsl to
197 non-zsl. */
198 if (!(pme->isZSLMode())) {
199 pme->stop();
200 }
201 }
202 }
203 else
204 ALOGW("%s: Receive jpeg cb Obj Null", __func__);
205
206
207 ALOGV("%s: X",__func__);
208}
209
210// ---------------------------------------------------------------------------
211/* private functions*/
212// ---------------------------------------------------------------------------
213
214void QCameraStream_Snapshot::
215receiveJpegFragment(uint8_t *ptr, uint32_t size)
216{
217 ALOGV("%s: E", __func__);
218#if 0
219 if (mJpegHeap != NULL) {
220 ALOGE("%s: Copy jpeg...", __func__);
221 memcpy((uint8_t *)mJpegHeap->mHeap->base()+ mJpegOffset, ptr, size);
222 mJpegOffset += size;
223 }
224 else {
225 ALOGE("%s: mJpegHeap is NULL!", __func__);
226 }
227 #else
228 if(mHalCamCtrl->mJpegMemory.camera_memory[0] != NULL && ptr != NULL && size > 0) {
229 memcpy((uint8_t *)((uint32_t)mHalCamCtrl->mJpegMemory.camera_memory[0]->data + mJpegOffset), ptr, size);
230 mJpegOffset += size;
231
232
233 /*
234 memcpy((uint8_t *)((uint32_t)mHalCamCtrl->mJpegMemory.camera_memory[0]->data + mJpegOffset), ptr, size);
235 mJpegOffset += size;
236 */
237 } else {
238 ALOGE("%s: mJpegHeap is NULL!", __func__);
239 }
240
241
242 #endif
243
244 ALOGV("%s: X", __func__);
245}
246
247void QCameraStream_Snapshot::jpegErrorHandler(jpeg_event_t event)
248{
249 ALOGV("%s: E", __func__);
250 camera_memory_t *data = mHalCamCtrl->mGetMemory(-1, 1, 1, NULL);
251 mStopCallbackLock.lock( );
252 if(mCurrentFrameEncoded) {
253 free(mCurrentFrameEncoded);
254 mCurrentFrameEncoded = NULL;
255 }
256 setSnapshotState(SNAPSHOT_STATE_ERROR);
257 if (!mSnapshotQueue.isEmpty()) {
258 ALOGV("%s: JPEG Queue not empty. flush the queue in "
259 "error case.", __func__);
260 mSnapshotQueue.flush();
261 }
262 mStopCallbackLock.unlock( );
263 if (NULL != mHalCamCtrl->mDataCb)
264 mHalCamCtrl->mDataCb (CAMERA_MSG_COMPRESSED_IMAGE,
265 data, 0, NULL,mHalCamCtrl->mCallbackCookie);
266 if(NULL != data) data->release(data);
267 ALOGV("%s: X", __func__);
268}
269
270void QCameraStream_Snapshot::
271receiveCompleteJpegPicture(jpeg_event_t event)
272{
273 int msg_type = CAMERA_MSG_COMPRESSED_IMAGE;
274 ALOGV("%s: E", __func__);
275 camera_memory_t *encodedMem = NULL;
276 camera_data_callback jpg_data_cb = NULL;
277 bool fail_cb_flag = false;
278
279 if (mHalCamCtrl->mHdrMode == HDR_MODE)
280 hdrJpegCount++;
281
282 mStopCallbackLock.lock( );
283 if(!mActive && !isLiveSnapshot()) {
284 ALOGE("%s : Cancel Picture",__func__);
285 fail_cb_flag = true;
286 goto end;
287 }
288
289 if(mCurrentFrameEncoded!=NULL /*&& !isLiveSnapshot()*/){
290 ALOGV("<DEBUG>: Calling buf done for snapshot buffer");
291 cam_evt_buf_done(mCameraId, mCurrentFrameEncoded);
292 }
293 mHalCamCtrl->dumpFrameToFile(mHalCamCtrl->mJpegMemory.camera_memory[0]->data, mJpegOffset, (char *)"debug", (char *)"jpg", 0);
294
295end:
296 msg_type = CAMERA_MSG_COMPRESSED_IMAGE;
297 if (mHalCamCtrl->mDataCb && (mHalCamCtrl->mMsgEnabled & msg_type)) {
298 jpg_data_cb = mHalCamCtrl->mDataCb;
299 }else{
300 ALOGE("%s: JPEG callback was cancelled--not delivering image.", __func__);
301 }
302 setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODE_DONE);
303 mNumOfRecievedJPEG++;
304 mHalCamCtrl->deinitExifData();
305
306 /* free the resource we allocated to maintain the structure */
307 //mm_camera_do_munmap(main_fd, (void *)main_buffer_addr, mSnapshotStreamBuf.frame_len);
308 if(mCurrentFrameEncoded) {
309 free(mCurrentFrameEncoded);
310 mCurrentFrameEncoded = NULL;
311 }
312 /* Before leaving check the jpeg queue. If it's not empty give the available
313 frame for encoding*/
314 if (!mSnapshotQueue.isEmpty()) {
315 ALOGV("%s: JPEG Queue not empty. Dequeue and encode.", __func__);
316 mm_camera_ch_data_buf_t* buf =
317 (mm_camera_ch_data_buf_t *)mSnapshotQueue.dequeue();
318 //encodeDisplayAndSave(buf, 1);
319 if ( NO_ERROR != encodeDisplayAndSave(buf, 1)){
320 fail_cb_flag = true;
321 }
322 } else if (mNumOfSnapshot == mNumOfRecievedJPEG ) { /* finished */
323 ALOGV("nusnap %d, mNumjpeg %d", mNumOfSnapshot, mNumOfRecievedJPEG);
324 ALOGV("%s: Before omxJpegFinish", __func__);
325 omxJpegFinish();
326 ALOGV("%s: After omxJpegFinish", __func__);
327 /* getRemainingSnapshots call will give us number of snapshots still
328 remaining after flushing current zsl buffer once*/
329 ALOGV("%s: Complete JPEG Encoding Done!", __func__);
330 setSnapshotState(SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE);
331 mBurstModeFlag = false;
332 mSnapshotQueue.flush();
333 mNumOfRecievedJPEG = 0;
334 /* in case of zsl, we need to reset some of the zsl attributes */
335 if (isZSLMode()){
336 ALOGV("%s: Resetting the ZSL attributes", __func__);
337 setZSLChannelAttribute();
338 }
339 if (!isZSLMode() && !isLiveSnapshot()){
340 //Stop polling before calling datacb for if not ZSL mode
341 stopPolling();
342 }
343
344 } else {
345 ALOGV("%s: mNumOfRecievedJPEG(%d), mNumOfSnapshot(%d)", __func__, mNumOfRecievedJPEG, mNumOfSnapshot);
346 }
347 if(fail_cb_flag && mHalCamCtrl->mDataCb &&
348 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
349 /* get picture failed. Give jpeg callback with NULL data
350 * to the application to restore to preview mode
351 */
352 jpg_data_cb = mHalCamCtrl->mDataCb;
353 }
354 if(mHalCamCtrl->mHdrMode == HDR_MODE && (hdrJpegCount%2) != 0){
355 mStopCallbackLock.unlock( );
356 mJpegOffset = 0;
357 return;
358 }
359 if(!fail_cb_flag) {
360 camera_memory_t *encodedMem = mHalCamCtrl->mGetMemory(
361 mHalCamCtrl->mJpegMemory.fd[0], mJpegOffset, 1, mHalCamCtrl);
362 if (!encodedMem || !encodedMem->data) {
363 ALOGE("%s: mGetMemory failed.\n", __func__);
364 }
365 memcpy(encodedMem->data, mHalCamCtrl->mJpegMemory.camera_memory[0]->data, mJpegOffset );
366 mStopCallbackLock.unlock( );
367
368 if ((mActive || isLiveSnapshot()) && jpg_data_cb != NULL) {
369 ALOGV("%s: Calling upperlayer callback to store JPEG image", __func__);
370 jpg_data_cb (msg_type,encodedMem, 0, NULL,mHalCamCtrl->mCallbackCookie);
371 }
372 encodedMem->release( encodedMem );
373 jpg_data_cb = NULL;
374 }else{
375 ALOGV("Image Encoding Failed... Notify Upper layer");
376 mStopCallbackLock.unlock( );
377 if((mActive || isLiveSnapshot()) && jpg_data_cb != NULL) {
378 jpg_data_cb (CAMERA_MSG_COMPRESSED_IMAGE,NULL, 0, NULL,
379 mHalCamCtrl->mCallbackCookie);
380 }
381 }
382 //reset jpeg_offset
383 mJpegOffset = 0;
384
385 if(isLiveSnapshot() && mHalCamCtrl->mStateLiveshot) {
386 deInitBuffer();
387 }
388 mHalCamCtrl->mStateLiveshot = false;
389
390 ALOGV("%s: X", __func__);
391}
392
393status_t QCameraStream_Snapshot::
394configSnapshotDimension(cam_ctrl_dimension_t* dim)
395{
396 bool matching = true;
397 cam_format_t img_format;
398 status_t ret = NO_ERROR;
399 ALOGV("%s: E", __func__);
400
401 ALOGV("%s:Passed picture size: %d X %d", __func__,
402 dim->picture_width, dim->picture_height);
403 ALOGV("%s:Passed postview size: %d X %d", __func__,
404 dim->ui_thumbnail_width, dim->ui_thumbnail_height);
405
406 /* First check if the picture resolution is the same, if not, change it*/
407 mHalCamCtrl->getPictureSize(&mPictureWidth, &mPictureHeight);
408 ALOGV("%s: Picture size received: %d x %d", __func__,
409 mPictureWidth, mPictureHeight);
410
411 mPostviewWidth = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
412 mPostviewHeight = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
413 /*If application requested thumbnail size to be (0,0)
414 then configure second outout to a default size.
415 Jpeg encoder will drop thumbnail as reflected in encodeParams.
416 */
417 mDropThumbnail = false;
418 if (mPostviewWidth == 0 && mPostviewHeight == 0) {
419 mPostviewWidth = THUMBNAIL_DEFAULT_WIDTH;
420 mPostviewHeight = THUMBNAIL_DEFAULT_HEIGHT;
421 mDropThumbnail = true;
422 }
423
424 ALOGV("%s: Postview size received: %d x %d", __func__,
425 mPostviewWidth, mPostviewHeight);
426
427 matching = (mPictureWidth == dim->picture_width) &&
428 (mPictureHeight == dim->picture_height);
429 matching &= (dim->ui_thumbnail_width == mPostviewWidth) &&
430 (dim->ui_thumbnail_height == mPostviewHeight);
431
432 /* picture size currently set do not match with the one wanted
433 by user.*/
434 if (!matching) {
435 if (!isZSLMode() && (mPictureWidth < mPostviewWidth || mPictureHeight < mPostviewHeight)) {
436 //Changes to Handle VFE limitation.
437 mActualPictureWidth = mPictureWidth;
438 mActualPictureHeight = mPictureHeight;
439 mPictureWidth = mPostviewWidth;
440 mPictureHeight = mPostviewHeight;
441 mJpegDownscaling = true;
442 }else{
443 mJpegDownscaling = false;
444 }
445 dim->picture_width = mPictureWidth;
446 dim->picture_height = mPictureHeight;
447 dim->ui_thumbnail_height = mThumbnailHeight = mPostviewHeight;
448 dim->ui_thumbnail_width = mThumbnailWidth = mPostviewWidth;
449 }
450 #if 0
451 img_format = mHalCamCtrl->getPreviewFormat();
452 if (img_format) {
453 matching &= (img_format == dim->main_img_format);
454 if (!matching) {
455 dim->main_img_format = img_format;
456 dim->thumb_format = img_format;
457 }
458 }
459 #endif
460 if (!matching) {
461 ALOGV("%s: Image Sizes before set parm call: main: %dx%d thumbnail: %dx%d",
462 __func__,
463 dim->picture_width, dim->picture_height,
464 dim->ui_thumbnail_width, dim->ui_thumbnail_height);
465
466 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,dim);
467 if (NO_ERROR != ret) {
468 ALOGE("%s: error - can't config snapshot parms!", __func__);
469 ret = FAILED_TRANSACTION;
470 goto end;
471 }
472 }
473 /* set_parm will return corrected dimension based on aspect ratio and
474 ceiling size */
475 mPictureWidth = dim->picture_width;
476 mPictureHeight = dim->picture_height;
477 mPostviewHeight = mThumbnailHeight = dim->ui_thumbnail_height;
478 mPostviewWidth = mThumbnailWidth = dim->ui_thumbnail_width;
479 mPictureFormat= dim->main_img_format;
480 mThumbnailFormat = dim->thumb_format;
481
482 ALOGV("%s: Image Format: %d", __func__, dim->main_img_format);
483 ALOGV("%s: Image Sizes: main: %dx%d thumbnail: %dx%d", __func__,
484 dim->picture_width, dim->picture_height,
485 dim->ui_thumbnail_width, dim->ui_thumbnail_height);
486end:
487 ALOGV("%s: X", __func__);
488 return ret;
489}
490
491status_t QCameraStream_Snapshot::
492initRawSnapshotChannel(cam_ctrl_dimension_t *dim,
493 int num_of_snapshots)
494{
495 status_t ret = NO_ERROR;
496 mm_camera_ch_image_fmt_parm_t fmt;
497 mm_camera_channel_attr_t ch_attr;
498 cam_format_t raw_fmt;
499
500 mm_camera_raw_streaming_type_t raw_stream_type =
501 MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE;
502
503 ALOGV("%s: E", __func__);
504
505 /* Initialize stream - set format, acquire channel */
506 /*TBD: Currently we only support single raw capture*/
507 ALOGV("num_of_snapshots = %d",num_of_snapshots);
508 if (num_of_snapshots == 1) {
509 raw_stream_type = MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE;
510 }
511
512 /* Set channel attribute */
513 ALOGV("%s: Set Raw Snapshot Channel attribute", __func__);
514 memset(&ch_attr, 0, sizeof(ch_attr));
515 ch_attr.type = MM_CAMERA_CH_ATTR_RAW_STREAMING_TYPE;
516 ch_attr.raw_streaming_mode = raw_stream_type;
517
518 if( NO_ERROR !=
519 cam_ops_ch_set_attr(mCameraId, MM_CAMERA_CH_RAW, &ch_attr)) {
520 ALOGV("%s: Failure setting Raw channel attribute.", __func__);
521 ret = FAILED_TRANSACTION;
522 goto end;
523 }
524
525 ret = cam_config_get_parm(mCameraId,
526 MM_CAMERA_PARM_RAW_SNAPSHOT_FMT, &raw_fmt);
527 if (NO_ERROR != ret) {
528 ALOGE("%s: error - can't get raw snapshot fmt!", __func__);
529 ret = FAILED_TRANSACTION;
530 goto end;
531 }
532
533 memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
534 fmt.ch_type = MM_CAMERA_CH_RAW;
535 fmt.def.fmt = raw_fmt;
536 fmt.def.dim.width = dim->raw_picture_width;
537 fmt.def.dim.height = dim->raw_picture_height;
538
539
540 ALOGV("%s: Raw snapshot channel fmt: %d", __func__,
541 fmt.def.fmt);
542 ALOGV("%s: Raw snapshot resolution: %dX%d", __func__,
543 dim->raw_picture_width, dim->raw_picture_height);
544
545 ALOGV("%s: Set Raw Snapshot channel image format", __func__);
546 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
547 if (NO_ERROR != ret) {
548 ALOGE("%s: Set Raw Snapshot Channel format err=%d\n", __func__, ret);
549 ret = FAILED_TRANSACTION;
550 goto end;
551 }
552
553end:
554 if (ret != NO_ERROR) {
555 handleError();
556 }
557 ALOGV("%s: X", __func__);
558 return ret;
559
560}
561
562status_t QCameraStream_Snapshot::
563setZSLChannelAttribute(void)
564{
565 status_t ret = NO_ERROR;
566 mm_camera_channel_attr_t ch_attr;
567 ALOGV("%s: E", __func__);
568
569 memset(&ch_attr, 0, sizeof(mm_camera_channel_attr_t));
570 ch_attr.type = MM_CAMERA_CH_ATTR_BUFFERING_FRAME;
571 ch_attr.buffering_frame.look_back = mHalCamCtrl->getZSLBackLookCount();
572 ch_attr.buffering_frame.water_mark = mHalCamCtrl->getZSLQueueDepth();
573 ch_attr.buffering_frame.interval = mHalCamCtrl->getZSLBurstInterval( );
574 ALOGV("%s: ZSL queue_depth = %d, back_look_count = %d", __func__,
575 ch_attr.buffering_frame.water_mark,
576 ch_attr.buffering_frame.look_back);
577 if( NO_ERROR !=
578 cam_ops_ch_set_attr(mCameraId, MM_CAMERA_CH_SNAPSHOT, &ch_attr)) {
579 ALOGV("%s: Failure setting ZSL channel attribute.", __func__);
580 ret = FAILED_TRANSACTION;
581 goto end;
582 }
583end:
584 ALOGV("%s: X", __func__);
585 return ret;
586}
587
588status_t QCameraStream_Snapshot::
589initSnapshotFormat(cam_ctrl_dimension_t *dim)
590{
591 status_t ret = NO_ERROR;
592 mm_camera_ch_image_fmt_parm_t fmt;
593
594 ALOGV("%s: E", __func__);
595
596 /* For ZSL mode we'll need to set channel attribute */
597 if (isZSLMode()) {
598 ret = setZSLChannelAttribute();
599 if (ret != NO_ERROR) {
600 goto end;
601 }
602 }
603
604 memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
605 fmt.ch_type = MM_CAMERA_CH_SNAPSHOT;
606 fmt.snapshot.main.fmt = dim->main_img_format;
607 fmt.snapshot.main.dim.width = dim->picture_width;
608 fmt.snapshot.main.dim.height = dim->picture_height;
609
610 fmt.snapshot.thumbnail.fmt = dim->thumb_format;
611 fmt.snapshot.thumbnail.dim.width = dim->ui_thumbnail_width;
612 fmt.snapshot.thumbnail.dim.height = dim->ui_thumbnail_height;
613
614 ALOGV("%s: Snapshot channel fmt = main: %d thumbnail: %d", __func__,
615 dim->main_img_format, dim->thumb_format);
616 ALOGV("%s: Snapshot channel resolution = main: %dX%d thumbnail: %dX%d",
617 __func__, dim->picture_width, dim->picture_height,
618 dim->ui_thumbnail_width, dim->ui_thumbnail_height);
619
620 ALOGV("%s: Set Snapshot channel image format", __func__);
621 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
622 if (NO_ERROR != ret) {
623 ALOGE("%s: Set Snapshot Channel format err=%d\n", __func__, ret);
624 ret = FAILED_TRANSACTION;
625 goto end;
626 }
627
628end:
629 if (ret != NO_ERROR) {
630 handleError();
631 }
632 ALOGV("%s: X", __func__);
633 return ret;
634
635}
636
637void QCameraStream_Snapshot::
638deinitSnapshotChannel(mm_camera_channel_type_t ch_type)
639{
640 ALOGV("%s: E", __func__);
641
642 /* unreg buf notify*/
643 if (getSnapshotState() >= SNAPSHOT_STATE_BUF_NOTIF_REGD){
644 if (NO_ERROR != cam_evt_register_buf_notify(mCameraId,
645 ch_type, NULL,(mm_camera_register_buf_cb_type_t)NULL,NULL, this)) {
646 ALOGE("%s: Failure to unregister buf notification", __func__);
647 }
648 }
649
650 if (getSnapshotState() >= SNAPSHOT_STATE_CH_ACQUIRED) {
651 ALOGV("%s: Release snapshot channel", __func__);
652 cam_ops_ch_release(mCameraId, ch_type);
653 }
654
655 ALOGV("%s: X",__func__);
656}
657
658status_t QCameraStream_Snapshot::
659initRawSnapshotBuffers(cam_ctrl_dimension_t *dim, int num_of_buf)
660{
661 status_t ret = NO_ERROR;
662 struct msm_frame *frame;
663 uint32_t frame_len;
664 uint8_t num_planes;
665 uint32_t planes[VIDEO_MAX_PLANES];
666 mm_camera_reg_buf_t reg_buf;
667 cam_format_t raw_fmt;
668
669 ALOGV("%s: E", __func__);
670 memset(&reg_buf, 0, sizeof(mm_camera_reg_buf_t));
671 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
672
673 if ((num_of_buf == 0) || (num_of_buf > MM_CAMERA_MAX_NUM_FRAMES)) {
674 ALOGE("%s: Invalid number of buffers (=%d) requested!", __func__, num_of_buf);
675 ret = BAD_VALUE;
676 goto end;
677 }
678
679 reg_buf.def.buf.mp = new mm_camera_mp_buf_t[num_of_buf];
680 if (!reg_buf.def.buf.mp) {
681 ALOGE("%s Error allocating memory for mplanar struct ", __func__);
682 ret = NO_MEMORY;
683 goto end;
684 }
685 memset(reg_buf.def.buf.mp, 0, num_of_buf * sizeof(mm_camera_mp_buf_t));
686
687 ret = cam_config_get_parm(mCameraId,
688 MM_CAMERA_PARM_RAW_SNAPSHOT_FMT, &raw_fmt);
689 if (NO_ERROR != ret) {
690 ALOGE("%s: error - can't get raw snapshot fmt!", __func__);
691 ret = FAILED_TRANSACTION;
692 goto end;
693 }
694
695 /* Get a frame len for buffer to be allocated*/
696 frame_len = mm_camera_get_msm_frame_len(raw_fmt,
697 myMode,
698 dim->raw_picture_width,
699 dim->raw_picture_height,
700 OUTPUT_TYPE_S,
701 &num_planes, planes);
702
703 if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mRawMemory, num_of_buf,
704 frame_len, 0, planes[0], MSM_PMEM_RAW_MAINIMG,
705 &mSnapshotStreamBuf, &reg_buf.def,
706 num_planes, planes) < 0) {
707 ret = NO_MEMORY;
708 goto end;
709 }
710
711 /* register the streaming buffers for the channel*/
712 reg_buf.ch_type = MM_CAMERA_CH_RAW;
713 reg_buf.def.num = mSnapshotStreamBuf.num;
714
715 ret = cam_config_prepare_buf(mCameraId, &reg_buf);
716 if(ret != NO_ERROR) {
717 ALOGV("%s:reg snapshot buf err=%d\n", __func__, ret);
718 ret = FAILED_TRANSACTION;
719 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mRawMemory);
720 goto end;
721 }
722
723 /* If we have reached here successfully, we have allocated buffer.
724 Set state machine.*/
725 setSnapshotState(SNAPSHOT_STATE_BUF_INITIALIZED);
726
727end:
728 /* If it's error, we'll need to do some needful */
729 if (ret != NO_ERROR) {
730 handleError();
731 }
732 if (reg_buf.def.buf.mp)
733 delete []reg_buf.def.buf.mp;
734 ALOGV("%s: X", __func__);
735 return ret;
736}
737
738status_t QCameraStream_Snapshot::deinitRawSnapshotBuffers(void)
739{
740 int ret = NO_ERROR;
741 ALOGV("%s: E", __func__);
742
743 int err = getSnapshotState();
744
745 /* deinit buffers only if we have already allocated */
746 if (err >= SNAPSHOT_STATE_BUF_INITIALIZED || err == SNAPSHOT_STATE_ERROR){
747 ALOGV("%s: Unpreparing Snapshot Buffer", __func__);
748 ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_RAW);
749 if(ret != NO_ERROR) {
750 ALOGE("%s:Unreg Raw snapshot buf err=%d\n", __func__, ret);
751 ret = FAILED_TRANSACTION;
752 goto end;
753 }
754 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mRawMemory);
755 }
756
757end:
758 ALOGV("%s: X", __func__);
759 return ret;
760}
761
762status_t QCameraStream_Snapshot::
763initSnapshotBuffers(cam_ctrl_dimension_t *dim, int num_of_buf)
764{
765 status_t ret = NO_ERROR;
766 struct msm_frame *frame;
767 uint32_t frame_len, y_off, cbcr_off;
768 uint8_t num_planes;
769 uint32_t planes[VIDEO_MAX_PLANES];
770 mm_camera_reg_buf_t reg_buf;
771 int rotation = 0;
772
773 ALOGV("%s: E", __func__);
774 memset(&reg_buf, 0, sizeof(mm_camera_reg_buf_t));
775 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
776
777 if ((num_of_buf == 0) || (num_of_buf > MM_CAMERA_MAX_NUM_FRAMES)) {
778 ALOGE("%s: Invalid number of buffers (=%d) requested!",
779 __func__, num_of_buf);
780 ret = BAD_VALUE;
781 goto end;
782 }
783
784 ALOGV("%s: Mode: %d Num_of_buf: %d ImageSizes: main: %dx%d thumb: %dx%d",
785 __func__, myMode, num_of_buf,
786 dim->picture_width, dim->picture_height,
787 dim->ui_thumbnail_width, dim->ui_thumbnail_height);
788
789 reg_buf.snapshot.main.buf.mp = new mm_camera_mp_buf_t[num_of_buf];
790 if (!reg_buf.snapshot.main.buf.mp) {
791 ALOGE("%s Error allocating memory for mplanar struct ", __func__);
792 ret = NO_MEMORY;
793 goto end;
794 }
795 memset(reg_buf.snapshot.main.buf.mp, 0,
796 num_of_buf * sizeof(mm_camera_mp_buf_t));
797 if (!isFullSizeLiveshot()) {
798 reg_buf.snapshot.thumbnail.buf.mp = new mm_camera_mp_buf_t[num_of_buf];
799 if (!reg_buf.snapshot.thumbnail.buf.mp) {
800 ALOGE("%s Error allocating memory for mplanar struct ", __func__);
801 ret = NO_MEMORY;
802 goto end;
803 }
804 memset(reg_buf.snapshot.thumbnail.buf.mp, 0,
805 num_of_buf * sizeof(mm_camera_mp_buf_t));
806 }
807 /* Number of buffers to be set*/
808 /* Set the JPEG Rotation here since get_buffer_offset needs
809 * the value of rotation.*/
810 mHalCamCtrl->setJpegRotation(isZSLMode());
811 if(!isZSLMode())
812 rotation = mHalCamCtrl->getJpegRotation();
813 else
814 rotation = 0;
815 if(rotation != dim->rotation) {
816 dim->rotation = rotation;
817 ret = cam_config_set_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, dim);
818 }
819
820 if(isLiveSnapshot()) {
821 ret = cam_config_set_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, dim);
822 }
823 num_planes = 2;
824 planes[0] = dim->picture_frame_offset.mp[0].len;
825 planes[1] = dim->picture_frame_offset.mp[1].len;
826 frame_len = dim->picture_frame_offset.frame_len;
827 y_off = dim->picture_frame_offset.mp[0].offset;
828 cbcr_off = dim->picture_frame_offset.mp[1].offset;
829 ALOGV("%s: main image: rotation = %d, yoff = %d, cbcroff = %d, size = %d, width = %d, height = %d",
830 __func__, dim->rotation, y_off, cbcr_off, frame_len, dim->picture_width, dim->picture_height);
831 if (mHalCamCtrl->initHeapMem (&mHalCamCtrl->mJpegMemory, 1, frame_len, 0, cbcr_off,
832 MSM_PMEM_MAX, NULL, NULL, num_planes, planes) < 0) {
833 ALOGE("%s: Error allocating JPEG memory", __func__);
834 ret = NO_MEMORY;
835 goto end;
836 }
837 if(!isLiveSnapshot()) {
838 if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mSnapshotMemory, num_of_buf,
839 frame_len, y_off, cbcr_off, MSM_PMEM_MAINIMG, &mSnapshotStreamBuf,
840 &reg_buf.snapshot.main, num_planes, planes) < 0) {
841 ret = NO_MEMORY;
842 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
843 goto end;
844 };
845 num_planes = 2;
846 planes[0] = dim->thumb_frame_offset.mp[0].len;
847 planes[1] = dim->thumb_frame_offset.mp[1].len;
848 frame_len = planes[0] + planes[1];
849 if (!isFullSizeLiveshot()) {
850 y_off = dim->thumb_frame_offset.mp[0].offset;
851 cbcr_off = dim->thumb_frame_offset.mp[1].offset;
852 ALOGV("%s: thumbnail: rotation = %d, yoff = %d, cbcroff = %d, size = %d, width = %d, height = %d",
853 __func__, dim->rotation, y_off, cbcr_off, frame_len,
854 dim->thumbnail_width, dim->thumbnail_height);
855
856 if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mThumbnailMemory, num_of_buf,
857 frame_len, y_off, cbcr_off, MSM_PMEM_THUMBNAIL, &mPostviewStreamBuf,
858 &reg_buf.snapshot.thumbnail, num_planes, planes) < 0) {
859 ret = NO_MEMORY;
860 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory);
861 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
862 goto end;
863 }
864 }
865 /* register the streaming buffers for the channel*/
866 reg_buf.ch_type = MM_CAMERA_CH_SNAPSHOT;
867 reg_buf.snapshot.main.num = mSnapshotStreamBuf.num;
868
869 if (!isFullSizeLiveshot())
870 reg_buf.snapshot.thumbnail.num = mPostviewStreamBuf.num;
871 else
872 reg_buf.snapshot.thumbnail.num = 0;
873
874 ret = cam_config_prepare_buf(mCameraId, &reg_buf);
875 if(ret != NO_ERROR) {
876 ALOGE("%s:reg snapshot buf err=%d\n", __func__, ret);
877 ret = FAILED_TRANSACTION;
878 if (!isFullSizeLiveshot()){
879 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mThumbnailMemory);
880 }
881 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory);
882 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
883 goto end;
884 }
885 }
886
887 /* If we have reached here successfully, we have allocated buffer.
888 Set state machine.*/
889 setSnapshotState(SNAPSHOT_STATE_BUF_INITIALIZED);
890end:
891 if (ret != NO_ERROR) {
892 handleError();
893 }
894 if (reg_buf.snapshot.main.buf.mp)
895 delete []reg_buf.snapshot.main.buf.mp;
896 if (reg_buf.snapshot.thumbnail.buf.mp)
897 delete []reg_buf.snapshot.thumbnail.buf.mp;
898 ALOGV("%s: X", __func__);
899 return ret;
900}
901
902status_t QCameraStream_Snapshot::
903deinitSnapshotBuffers(void)
904{
905 int ret = NO_ERROR;
906 ALOGV("%s: E", __func__);
907
908 int err = getSnapshotState();
909 /* Deinit only if we have already initialized*/
910 if (err >= SNAPSHOT_STATE_BUF_INITIALIZED || err == SNAPSHOT_STATE_ERROR){
911
912 if(!isLiveSnapshot()) {
913 ALOGV("%s: Unpreparing Snapshot Buffer", __func__);
914 ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_SNAPSHOT);
915 if(ret != NO_ERROR) {
916 ALOGE("%s:unreg snapshot buf err=%d\n", __func__, ret);
917 ret = FAILED_TRANSACTION;
918 goto end;
919 }
920 }
921
922 /* Clear main and thumbnail heap*/
923 if(!isLiveSnapshot()) {
924 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory);
925 if (!isFullSizeLiveshot())
926 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mThumbnailMemory);
927 }
928 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
929 }
930end:
931 ALOGV("%s: X", __func__);
932 return ret;
933}
934
935void QCameraStream_Snapshot::deInitBuffer(void)
936{
937 mm_camera_channel_type_t ch_type;
938
939 ALOGV("%s: E", __func__);
940
941 if( getSnapshotState() == SNAPSHOT_STATE_UNINIT) {
942 ALOGV("%s: Already deinit'd!", __func__);
943 return;
944 }
945
946 if (mSnapshotFormat == PICTURE_FORMAT_RAW) {
947 /* deinit buffer */
948 deinitRawSnapshotBuffers();
949 }
950 else
951 {
952 if ((!isZSLMode() && !isLiveSnapshot()) &&
953 ((mHalCamCtrl->getHDRMode() == HDR_MODE) || (mHalCamCtrl->isWDenoiseEnabled()))) {
954 /*register main and thumbnail buffers at back-end for frameproc*/
955 for (int i = 0; i < mHalCamCtrl->mSnapshotMemory.buffer_count; i++) {
956 if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, mCameraId,
957 CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
958 ALOGE("%s: unmapping Main image Buffer for HDR and Denoise", __func__);
959 }
960 if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, i, mCameraId,
961 CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
962 ALOGE("%s: unmapping Thumbnail buffer for HDR and Denoise", __func__);
963 }
964 }
965 }
966 if (isZSLMode()) {
967 /*register main and thumbnail buffers at back-end for frameproc*/
968 for (int i = 0; i < mHalCamCtrl->mSnapshotMemory.buffer_count; i++) {
969 if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, mCameraId,
970 CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
971 ALOGE("%s: unmapping Main image Buffer for ZSL", __func__);
972 }
973 }
974 }
975
976 deinitSnapshotBuffers();
977 }
978
979
980 /* deinit jpeg buffer if allocated */
981 if(mJpegHeap != NULL) mJpegHeap.clear();
982 mJpegHeap = NULL;
983
984 /* memset some global structure */
985 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
986 memset(&mPostviewStreamBuf, 0, sizeof(mPostviewStreamBuf));
987 mSnapshotQueue.flush();
988 mWDNQueue.flush();
989
990 setSnapshotState(SNAPSHOT_STATE_UNINIT);
991
992 ALOGV("%s: X", __func__);
993}
994
995/*Temp: to be removed once event handling is enabled in mm-camera.
996 We need an event - one event for
997 stream-off to disable OPS_SNAPSHOT*/
998void QCameraStream_Snapshot::runSnapshotThread(void *data)
999{
1000 ALOGV("%s: E", __func__);
1001
1002 if (mSnapshotFormat == PICTURE_FORMAT_RAW) {
1003 /* TBD: Temp: Needs to be removed once event handling is enabled.
1004 We cannot call mm-camera interface to stop snapshot from callback
1005 function as it causes deadlock. Hence handling it here temporarily
1006 in this thread. Later mm-camera intf will give us event in separate
1007 thread context */
1008 mm_app_snapshot_wait();
1009 /* Send command to stop snapshot polling thread*/
1010 stop();
1011 }
1012 ALOGV("%s: X", __func__);
1013}
1014
1015/*Temp: to be removed once event handling is enabled in mm-camera*/
1016static void *snapshot_thread(void *obj)
1017{
1018 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)obj;
1019 ALOGV("%s: E", __func__);
1020 if (pme != 0) {
1021 pme->runSnapshotThread(obj);
1022 }
1023 else ALOGW("not starting snapshot thread: the object went away!");
1024 ALOGV("%s: X", __func__);
1025 return NULL;
1026}
1027
1028/*Temp: to be removed later*/
1029static pthread_t mSnapshotThread;
1030
1031status_t QCameraStream_Snapshot::initJPEGSnapshot(int num_of_snapshots)
1032{
1033 status_t ret = NO_ERROR;
1034 cam_ctrl_dimension_t dim;
1035 mm_camera_op_mode_type_t op_mode;
1036
1037 ALOGV("%s: E", __func__);
1038
1039 if (isFullSizeLiveshot())
1040 goto end;
1041
1042 ALOGV("%s: Get current dimension", __func__);
1043 /* Query mm_camera to get current dimension */
1044 memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
1045 ret = cam_config_get_parm(mCameraId,
1046 MM_CAMERA_PARM_DIMENSION, &dim);
1047 if (NO_ERROR != ret) {
1048 ALOGE("%s: error - can't get preview dimension!", __func__);
1049 ret = FAILED_TRANSACTION;
1050 goto end;
1051 }
1052
1053 /* Set camera op mode to MM_CAMERA_OP_MODE_CAPTURE */
1054 ALOGV("Setting OP_MODE_CAPTURE");
1055 op_mode = MM_CAMERA_OP_MODE_CAPTURE;
1056 if( NO_ERROR != cam_config_set_parm(mCameraId,
1057 MM_CAMERA_PARM_OP_MODE, &op_mode)) {
1058 ALOGE("%s: MM_CAMERA_OP_MODE_CAPTURE failed", __func__);
1059 ret = FAILED_TRANSACTION;
1060 goto end;
1061 }
1062
1063 /* config the parmeters and see if we need to re-init the stream*/
1064 ALOGV("%s: Configure Snapshot Dimension", __func__);
1065 ret = configSnapshotDimension(&dim);
1066 if (ret != NO_ERROR) {
1067 ALOGE("%s: Setting snapshot dimension failed", __func__);
1068 goto end;
1069 }
1070
1071 /* Initialize stream - set format, acquire channel */
1072 ret = initSnapshotFormat(&dim);
1073 if (NO_ERROR != ret) {
1074 ALOGE("%s: error - can't init nonZSL stream!", __func__);
1075 goto end;
1076 }
1077
1078 ret = initSnapshotBuffers(&dim, num_of_snapshots);
1079 if ( NO_ERROR != ret ){
1080 ALOGE("%s: Failure allocating memory for Snapshot buffers", __func__);
1081 goto end;
1082 }
1083
1084 {
1085 /*register main and thumbnail buffers at back-end for frameproc*/
1086 for (int i = 0; i < num_of_snapshots; i++) {
1087 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i,
1088 mSnapshotStreamBuf.frame[i].fd, mHalCamCtrl->mSnapshotMemory.size, mCameraId,
1089 CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
1090 ALOGE("%s: sending mapping data Msg Failed", __func__);
1091 }
1092 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, i,
1093 mPostviewStreamBuf.frame[i].fd, mHalCamCtrl->mThumbnailMemory.size, mCameraId,
1094 CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
1095 ALOGE("%s: sending mapping data Msg Failed", __func__);
1096 }
1097 }
1098 }
1099
1100end:
1101 /* Based on what state we are in, we'll need to handle error -
1102 like deallocating memory if we have already allocated */
1103 if (ret != NO_ERROR) {
1104 handleError();
1105 }
1106 ALOGV("%s: X", __func__);
1107 return ret;
1108
1109}
1110
1111status_t QCameraStream_Snapshot::initRawSnapshot(int num_of_snapshots)
1112{
1113 status_t ret = NO_ERROR;
1114 cam_ctrl_dimension_t dim;
1115 bool initSnapshot = false;
1116 mm_camera_op_mode_type_t op_mode;
1117
1118 ALOGV("%s: E", __func__);
1119
1120 /* Set camera op mode to MM_CAMERA_OP_MODE_CAPTURE */
1121 ALOGV("%s: Setting OP_MODE_CAPTURE", __func__);
1122 op_mode = MM_CAMERA_OP_MODE_CAPTURE;
1123 if( NO_ERROR != cam_config_set_parm(mCameraId,
1124 MM_CAMERA_PARM_OP_MODE, &op_mode)) {
1125 ALOGE("%s: MM_CAMERA_OP_MODE_CAPTURE failed", __func__);
1126 ret = FAILED_TRANSACTION;
1127 goto end;
1128 }
1129
1130 /* For raw snapshot, we do not know the dimension as it
1131 depends on sensor to sensor. We call getDimension which will
1132 give us raw width and height */
1133 memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
1134 ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
1135 if (MM_CAMERA_OK != ret) {
1136 ALOGE("%s: error - can't get dimension!", __func__);
1137 ALOGV("%s: X", __func__);
1138 goto end;
1139 }
1140 ALOGV("%s: Raw Snapshot dimension: %dx%d", __func__,
1141 dim.raw_picture_width,
1142 dim.raw_picture_height);
1143
1144
1145 ret = initRawSnapshotChannel(&dim, num_of_snapshots);
1146 if (NO_ERROR != ret) {
1147 ALOGE("%s: error - can't init nonZSL stream!", __func__);
1148 goto end;
1149 }
1150
1151 ret = initRawSnapshotBuffers(&dim, num_of_snapshots);
1152 if ( NO_ERROR != ret ){
1153 ALOGE("%s: Failure allocating memory for Raw Snapshot buffers",
1154 __func__);
1155 goto end;
1156 }
1157 setSnapshotState(SNAPSHOT_STATE_INITIALIZED);
1158
1159end:
1160 if (ret != NO_ERROR) {
1161 handleError();
1162 }
1163 ALOGV("%s: X", __func__);
1164 return ret;
1165}
1166
1167status_t QCameraStream_Snapshot::initFullLiveshot(void)
1168{
1169 status_t ret = NO_ERROR;
1170 cam_ctrl_dimension_t dim;
1171 bool matching = true;
1172
1173 memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
1174 ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
1175 if (MM_CAMERA_OK != ret) {
1176 ALOGE("%s: error - can't get dimension!", __func__);
1177 return ret;
1178 }
1179#if 1
1180 /* First check if the picture resolution is the same, if not, change it*/
1181 mHalCamCtrl->getPictureSize(&mPictureWidth, &mPictureHeight);
1182 ALOGV("%s: Picture size received: %d x %d", __func__,
1183 mPictureWidth, mPictureHeight);
1184
1185 //Use main image as input to encoder to generate thumbnail
1186 mThumbnailWidth = dim.picture_width;
1187 mThumbnailHeight = dim.picture_height;
1188 matching = (mPictureWidth == dim.picture_width) &&
1189 (mPictureHeight == dim.picture_height);
1190
1191 //Actual thumbnail size requested
1192 mPostviewWidth = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
1193 mPostviewHeight = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
1194
1195 mDropThumbnail = false;
1196 if (mPostviewWidth == 0 && mPostviewHeight == 0) {
1197 mPostviewWidth = THUMBNAIL_DEFAULT_WIDTH;
1198 mPostviewHeight = THUMBNAIL_DEFAULT_HEIGHT;
1199 mDropThumbnail = true;
1200 }
1201
1202 if (!matching) {
1203 dim.picture_width = mPictureWidth;
1204 dim.picture_height = mPictureHeight;
1205 dim.ui_thumbnail_height = mThumbnailHeight;
1206 dim.ui_thumbnail_width = mThumbnailWidth;
1207 }
1208 ALOGV("%s: Picture size to set: %d x %d", __func__,
1209 dim.picture_width, dim.picture_height);
1210 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
1211#endif
1212 /* Initialize stream - set format, acquire channel */
1213 ret = initSnapshotFormat(&dim);
1214 if (NO_ERROR != ret) {
1215 ALOGE("%s: error - can't init nonZSL stream!", __func__);
1216 return ret;
1217 }
1218 ret = initSnapshotBuffers(&dim, 1);
1219 if ( NO_ERROR != ret ){
1220 ALOGE("%s: Failure allocating memory for Snapshot buffers", __func__);
1221 return ret;
1222 }
1223
1224 return ret;
1225}
1226
1227status_t QCameraStream_Snapshot::initZSLSnapshot(void)
1228{
1229 status_t ret = NO_ERROR;
1230 cam_ctrl_dimension_t dim;
1231 mm_camera_op_mode_type_t op_mode;
1232
1233 ALOGV("%s: E", __func__);
1234
1235 ALOGV("%s: Get current dimension", __func__);
1236 /* Query mm_camera to get current dimension */
1237 memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
1238 ret = cam_config_get_parm(mCameraId,
1239 MM_CAMERA_PARM_DIMENSION, &dim);
1240 if (NO_ERROR != ret) {
1241 ALOGE("%s: error - can't get preview dimension!", __func__);
1242 ret = FAILED_TRANSACTION;
1243 goto end;
1244 }
1245
1246 /* config the parmeters and see if we need to re-init the stream*/
1247 ALOGV("%s: Configure Snapshot Dimension", __func__);
1248 ret = configSnapshotDimension(&dim);
1249 if (ret != NO_ERROR) {
1250 ALOGE("%s: Setting snapshot dimension failed", __func__);
1251 goto end;
1252 }
1253
1254 /* Initialize stream - set format, acquire channel */
1255 ret = initSnapshotFormat(&dim);
1256 if (NO_ERROR != ret) {
1257 ALOGE("%s: error - can't init nonZSL stream!", __func__);
1258 goto end;
1259 }
1260
1261 /* For ZSL we'll have to allocate buffers for internal queue
1262 maintained by mm-camera lib plus around 3 buffers used for
1263 data handling by lower layer.*/
1264
1265 ret = initSnapshotBuffers(&dim, mHalCamCtrl->getZSLQueueDepth() + 3);
1266 if ( NO_ERROR != ret ){
1267 ALOGE("%s: Failure allocating memory for Snapshot buffers", __func__);
1268 goto end;
1269 }
1270 /*register main and thumbnail buffers at back-end for frameproc*/
1271 for (int i = 0; i < mHalCamCtrl->getZSLQueueDepth() + 3; i++) {
1272 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i,
1273 mSnapshotStreamBuf.frame[i].fd, mHalCamCtrl->mSnapshotMemory.size, mCameraId,
1274 CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
1275 ALOGE("%s: sending mapping data Msg Failed", __func__);
1276 }
1277 }
1278
1279end:
1280 /* Based on what state we are in, we'll need to handle error -
1281 like deallocating memory if we have already allocated */
1282 if (ret != NO_ERROR) {
1283 handleError();
1284 }
1285 ALOGV("%s: X", __func__);
1286 return ret;
1287
1288}
1289
1290status_t QCameraStream_Snapshot::
1291takePictureJPEG(void)
1292{
1293 status_t ret = NO_ERROR;
1294
1295 ALOGV("%s: E", __func__);
1296
1297 if (mHalCamCtrl->mHdrMode == HDR_MODE) {
1298 hdrRawCount = 0;
1299 hdrJpegCount = 0;
1300 }
1301 /* Take snapshot */
1302 ALOGV("%s: Call MM_CAMERA_OPS_SNAPSHOT", __func__);
1303 if (NO_ERROR != cam_ops_action(mCameraId,
1304 true,
1305 MM_CAMERA_OPS_SNAPSHOT,
1306 this)) {
1307 ALOGE("%s: Failure taking snapshot", __func__);
1308 ret = FAILED_TRANSACTION;
1309 goto end;
1310 }
1311
1312 /* TBD: Temp: to be removed once event callback
1313 is implemented in mm-camera lib */
1314 pthread_attr_t attr;
1315 pthread_attr_init(&attr);
1316 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1317 pthread_create(&mSnapshotThread,&attr,
1318 snapshot_thread, (void *)this);
1319
1320end:
1321 if (ret != NO_ERROR) {
1322 handleError();
1323 }
1324
1325 ALOGV("%s: X", __func__);
1326 return ret;
1327
1328}
1329
1330status_t QCameraStream_Snapshot::
1331takePictureRaw(void)
1332{
1333 status_t ret = NO_ERROR;
1334
1335 ALOGV("%s: E", __func__);
1336
1337 /* Take snapshot */
1338 ALOGV("%s: Call MM_CAMERA_OPS_SNAPSHOT", __func__);
1339 if (NO_ERROR != cam_ops_action(mCameraId,
1340 true,
1341 MM_CAMERA_OPS_RAW,
1342 this)) {
1343 ALOGE("%s: Failure taking snapshot", __func__);
1344 ret = FAILED_TRANSACTION;
1345 goto end;
1346 }
1347
1348 /* TBD: Temp: to be removed once event callback
1349 is implemented in mm-camera lib */
1350 /* Wait for snapshot frame callback to return*/
1351 pthread_attr_t attr;
1352 pthread_attr_init(&attr);
1353 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1354 pthread_create(&mSnapshotThread,&attr,
1355 snapshot_thread, (void *)this);
1356
1357end:
1358 if (ret != NO_ERROR) {
1359 handleError();
1360 }
1361 ALOGV("%s: X", __func__);
1362 return ret;
1363
1364}
1365
1366status_t QCameraStream_Snapshot::
1367takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame)
1368{
1369 status_t ret = NO_ERROR;
1370 int mJpegMaxSize;
1371 int mNuberOfVFEOutputs = 0;
1372 common_crop_t crop_info;
1373 camera_notify_callback notifyCb;
1374 camera_data_callback dataCb;
1375 cam_ctrl_dimension_t dim;
1376
1377 mStopCallbackLock.lock();
1378 if (!mHalCamCtrl->mStateLiveshot) {
1379 ALOGE("%s: Picture Cancelled", __func__);
1380 mStopCallbackLock.unlock();
1381 return FAILED_TRANSACTION;
1382 }
1383
1384 ret = cam_config_get_parm(mHalCamCtrl->mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE,
1385 &mNuberOfVFEOutputs);
1386 if (ret != MM_CAMERA_OK) {
1387 ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed");
1388 cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame);
1389 mStopCallbackLock.unlock();
1390 return FAILED_TRANSACTION;
1391 }
1392
1393 mm_camera_ch_data_buf_t* frame =
1394 (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
1395 if (frame == NULL) {
1396 ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
1397 cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame);
1398 mStopCallbackLock.unlock();
1399 return FAILED_TRANSACTION;
1400 }
1401 memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t));
1402
1403 if (mNuberOfVFEOutputs == 1){
1404 ALOGV("<DEBUG> Liveshot buffer idx:%d",frame->def.idx);
1405 frame->snapshot.main.frame = frame->def.frame;
1406 frame->snapshot.main.idx = frame->def.idx;
1407 frame->snapshot.thumbnail.frame = frame->def.frame;
1408 frame->snapshot.thumbnail.idx = frame->def.idx;
1409 } else {
1410 ALOGV("<DEBUG> Liveshot buffer idx:%d",frame->video.video.idx);
1411 frame->snapshot.main.frame = frame->video.video.frame;
1412 frame->snapshot.main.idx = frame->video.video.idx;
1413 frame->snapshot.thumbnail.frame = frame->video.video.frame;
1414 frame->snapshot.thumbnail.idx = frame->video.video.idx;
1415 }
1416
1417 memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
1418 ret = cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
1419 if (MM_CAMERA_OK != ret) {
1420 ALOGE("%s: X error - can't get dimension!", __func__);
1421 cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame);
1422 setModeLiveSnapshot(false);
1423 mStopCallbackLock.unlock();
1424 return FAILED_TRANSACTION;
1425 }
1426 dim.picture_width = dim.video_width;
1427 dim.picture_height = dim.video_height;
1428 dim.ui_thumbnail_width = dim.video_width;
1429 dim.ui_thumbnail_height = dim.video_height;
1430
1431 if (mNuberOfVFEOutputs == 1){
1432 dim.main_img_format = dim.prev_format;
1433 dim.thumb_format = dim.prev_format;
1434 } else {
1435 dim.main_img_format = dim.enc_format;
1436 dim.thumb_format = dim.enc_format;
1437 }
1438 initSnapshotBuffers(&dim,1);
1439
1440 /* set flag to indicate we are doing livesnapshot */
1441 resetSnapshotCounters( );
1442 setModeLiveSnapshot(true);
1443
1444 mStopCallbackLock.unlock();
1445 if (mHalCamCtrl->mStateLiveshot) {
1446 if(!mHalCamCtrl->mShutterSoundPlayed) {
1447 notifyShutter(&crop_info, true);
1448 }
1449 notifyShutter(&crop_info, false);
1450 mHalCamCtrl->mShutterSoundPlayed = false;
1451 }
1452 mStopCallbackLock.lock();
1453
1454 // send upperlayer callback for raw image (data or notify, not both)
1455 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
1456 dataCb = mHalCamCtrl->mDataCb;
1457 } else {
1458 dataCb = NULL;
1459 }
1460 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){
1461 notifyCb = mHalCamCtrl->mNotifyCb;
1462 } else {
1463 notifyCb = NULL;
1464 }
1465
1466 mPictureWidth = dim.picture_width;
1467 mPictureHeight = dim.picture_height;
1468 mThumbnailWidth = dim.ui_thumbnail_width;
1469 mThumbnailHeight = dim.ui_thumbnail_height;
1470 mPictureFormat = dim.main_img_format;
1471 mThumbnailFormat = dim.thumb_format;
1472
1473 mJpegMaxSize = mPictureWidth * mPictureHeight * 1.5;
1474
1475 ALOGV("Liveshot res = %d X %d, Thumabnail = %d % %d",
1476 mPictureWidth,mPictureHeight,mThumbnailWidth,mThumbnailHeight);
1477
1478 memset(&crop_info, 0, sizeof(common_crop_t));
1479 crop_info.in1_w = mPictureWidth;
1480 crop_info.in1_h = mPictureHeight;
1481 /* For low power live snapshot the thumbnail output size is set to default size.
1482 In case of live snapshot video buffer = thumbnail buffer. For higher resolutions
1483 the thumnail will be dropped if its more than 64KB. To avoid thumbnail drop
1484 set thumbnail as configured by application. This will be a size lower than video size*/
1485 mDropThumbnail = false;
1486 if(mHalCamCtrl->thumbnailWidth == 0 && mHalCamCtrl->thumbnailHeight == 0) {
1487 ALOGE("Live Snapshot thumbnail will be dropped as indicated by application");
1488 mDropThumbnail = true;
1489 }
1490 crop_info.out1_w = mHalCamCtrl->thumbnailWidth;
1491 crop_info.out1_h = mHalCamCtrl->thumbnailHeight;
1492 ret = encodeData(frame, &crop_info, mJpegMaxSize, 0);
1493 if (ret != NO_ERROR) {
1494 ALOGE("%s: Failure configuring JPEG encoder", __func__);
1495 setModeLiveSnapshot(false);
1496 mStopCallbackLock.unlock();
1497 ret = FAILED_TRANSACTION;
1498 goto end;
1499 }
1500 mStopCallbackLock.unlock();
1501 if (dataCb && mHalCamCtrl->mStateLiveshot) {
1502 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mRecordingMemory.camera_memory[frame->video.video.idx],
1503 1, NULL, mHalCamCtrl->mCallbackCookie);
1504 }
1505 if (notifyCb && mHalCamCtrl->mStateLiveshot) {
1506 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
1507 }
1508end:
1509 ALOGV("%s: X", __func__);
1510 return ret;
1511}
1512
1513status_t QCameraStream_Snapshot::
1514takePictureZSL(void)
1515{
1516 status_t ret = NO_ERROR;
1517 mm_camera_ops_parm_get_buffered_frame_t param;
1518
1519 ALOGV("%s: E", __func__);
1520
1521 memset(&param, 0, sizeof(param));
1522 param.ch_type = MM_CAMERA_CH_SNAPSHOT;
1523
1524 /* Take snapshot */
1525 ALOGV("%s: Call MM_CAMERA_OPS_GET_BUFFERED_FRAME", __func__);
1526
1527 mNumOfSnapshot = mHalCamCtrl->getNumOfSnapshots();
1528 // it's just for stabilization for dequeuing zsl buffer frame
1529 // 13.2 ~ 22.4fps
1530 usleep(80000);
1531 if (NO_ERROR != cam_ops_action(mCameraId,
1532 true,
1533 MM_CAMERA_OPS_GET_BUFFERED_FRAME,
1534 &param)) {
1535 ALOGE("%s: Failure getting zsl frame(s)", __func__);
1536 ret = FAILED_TRANSACTION;
1537 goto end;
1538 }
1539
1540 /* TBD: Temp: to be removed once event callback
1541 is implemented in mm-camera lib */
1542/* pthread_attr_t attr;
1543 pthread_attr_init(&attr);
1544 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1545 pthread_create(&mSnapshotThread,&attr,
1546 snapshot_thread, (void *)this);
1547*/
1548end:
1549 ALOGV("%s: X", __func__);
1550 return ret;
1551}
1552
1553status_t QCameraStream_Snapshot::
1554startStreamZSL(void)
1555{
1556 status_t ret = NO_ERROR;
1557
1558 ALOGV("%s: E", __func__);
1559
1560 /* Start ZSL - it'll start queuing the frames */
1561 ALOGV("%s: Call MM_CAMERA_OPS_ZSL", __func__);
1562 if (NO_ERROR != cam_ops_action(mCameraId,
1563 true,
1564 MM_CAMERA_OPS_ZSL,
1565 this)) {
1566 ALOGE("%s: Failure starting ZSL stream", __func__);
1567 ret = FAILED_TRANSACTION;
1568 goto end;
1569 }
1570
1571end:
1572 ALOGV("%s: X", __func__);
1573 return ret;
1574
1575}
1576
1577status_t QCameraStream_Snapshot::
1578encodeData(mm_camera_ch_data_buf_t* recvd_frame,
1579 common_crop_t *crop_info,
1580 int frame_len,
1581 bool enqueued)
1582{
1583 status_t ret = NO_ERROR;
1584 cam_ctrl_dimension_t dimension;
1585 struct msm_frame *postviewframe;
1586 struct msm_frame *mainframe;
1587 common_crop_t crop;
1588 cam_point_t main_crop_offset;
1589 cam_point_t thumb_crop_offset;
1590 int width, height;
1591 uint8_t *thumbnail_buf;
1592 uint32_t thumbnail_fd;
1593 uint8_t hw_encode = true;
1594 int mNuberOfVFEOutputs = 0;
1595
1596 omx_jpeg_encode_params encode_params;
1597
1598 /* If it's the only frame, we directly pass to encoder.
1599 If not, we'll queue it and check during next jpeg .
1600 Also, if the queue isn't empty then we need to queue this
1601 one too till its turn comes (only if it's not already
1602 queued up there)*/
1603 ALOGV("%s: getSnapshotState()=%d, enqueued =%d, Q empty=%d", __func__, getSnapshotState(), enqueued, mSnapshotQueue.isEmpty());
1604 ALOGV("%s: mNumOfRecievedJPEG=%d, mNumOfSnapshot =%d", __func__, mNumOfRecievedJPEG, mNumOfSnapshot);
1605 if(mHalCamCtrl->thumbnailWidth == 0 || mHalCamCtrl->thumbnailHeight == 0) {
1606 ALOGV("Snapshot thumbnail will be dropped as indicated by application");
1607 mDropThumbnail = true;
1608 }
1609 if((getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) ||
1610 (!mSnapshotQueue.isEmpty() && !enqueued)){ /*busy and new buffer*/
1611 /* encoding is going on. Just queue the frame for now.*/
1612 ALOGV("%s: JPEG encoding in progress."
1613 "Enqueuing frame id(%d) for later processing.", __func__,
1614 recvd_frame->snapshot.main.idx);
1615 mSnapshotQueue.enqueue((void *)recvd_frame);
1616 } else if (enqueued ||
1617 (mNumOfRecievedJPEG != mNumOfSnapshot && mNumOfRecievedJPEG != 0)) { /*not busy, not first*/
1618 ALOGV("%s: JPG not busy, not first frame.", __func__);
1619
1620 // For full-size live shot, use mainimage to generate thumbnail
1621 if (isFullSizeLiveshot()) {
1622 postviewframe = recvd_frame->snapshot.main.frame;
1623 } else {
1624 postviewframe = recvd_frame->snapshot.thumbnail.frame;
1625 }
1626 mainframe = recvd_frame->snapshot.main.frame;
1627 cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dimension);
1628 ALOGV("%s: main_fmt =%d, tb_fmt =%d", __func__, dimension.main_img_format, dimension.thumb_format);
1629 /*since this is the continue job, we only care about the input buffer*/
1630 encode_params.thumbnail_buf = (uint8_t *)postviewframe->buffer;
1631 encode_params.thumbnail_fd = postviewframe->fd;
1632 encode_params.snapshot_buf = (uint8_t *)mainframe->buffer;
1633 encode_params.snapshot_fd = mainframe->fd;
1634 encode_params.dimension = &dimension;
1635 /*update exif parameters in HAL*/
1636 mHalCamCtrl->setExifTags();
1637
1638 encode_params.exif_data = mHalCamCtrl->getExifData();
1639 encode_params.exif_numEntries = mHalCamCtrl->getExifTableNumEntries();
1640 if (!omxJpegEncodeNext(&encode_params)){
1641 ALOGE("%s: Failure! JPEG encoder returned error.", __func__);
1642 ret = FAILED_TRANSACTION;
1643 goto end;
1644 }
1645 /* Save the pointer to the frame sent for encoding. we'll need it to
1646 tell kernel that we are done with the frame.*/
1647 mCurrentFrameEncoded = recvd_frame;
1648 setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODING);
1649 } else { /*not busy and new buffer (first job)*/
1650
1651 ALOGV("%s: JPG Idle and first frame.", __func__);
1652
1653 // For full-size live shot, use mainimage to generate thumbnail
1654 if (isFullSizeLiveshot()){
1655 postviewframe = recvd_frame->snapshot.main.frame;
1656 } else {
1657 postviewframe = recvd_frame->snapshot.thumbnail.frame;
1658 }
1659 mainframe = recvd_frame->snapshot.main.frame;
1660 cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dimension);
1661 ALOGV("%s: main_fmt =%d, tb_fmt =%d", __func__, dimension.main_img_format, dimension.thumb_format);
1662
1663 dimension.orig_picture_dx = mPictureWidth;
1664 dimension.orig_picture_dy = mPictureHeight;
1665
1666 if(!mDropThumbnail) {
1667 if(isZSLMode()) {
1668 ALOGV("Setting input thumbnail size to previewWidth= %d previewheight= %d in ZSL mode",
1669 mHalCamCtrl->mPreviewWidth, mHalCamCtrl->mPreviewHeight);
1670 dimension.thumbnail_width = width = mHalCamCtrl->mPreviewWidth;
1671 dimension.thumbnail_height = height = mHalCamCtrl->mPreviewHeight;
1672 } else {
1673 dimension.thumbnail_width = width = mThumbnailWidth;
1674 dimension.thumbnail_height = height = mThumbnailHeight;
1675 }
1676 } else {
1677 dimension.thumbnail_width = width = 0;
1678 dimension.thumbnail_height = height = 0;
1679 }
1680 dimension.main_img_format = mPictureFormat;
1681 dimension.thumb_format = mThumbnailFormat;
1682
1683 /*TBD: Move JPEG handling to the mm-camera library */
1684 ALOGV("Setting callbacks, initializing encoder and start encoding.");
1685 ALOGV(" Passing my obj: %x", (unsigned int) this);
1686 set_callbacks(snapshot_jpeg_fragment_cb, snapshot_jpeg_cb, this,
1687 mHalCamCtrl->mJpegMemory.camera_memory[0]->data, &mJpegOffset);
1688
1689 if (isLiveSnapshot() || isFullSizeLiveshot()) {
1690 /* determine the target type */
1691 ret = cam_config_get_parm(mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE,
1692 &mNuberOfVFEOutputs);
1693 if (ret != MM_CAMERA_OK) {
1694 ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed");
1695 ret = BAD_VALUE;
1696 }
1697 /* VFE 2x has hardware limitation:
1698 * It can't support concurrent
1699 * video encoding and jpeg encoding
1700 * So switch to software for liveshot
1701 */
1702 if (mNuberOfVFEOutputs == 1)
1703 hw_encode = false;
1704 }
1705 ALOGV("%s: hw_encode: %d\n",__func__, hw_encode);
1706
1707 if(omxJpegStart(hw_encode) != NO_ERROR){
1708 ALOGE("Error In omxJpegStart!!! Return");
1709 ret = FAILED_TRANSACTION;
1710 goto end;
1711 }
1712
1713 if (mHalCamCtrl->getJpegQuality())
1714 mm_jpeg_encoder_setMainImageQuality(mHalCamCtrl->getJpegQuality());
1715 else
1716 mm_jpeg_encoder_setMainImageQuality(85);
1717
1718 ALOGV("%s: Dimension to encode: main: %dx%d thumbnail: %dx%d", __func__,
1719 dimension.orig_picture_dx, dimension.orig_picture_dy,
1720 dimension.thumbnail_width, dimension.thumbnail_height);
1721
1722 /*TBD: Pass 0 as cropinfo for now as v4l2 doesn't provide
1723 cropinfo. It'll be changed later.*/
1724 memset(&crop,0,sizeof(common_crop_t));
1725 memset(&main_crop_offset,0,sizeof(cam_point_t));
1726 memset(&thumb_crop_offset,0,sizeof(cam_point_t));
1727
1728 /* Setting crop info */
1729
1730 /*Main image*/
1731 crop.in2_w=mCrop.snapshot.main_crop.width;// dimension.picture_width
1732 crop.in2_h=mCrop.snapshot.main_crop.height;// dimension.picture_height;
1733 if (!mJpegDownscaling) {
1734 crop.out2_w = mPictureWidth;
1735 crop.out2_h = mPictureHeight;
1736 } else {
1737 crop.out2_w = mActualPictureWidth;
1738 crop.out2_h = mActualPictureHeight;
1739 if (!crop.in2_w || !crop.in2_h) {
1740 crop.in2_w = mPictureWidth;
1741 crop.in2_h = mPictureHeight;
1742 }
1743 }
1744 main_crop_offset.x=mCrop.snapshot.main_crop.left;
1745 main_crop_offset.y=mCrop.snapshot.main_crop.top;
1746 /*Thumbnail image*/
1747 crop.in1_w=mCrop.snapshot.thumbnail_crop.width; //dimension.thumbnail_width;
1748 crop.in1_h=mCrop.snapshot.thumbnail_crop.height; // dimension.thumbnail_height;
1749 if(isLiveSnapshot() || isFullSizeLiveshot() || isZSLMode()) {
1750 crop.out1_w= mHalCamCtrl->thumbnailWidth;
1751 crop.out1_h= mHalCamCtrl->thumbnailHeight;
1752 ALOGV("Thumbnail width= %d height= %d for livesnapshot", crop.out1_w, crop.out1_h);
1753 } else {
1754 crop.out1_w = width;
1755 crop.out1_h = height;
1756 }
1757 thumb_crop_offset.x=mCrop.snapshot.thumbnail_crop.left;
1758 thumb_crop_offset.y=mCrop.snapshot.thumbnail_crop.top;
1759
1760 if (crop.out1_w > crop.out2_w || crop.out1_h > crop.out2_h) {
1761 crop.out1_w = crop.out2_w;
1762 crop.out1_h = crop.out2_h;
1763 }
1764 //update exif parameters in HAL
1765 mHalCamCtrl->initExifData();
1766
1767 /*Fill in the encode parameters*/
1768 encode_params.dimension = (const cam_ctrl_dimension_t *)&dimension;
1769 //if (!isFullSizeLiveshot()) {
1770 encode_params.thumbnail_buf = (uint8_t *)postviewframe->buffer;
1771 encode_params.thumbnail_fd = postviewframe->fd;
1772 encode_params.thumbnail_offset = postviewframe->phy_offset;
1773 encode_params.thumb_crop_offset = &thumb_crop_offset;
1774 //}
1775 encode_params.snapshot_buf = (uint8_t *)mainframe->buffer;
1776 encode_params.snapshot_fd = mainframe->fd;
1777 encode_params.snapshot_offset = mainframe->phy_offset;
1778 encode_params.scaling_params = &crop;
1779 encode_params.exif_data = mHalCamCtrl->getExifData();
1780 encode_params.exif_numEntries = mHalCamCtrl->getExifTableNumEntries();
1781
1782 if (isLiveSnapshot() && !isFullSizeLiveshot())
1783 encode_params.a_cbcroffset = mainframe->cbcr_off;
1784 else
1785 encode_params.a_cbcroffset = -1;
1786 encode_params.main_crop_offset = &main_crop_offset;
1787
1788 if (mDropThumbnail)
1789 encode_params.hasThumbnail = 0;
1790 else
1791 encode_params.hasThumbnail = 1;
1792 encode_params.thumb_crop_offset = &thumb_crop_offset;
1793 encode_params.main_format = dimension.main_img_format;
1794 encode_params.thumbnail_format = dimension.thumb_format;
1795
1796 if (!omxJpegEncode(&encode_params)){
1797 ALOGE("%s: Failure! JPEG encoder returned error.", __func__);
1798 ret = FAILED_TRANSACTION;
1799 goto end;
1800 }
1801
1802 /* Save the pointer to the frame sent for encoding. we'll need it to
1803 tell kernel that we are done with the frame.*/
1804 mCurrentFrameEncoded = recvd_frame;
1805 setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODING);
1806 }
1807
1808end:
1809 ALOGV("%s: X", __func__);
1810 return ret;
1811}
1812
1813/* Called twice - 1st to play shutter sound and 2nd to configure
1814 overlay/surfaceflinger for postview */
1815void QCameraStream_Snapshot::notifyShutter(common_crop_t *crop,
1816 bool mPlayShutterSoundOnly)
1817{
1818 ALOGV("%s: E", __func__);
1819 if(!mActive && !isLiveSnapshot()) {
1820 ALOGE("__debbug: Snapshot thread stopped \n");
1821 return;
1822 }
1823 if(mHalCamCtrl->mNotifyCb)
1824 mHalCamCtrl->mNotifyCb(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
1825 mHalCamCtrl->mCallbackCookie);
1826 ALOGV("%s: X", __func__);
1827}
1828
1829status_t QCameraStream_Snapshot::
1830encodeDisplayAndSave(mm_camera_ch_data_buf_t* recvd_frame,
1831 bool enqueued)
1832{
1833 status_t ret = NO_ERROR;
1834 struct msm_frame *postview_frame;
1835 struct ion_flush_data cache_inv_data;
1836 int ion_fd;
1837 int buf_index = 0;
1838 ssize_t offset_addr = 0;
1839 common_crop_t dummy_crop;
1840 /* send frame for encoding */
1841 ALOGV("%s: Send frame for encoding", __func__);
1842 /*TBD: Pass 0 as cropinfo for now as v4l2 doesn't provide
1843 cropinfo. It'll be changed later.*/
1844 if(!mActive) {
1845 ALOGE("Cancel Picture.. Stop is called");
1846 return NO_ERROR;
1847 }
1848 if(isZSLMode()){
1849 ALOGV("%s: set JPEG rotation in ZSL mode", __func__);
1850 mHalCamCtrl->setJpegRotation(isZSLMode());
1851 }
1852#ifdef USE_ION
1853 /*Clean out(Write-back) cache before sending for JPEG*/
1854 memset(&cache_inv_data, 0, sizeof(struct ion_flush_data));
1855 cache_inv_data.vaddr = (void*)recvd_frame->snapshot.main.frame->buffer;
1856 cache_inv_data.fd = recvd_frame->snapshot.main.frame->fd;
1857 cache_inv_data.handle = recvd_frame->snapshot.main.frame->fd_data.handle;
1858 cache_inv_data.length = recvd_frame->snapshot.main.frame->ion_alloc.len;
1859 ion_fd = recvd_frame->snapshot.main.frame->ion_dev_fd;
1860 if(ion_fd > 0) {
1861 if(mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_INV_CACHES) < 0)
1862 ALOGE("%s: Cache Invalidate failed\n", __func__);
1863 else {
1864 ALOGV("%s: Successful cache invalidate\n", __func__);
1865 if(!isFullSizeLiveshot()) {
1866 ion_fd = recvd_frame->snapshot.thumbnail.frame->ion_dev_fd;
1867 cache_inv_data.vaddr = (void*)recvd_frame->snapshot.thumbnail.frame->buffer;
1868 cache_inv_data.fd = recvd_frame->snapshot.thumbnail.frame->fd;
1869 cache_inv_data.handle = recvd_frame->snapshot.thumbnail.frame->fd_data.handle;
1870 cache_inv_data.length = recvd_frame->snapshot.thumbnail.frame->ion_alloc.len;
1871 if(mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_INV_CACHES) < 0)
1872 ALOGE("%s: Cache Invalidate failed\n", __func__);
1873 else
1874 ALOGV("%s: Successful cache invalidate\n", __func__);
1875 }
1876 }
1877 }
1878#endif
1879 memset(&dummy_crop,0,sizeof(common_crop_t));
1880 ret = encodeData(recvd_frame, &dummy_crop, mSnapshotStreamBuf.frame_len,
1881 enqueued);
1882 if (ret != NO_ERROR) {
1883 ALOGE("%s: Failure configuring JPEG encoder", __func__);
1884
1885 goto end;
1886 }
1887
1888 /* Display postview image*/
1889 /* If it's burst mode, we won't be displaying postview of all the captured
1890 images - only the first one */
1891 ALOGV("%s: Burst mode flag %d", __func__, mBurstModeFlag);
1892
1893end:
1894 ALOGV("%s: X", __func__);
1895 return ret;
1896}
1897
1898status_t QCameraStream_Snapshot::receiveRawPicture(mm_camera_ch_data_buf_t* recvd_frame)
1899{
1900 int buf_index = 0;
1901 common_crop_t crop;
1902 int rc = NO_ERROR;
1903 int cur_lux_idx = 0;
1904
1905 camera_notify_callback notifyCb;
1906 camera_data_callback dataCb, jpgDataCb;
1907
1908 ALOGV("%s: E ", __func__);
1909 mStopCallbackLock.lock( );
1910 if(!mActive) {
1911 mStopCallbackLock.unlock();
1912 ALOGV("%s: Stop receiving raw pic ", __func__);
1913 return NO_ERROR;
1914 }
1915
1916 if(getSnapshotState() == SNAPSHOT_STATE_ERROR) {
1917 cam_evt_buf_done(mCameraId, recvd_frame);
1918 }
1919
1920 mHalCamCtrl->dumpFrameToFile(recvd_frame->snapshot.main.frame, HAL_DUMP_FRM_MAIN);
1921 if (!isFullSizeLiveshot())
1922 mHalCamCtrl->dumpFrameToFile(recvd_frame->snapshot.thumbnail.frame,
1923 HAL_DUMP_FRM_THUMBNAIL);
1924
1925 /* If it's raw snapshot, we just want to tell upperlayer to save the image*/
1926 if(mSnapshotFormat == PICTURE_FORMAT_RAW) {
1927 ALOGV("%s: Call notifyShutter 2nd time in case of RAW", __func__);
1928 mStopCallbackLock.unlock();
1929 if(!mHalCamCtrl->mShutterSoundPlayed) {
1930 notifyShutter(&crop, true);
1931 }
1932 notifyShutter(&crop, false);
1933 mHalCamCtrl->mShutterSoundPlayed = false;
1934
1935 mStopCallbackLock.lock( );
1936 ALOGV("%s: Sending Raw Snapshot Callback to Upperlayer", __func__);
1937 buf_index = recvd_frame->def.idx;
1938
1939 if (mHalCamCtrl->mDataCb && mActive &&
1940 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)){
1941 dataCb = mHalCamCtrl->mDataCb;
1942 } else {
1943 dataCb = NULL;
1944 }
1945 mStopCallbackLock.unlock();
1946
1947 if(dataCb) {
1948 dataCb(
1949 CAMERA_MSG_COMPRESSED_IMAGE,
1950 mHalCamCtrl->mRawMemory.camera_memory[buf_index], 0, NULL,
1951 mHalCamCtrl->mCallbackCookie);
1952 }
1953 /* TBD: Temp: To be removed once event handling is enabled */
1954 mm_app_snapshot_done();
1955 } else {
1956 /*TBD: v4l2 doesn't have support to provide cropinfo along with
1957 frame. We'll need to query.*/
1958 memset(&crop, 0, sizeof(common_crop_t));
1959
1960 if(isZSLMode()){
1961 //Changes to stop sending Preview Frames when Snapshot issued
1962 //in ZSL case.
1963 mHalCamCtrl->mPauseFramedispatch = true;
1964 }
1965
1966 ALOGV("%s: Call notifyShutter 2nd time", __func__);
1967 /* The recvd_frame structre we receive from lower library is a local
1968 variable. So we'll need to save this structure so that we won't
1969 be later pointing to garbage data when that variable goes out of
1970 scope */
1971 mm_camera_ch_data_buf_t* frame =
1972 (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
1973 if (frame == NULL) {
1974 ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
1975 cam_evt_buf_done(mCameraId, recvd_frame);
1976 mStopCallbackLock.unlock();
1977 return BAD_VALUE;
1978 }
1979 memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t));
1980 rc = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_LUX_IDX, &cur_lux_idx);
1981
1982 if (cur_lux_idx > 370) {
1983 static int input_width = 0, input_height = 0;
1984 static int ret = 0;
1985 unsigned char *dnr_buffer;
1986 input_width = mPictureWidth;
1987 input_height = mPictureHeight;
1988
1989 ALOGV("%s: received frame %d * %d", __func__, input_width, input_height);
1990 {
1991 dnr_buffer = (uint8_t *)malloc(input_width*input_height*3/2);
1992 if (dnr_buffer == NULL)
1993 ALOGE("dnr_buffer alloc fail");
1994 ALOGV("dnr_buffer allocated size : %d", input_width*input_height*3/2);
1995 memcpy(dnr_buffer, (uint8_t *)frame->snapshot.main.frame->buffer, input_width*input_height*3/2);
1996 ALOGV("dnr_buffer memcpy completed.");
1997 }
1998 ALOGV("[DNR] DNR Processing Start.... %d * %d\n", mPictureWidth, mPictureHeight);
1999 ret = NO_ERROR;
2000 if (mHalCamCtrl->LINK_morpho_DNR_ProcessFrame)
insup.choid1471632013-04-12 21:43:09 -07002001 ret = (int)mHalCamCtrl->LINK_morpho_DNR_ProcessFrame(dnr_buffer, mPictureWidth, mPictureHeight, 1, 1); //bright->normal->dark
Iliyan Malchev6d016452013-03-27 16:27:56 -07002002 ALOGV("[DNR] DNR Processing result.... ret = %d\n", ret);
2003 memcpy((uint8_t *)recvd_frame->snapshot.main.frame->buffer, (uint8_t *)dnr_buffer, mPictureWidth*mPictureHeight*3/2);
2004 ALOGV("[DNR] DNR Processing END....\n");
2005 if(dnr_buffer)
2006 free(dnr_buffer);
2007 }
2008 //mStopCallbackLock.lock();
2009
2010 // only in ZSL mode and Wavelet Denoise is enabled, we will send frame to deamon to do WDN
2011 if (isZSLMode() && mHalCamCtrl->isWDenoiseEnabled()) {
2012 if(mIsDoingWDN){
2013 mWDNQueue.enqueue((void *)frame);
2014 ALOGV("%s: Wavelet denoise is going on, queue frame", __func__);
2015 rc = NO_ERROR;
2016 } else {
2017 ALOGV("%s: Start Wavelet denoise", __func__);
2018 mIsDoingWDN = true; // set the falg to true because we are going to do WDN
2019
2020 // No WDN is going on so far, we will start it here
2021 rc = doWaveletDenoise(frame);
2022 if ( NO_ERROR != rc ) {
2023 ALOGE("%s: Error while doing wavelet denoise", __func__);
2024 mIsDoingWDN = false;
2025 }
2026 }
2027 } else if (mHdrInfo.hdr_on) {
2028 mHdrInfo.recvd_frame[mHdrInfo.num_raw_received] = frame;
2029 mHdrInfo.num_raw_received++;
2030 ALOGV("%s Total %d Received %d frames, still need to receive %d frames", __func__,
2031 mHdrInfo.num_frame, mHdrInfo.num_raw_received, (mHdrInfo.num_frame - mHdrInfo.num_raw_received));
2032 if (mHdrInfo.num_raw_received == mHdrInfo.num_frame) {
2033 ALOGV(" Received all %d YUV frames, Invoke HDR", mHdrInfo.num_raw_received);
2034 doHdrProcessing();
2035 }
2036 }
2037 else {
2038 ALOGV("%s: encodeDisplayAndSave ", __func__);
2039 rc = encodeDisplayAndSave(frame, 0);
2040 }
2041
2042
2043 // send upperlayer callback for raw image (data or notify, not both)
2044 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
2045 dataCb = mHalCamCtrl->mDataCb;
2046 } else {
2047 dataCb = NULL;
2048 }
2049 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){
2050 notifyCb = mHalCamCtrl->mNotifyCb;
2051 } else {
2052 notifyCb = NULL;
2053 }
2054
2055 mStopCallbackLock.unlock();
2056 if(!mHalCamCtrl->mShutterSoundPlayed) {
2057 notifyShutter(&crop, true);
2058 }
2059 notifyShutter(&crop, false);
2060 mHalCamCtrl->mShutterSoundPlayed = false;
2061
2062 if(mHalCamCtrl->mHdrMode == HDR_MODE) {
2063 if ((hdrRawCount % 3) != 2)
2064 return NO_ERROR;
2065 else
2066 hdrRawCount++;
2067 }
2068
2069 if (rc != NO_ERROR)
2070 {
2071 ALOGE("%s: Error while encoding/displaying/saving image", __func__);
2072 cam_evt_buf_done(mCameraId, recvd_frame);
2073
2074 if(mHalCamCtrl->mDataCb &&
2075 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2076 /* get picture failed. Give jpeg callback with NULL data
2077 * to the application to restore to preview mode
2078 */
2079 jpgDataCb = mHalCamCtrl->mDataCb;
2080 } else {
2081 jpgDataCb = NULL;
2082 }
2083 ALOGE("%s: encode err so data cb", __func__);
2084 //mStopCallbackLock.unlock();
2085 if (dataCb) {
2086 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
2087 1, NULL, mHalCamCtrl->mCallbackCookie);
2088 }
2089 if (notifyCb) {
2090 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
2091 }
2092 if (jpgDataCb) {
2093 jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE,
2094 NULL, 0, NULL,
2095 mHalCamCtrl->mCallbackCookie);
2096 }
2097
2098 if (frame != NULL) {
2099 free(frame);
2100 }
2101 } else {
2102
2103 //mStopCallbackLock.unlock();
2104 if (dataCb) {
2105 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
2106 1, NULL, mHalCamCtrl->mCallbackCookie);
2107 }
2108 if (notifyCb) {
2109 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
2110 }
2111
2112 if (!isZSLMode() &&
2113 (!isLiveSnapshot() && !isFullSizeLiveshot())) {
2114 if(mHalCamCtrl->mDataCb &&
2115 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME)) {
2116 mHalCamCtrl->mDataCb(CAMERA_MSG_POSTVIEW_FRAME,mHalCamCtrl->mThumbnailMemory.camera_memory[0],
2117 0, NULL, mHalCamCtrl->mCallbackCookie);
2118 }
2119 }
2120 }
2121 }
2122
2123 ALOGV("%s: X", __func__);
2124 return NO_ERROR;
2125}
2126
2127//-------------------------------------------------------------------
2128// Helper Functions
2129//-------------------------------------------------------------------
2130void QCameraStream_Snapshot::handleError()
2131{
2132 mm_camera_channel_type_t ch_type;
2133 ALOGV("%s: E", __func__);
2134
2135 /* Depending upon the state we'll have to
2136 handle error */
2137 switch(getSnapshotState()) {
2138 case SNAPSHOT_STATE_JPEG_ENCODING:
2139 if(mJpegHeap != NULL) mJpegHeap.clear();
2140 mJpegHeap = NULL;
2141
2142 case SNAPSHOT_STATE_YUV_RECVD:
2143 case SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD:
2144 stopPolling();
2145 case SNAPSHOT_STATE_INITIALIZED:
2146 case SNAPSHOT_STATE_BUF_INITIALIZED:
2147 if (mSnapshotFormat == PICTURE_FORMAT_JPEG) {
2148 deinitSnapshotBuffers();
2149 }else
2150 {
2151 deinitRawSnapshotBuffers();
2152 }
2153 case SNAPSHOT_STATE_BUF_NOTIF_REGD:
2154 case SNAPSHOT_STATE_CH_ACQUIRED:
2155 if (mSnapshotFormat == PICTURE_FORMAT_JPEG) {
2156 deinitSnapshotChannel(MM_CAMERA_CH_SNAPSHOT);
2157 }else
2158 {
2159 deinitSnapshotChannel(MM_CAMERA_CH_RAW);
2160 }
2161 default:
2162 /* Set the state to ERROR */
2163 setSnapshotState(SNAPSHOT_STATE_ERROR);
2164 break;
2165 }
2166
2167 ALOGV("%s: X", __func__);
2168}
2169
2170void QCameraStream_Snapshot::setSnapshotState(int state)
2171{
2172 ALOGV("%s: Setting snapshot state to: %d",
2173 __func__, state);
2174 mSnapshotState = state;
2175}
2176
2177int QCameraStream_Snapshot::getSnapshotState()
2178{
2179 return mSnapshotState;
2180}
2181
2182void QCameraStream_Snapshot::setModeLiveSnapshot(bool value)
2183{
2184 mModeLiveSnapshot = value;
2185}
2186
2187bool QCameraStream_Snapshot::isLiveSnapshot(void)
2188{
2189 return mModeLiveSnapshot;
2190}
2191bool QCameraStream_Snapshot::isZSLMode()
2192{
2193 return (myMode & CAMERA_ZSL_MODE);
2194}
2195
2196void QCameraStream_Snapshot::setFullSizeLiveshot(bool value)
2197{
2198 mFullLiveshot = value;
2199}
2200
2201bool QCameraStream_Snapshot::isFullSizeLiveshot()
2202{
2203 return mFullLiveshot;
2204}
2205
2206void QCameraStream_Snapshot::resetSnapshotCounters(void )
2207{
2208 mNumOfSnapshot = mHalCamCtrl->getNumOfSnapshots();
2209 if (mNumOfSnapshot <= 0) {
2210 mNumOfSnapshot = 1;
2211 }
2212 mNumOfRecievedJPEG = 0;
2213 ALOGV("%s: Number of images to be captured: %d", __func__, mNumOfSnapshot);
2214}
2215
2216//------------------------------------------------------------------
2217// Constructor and Destructor
2218//------------------------------------------------------------------
2219QCameraStream_Snapshot::
2220QCameraStream_Snapshot(int cameraId, camera_mode_t mode)
2221 : QCameraStream(cameraId,mode),
2222 mSnapshotFormat(PICTURE_FORMAT_JPEG),
2223 mPictureWidth(0), mPictureHeight(0),
2224 mPictureFormat(CAMERA_YUV_420_NV21),
2225 mPostviewWidth(0), mPostviewHeight(0),
2226 mThumbnailWidth(0), mThumbnailHeight(0),
2227 mThumbnailFormat(CAMERA_YUV_420_NV21),
2228 mJpegOffset(0),
2229 mSnapshotState(SNAPSHOT_STATE_UNINIT),
2230 mNumOfSnapshot(1),
2231 mModeLiveSnapshot(false),
2232 mBurstModeFlag(false),
2233 mActualPictureWidth(0),
2234 mActualPictureHeight(0),
2235 mJpegDownscaling(false),
2236 mJpegHeap(NULL),
2237 mDisplayHeap(NULL),
2238 mPostviewHeap(NULL),
2239 mCurrentFrameEncoded(NULL),
2240 mJpegSessionId(0),
2241 mFullLiveshot(false),
2242 mDropThumbnail(false)
2243 {
2244 ALOGV("%s: E", __func__);
2245
2246 /*initialize snapshot queue*/
2247 mSnapshotQueue.init();
2248 memset (&mHdrInfo, 0, sizeof(snap_hdr_record_t ));
2249
2250 /*initialize WDN queue*/
2251 mWDNQueue.init();
2252 mIsDoingWDN = false;
2253
2254 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
2255 memset(&mPostviewStreamBuf, 0, sizeof(mPostviewStreamBuf));
2256 mSnapshotBufferNum = 0;
2257 mMainSize = 0;
2258 mThumbSize = 0;
2259 for(int i = 0; i < mMaxSnapshotBufferCount; i++) {
2260 mMainfd[i] = 0;
2261 mThumbfd[i] = 0;
2262 mCameraMemoryPtrMain[i] = NULL;
2263 mCameraMemoryPtrThumb[i] = NULL;
2264 }
2265 /*load the jpeg lib*/
2266 mJpegSessionId = omxJpegOpen( );
2267 ALOGV("%s: X", __func__);
2268 }
2269
2270
2271QCameraStream_Snapshot::~QCameraStream_Snapshot() {
2272 ALOGV("%s: E", __func__);
2273
2274 /* deinit snapshot queue */
2275 if (mSnapshotQueue.isInitialized()) {
2276 mSnapshotQueue.deinit();
2277 }
2278 /* deinit snapshot queue */
2279 if (mWDNQueue.isInitialized()) {
2280 mWDNQueue.deinit();
2281 }
2282
2283 if(mActive) {
2284 stop();
2285 }
2286 if(mInit) {
2287 release();
2288 }
2289 mInit = false;
2290 mActive = false;
2291 if (mJpegSessionId > 0) {
2292 omxJpegClose( );
2293 mJpegSessionId = 0;
2294 }
2295 ALOGV("%s: X", __func__);
2296
2297}
2298
2299//------------------------------------------------------------------
2300// Public Members
2301//------------------------------------------------------------------
2302status_t QCameraStream_Snapshot::init()
2303{
2304 status_t ret = NO_ERROR;
2305 mm_camera_op_mode_type_t op_mode;
2306
2307 ALOGV("%s: E", __func__);
2308 /* Check the state. If we have already started snapshot
2309 process just return*/
2310 if (getSnapshotState() != SNAPSHOT_STATE_UNINIT) {
2311 ret = isZSLMode() ? NO_ERROR : INVALID_OPERATION;
2312 ALOGE("%s: Trying to take picture while snapshot is in progress",
2313 __func__);
2314 goto end;
2315 }
2316 mInit = true;
2317
2318end:
2319 /*if (ret == NO_ERROR) {
2320 setSnapshotState(SNAPSHOT_STATE_INITIALIZED);
2321 }*/
2322 ALOGV("%s: X", __func__);
2323 return ret;
2324}
2325
2326status_t QCameraStream_Snapshot::start(void) {
2327 status_t ret = NO_ERROR;
2328
2329 ALOGV("%s: E", __func__);
2330
2331 Mutex::Autolock lock(mStopCallbackLock);
2332
2333 /* Keep track of number of snapshots to take - in case of
2334 multiple snapshot/burst mode */
2335
2336 if(mHalCamCtrl->isRawSnapshot()) {
2337 ALOGV("%s: Acquire Raw Snapshot Channel", __func__);
2338 ret = cam_ops_ch_acquire(mCameraId, MM_CAMERA_CH_RAW);
2339 if (NO_ERROR != ret) {
2340 ALOGE("%s: Failure Acquiring Raw Snapshot Channel error =%d\n",
2341 __func__, ret);
2342 ret = FAILED_TRANSACTION;
2343 goto end;
2344 }
2345 /* Snapshot channel is acquired */
2346 setSnapshotState(SNAPSHOT_STATE_CH_ACQUIRED);
2347 ALOGV("%s: Register buffer notification. My object: %x",
2348 __func__, (unsigned int) this);
2349 (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_RAW,
2350 snapshot_notify_cb,
2351 MM_CAMERA_REG_BUF_CB_INFINITE,
2352 0,
2353 this);
2354 /* Set the state to buffer notification completed */
2355 setSnapshotState(SNAPSHOT_STATE_BUF_NOTIF_REGD);
2356 }else{
2357 ALOGV("%s: Acquire Snapshot Channel", __func__);
2358 ret = cam_ops_ch_acquire(mCameraId, MM_CAMERA_CH_SNAPSHOT);
2359 if (NO_ERROR != ret) {
2360 ALOGE("%s: Failure Acquiring Snapshot Channel error =%d\n", __func__, ret);
2361 ret = FAILED_TRANSACTION;
2362 goto end;
2363 }
2364 /* Snapshot channel is acquired */
2365 setSnapshotState(SNAPSHOT_STATE_CH_ACQUIRED);
2366 ALOGV("%s: Register buffer notification. My object: %x",
2367 __func__, (unsigned int) this);
2368 (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_SNAPSHOT,
2369 snapshot_notify_cb,
2370 MM_CAMERA_REG_BUF_CB_INFINITE,
2371 0,
2372 this);
2373 /* Set the state to buffer notification completed */
2374 setSnapshotState(SNAPSHOT_STATE_BUF_NOTIF_REGD);
2375 }
2376
2377 if (isZSLMode()) {
2378 prepareHardware();
2379 ret = initZSLSnapshot();
2380 if(ret != NO_ERROR) {
2381 ALOGE("%s : Error while Initializing ZSL snapshot",__func__);
2382 goto end;
2383 }
2384 mHalCamCtrl->setExifTags();
2385 /* In case of ZSL, start will only start snapshot stream and
2386 continuously queue the frames in a queue. When user clicks
2387 shutter we'll call get buffer from the queue and pass it on */
2388 ret = startStreamZSL();
2389 goto end;
2390 }
2391
2392 if (isFullSizeLiveshot())
2393 ret = initFullLiveshot();
2394
2395 /* Check if it's a raw snapshot or JPEG*/
2396 if(mHalCamCtrl->isRawSnapshot()) {
2397 mSnapshotFormat = PICTURE_FORMAT_RAW;
2398 ret = initRawSnapshot(mNumOfSnapshot);
2399 }else{
2400 //JPEG
2401 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2402 if (mHdrInfo.hdr_on) {
2403 ret = initJPEGSnapshot(mHdrInfo.num_frame);
2404 } else {
2405 ret = initJPEGSnapshot(mNumOfSnapshot);
2406 }
2407 }
2408 if(ret != NO_ERROR) {
2409 ALOGE("%s : Error while Initializing snapshot",__func__);
2410 goto end;
2411 }
2412
2413 //Update Exiftag values.
2414 mHalCamCtrl->setExifTags();
2415
2416 if (mSnapshotFormat == PICTURE_FORMAT_RAW) {
2417 ret = takePictureRaw();
2418 goto end;
2419 }
2420 else{
2421 ret = takePictureJPEG();
2422 goto end;
2423 }
2424
2425end:
2426 if (ret == NO_ERROR) {
2427 setSnapshotState(SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD);
2428 mActive = true;
2429 } else {
2430 deInitBuffer();
2431 }
2432
2433 ALOGV("%s: X", __func__);
2434 return ret;
2435 }
2436
2437void QCameraStream_Snapshot::stopPolling(void)
2438{
2439 mm_camera_ops_type_t ops_type;
2440
2441 if (mSnapshotFormat == PICTURE_FORMAT_JPEG) {
2442 ops_type = isZSLMode() ? MM_CAMERA_OPS_ZSL : MM_CAMERA_OPS_SNAPSHOT;
2443 }else
2444 ops_type = MM_CAMERA_OPS_RAW;
2445
2446 if( NO_ERROR != cam_ops_action(mCameraId, false,
2447 ops_type, this)) {
2448 ALOGE("%s: Failure stopping snapshot", __func__);
2449 }
2450}
2451
2452void QCameraStream_Snapshot::stop(void)
2453{
2454 mm_camera_ops_type_t ops_type;
2455 status_t ret = NO_ERROR;
2456
2457 ALOGV("%s: E", __func__);
2458
2459 if(isLiveSnapshot() && mHalCamCtrl->mStateLiveshot) {
2460 if(getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) {
2461 ALOGV("Destroy Liveshot Jpeg Instance");
2462 omxJpegAbort();
2463 }
2464 mStopCallbackLock.lock();
2465 deInitBuffer();
2466 mHalCamCtrl->mStateLiveshot = false;
2467 mStopCallbackLock.unlock();
2468 return;
2469 }
2470
2471 if(!mActive) {
2472 ALOGV("%s: Not Active return now", __func__);
2473 return;
2474 }
2475 mActive = false;
2476 mStopCallbackLock.lock();
2477 if (getSnapshotState() != SNAPSHOT_STATE_UNINIT) {
2478 /* Stop polling for further frames */
2479 stopPolling();
2480
2481 if(getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) {
2482 mStopCallbackLock.unlock();
2483 ALOGV("Destroy Jpeg Instance");
2484 omxJpegAbort();
2485 mStopCallbackLock.lock();
2486 }
2487 /* Depending upon current state, we'll need to allocate-deallocate-deinit*/
2488 deInitBuffer();
2489 }
2490
2491 if(mSnapshotFormat == PICTURE_FORMAT_RAW) {
2492 ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_RAW);
2493 if(ret != MM_CAMERA_OK) {
2494 ALOGE("%s:Deinit RAW channel failed=%d\n", __func__, ret);
2495 }
2496 (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_RAW,
2497 NULL,
2498 (mm_camera_register_buf_cb_type_t)NULL,
2499 NULL,
2500 NULL);
2501 } else {
2502 ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_SNAPSHOT);
2503 if(ret != MM_CAMERA_OK) {
2504 ALOGE("%s:Deinit Snapshot channel failed=%d\n", __func__, ret);
2505 }
2506 (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_SNAPSHOT,
2507 NULL,
2508 (mm_camera_register_buf_cb_type_t)NULL,
2509 NULL,
2510 NULL);
2511 }
2512
2513 /* release is generally called in case of explicit call from
2514 upper-layer during disconnect. So we need to deinit everything
2515 whatever state we are in */
2516 ALOGV("Calling omxjpegjoin from release\n");
2517 omxJpegFinish();
2518#if 0
2519 omxJpegClose();
2520#endif
2521 mFullLiveshot = false;
2522 mStopCallbackLock.unlock();
2523 ALOGV("%s: X", __func__);
2524
2525}
2526
2527void QCameraStream_Snapshot::release()
2528{
2529 status_t ret = NO_ERROR;
2530 ALOGV("%s: E", __func__);
2531 //Mutex::Autolock l(&snapshotLock);
2532
2533 if(!mInit){
2534 ALOGE("%s : Stream not Initalized",__func__);
2535 return;
2536 }
2537
2538 if(mActive) {
2539 this->stop();
2540 mActive = false;
2541 }
2542
2543 /* release is generally called in case of explicit call from
2544 upper-layer during disconnect. So we need to deinit everything
2545 whatever state we are in */
2546
2547 //deinit();
2548 mInit = false;
2549 ALOGV("%s: X", __func__);
2550
2551}
2552
2553void QCameraStream_Snapshot::prepareHardware()
2554{
2555 ALOGV("%s: E", __func__);
2556
2557 /* Prepare snapshot*/
2558 cam_ops_action(mCameraId,
2559 true,
2560 MM_CAMERA_OPS_PREPARE_SNAPSHOT,
2561 this);
2562 ALOGV("%s: X", __func__);
2563}
2564
2565sp<IMemoryHeap> QCameraStream_Snapshot::getRawHeap() const
2566{
2567 return ((mDisplayHeap != NULL) ? mDisplayHeap->mHeap : NULL);
2568}
2569
2570QCameraStream*
2571QCameraStream_Snapshot::createInstance(int cameraId,
2572 camera_mode_t mode)
2573{
2574
2575 QCameraStream* pme = new QCameraStream_Snapshot(cameraId, mode);
2576
2577 return pme;
2578}
2579
2580void QCameraStream_Snapshot::deleteInstance(QCameraStream *p)
2581{
2582 if (p){
2583 p->release();
2584 delete p;
2585 p = NULL;
2586 }
2587}
2588
2589void QCameraStream_Snapshot::notifyWDenoiseEvent(cam_ctrl_status_t status, void * cookie)
2590{
2591 camera_notify_callback notifyCb;
2592 camera_data_callback dataCb, jpgDataCb;
2593 int rc = NO_ERROR;
2594 mm_camera_ch_data_buf_t *frame = (mm_camera_ch_data_buf_t *)cookie;
2595
2596 ALOGV("%s: WDN Done status (%d) received",__func__,status);
2597 Mutex::Autolock lock(mStopCallbackLock);
2598 if (frame == NULL) {
2599 ALOGE("%s: cookie is returned NULL", __func__);
2600 } else {
2601 #if 0
2602 // first unmapping the fds
2603 mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, frame->snapshot.main.idx, mCameraId,
2604 CAM_SOCK_MSG_TYPE_FD_UNMAPPING);
2605 mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, frame->snapshot.thumbnail.idx, mCameraId,
2606 CAM_SOCK_MSG_TYPE_FD_UNMAPPING);
2607 #endif
2608
2609 // then do JPEG encoding
2610 rc = encodeDisplayAndSave(frame, 0);
2611 }
2612
2613 // send upperlayer callback for raw image (data or notify, not both)
2614 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
2615 dataCb = mHalCamCtrl->mDataCb;
2616 } else {
2617 dataCb = NULL;
2618 }
2619 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){
2620 notifyCb = mHalCamCtrl->mNotifyCb;
2621 } else {
2622 notifyCb = NULL;
2623 }
2624 if(mHalCamCtrl->mDataCb &&
2625 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2626 /* get picture failed. Give jpeg callback with NULL data
2627 * to the application to restore to preview mode
2628 */
2629 jpgDataCb = mHalCamCtrl->mDataCb;
2630 } else {
2631 jpgDataCb = NULL;
2632 }
2633
2634 // launch next WDN if there is more in WDN Queue
2635 lauchNextWDenoiseFromQueue();
2636
2637 mStopCallbackLock.unlock();
2638
2639 if (rc != NO_ERROR)
2640 {
2641 ALOGE("%s: Error while encoding/displaying/saving image", __func__);
2642 if (frame) {
2643 cam_evt_buf_done(mCameraId, frame);
2644 }
2645
2646 if (dataCb) {
2647 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
2648 1, NULL, mHalCamCtrl->mCallbackCookie);
2649 }
2650 if (notifyCb) {
2651 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
2652 }
2653 if (jpgDataCb) {
2654 jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE,
2655 NULL, 0, NULL,
2656 mHalCamCtrl->mCallbackCookie);
2657 }
2658
2659 if (frame != NULL) {
2660 free(frame);
2661 }
2662 }
2663}
2664
2665void QCameraStream_Snapshot::lauchNextWDenoiseFromQueue()
2666{
2667 do {
2668 mm_camera_ch_data_buf_t *frame = NULL;
2669 if ( mWDNQueue.isEmpty() ||
2670 (NULL == (frame = (mm_camera_ch_data_buf_t *)mWDNQueue.dequeue())) ) {
2671 // set the flag back to false when no WDN going on
2672 mIsDoingWDN = false;
2673 break;
2674 }
2675
2676 if ( NO_ERROR != doWaveletDenoise(frame) ) {
2677 ALOGE("%s: Error while doing wavelet denoise", __func__);
2678 if (frame != NULL) {
2679 free(frame);
2680 }
2681 } else {
2682 // we sent out req for WDN, so we can break here
2683 ALOGV("%s: Send out req for doing wavelet denoise, return here", __func__);
2684 break;
2685 }
2686 } while (true);
2687}
2688
2689status_t QCameraStream_Snapshot::doWaveletDenoise(mm_camera_ch_data_buf_t* frame)
2690{
2691 status_t ret = NO_ERROR;
2692 cam_sock_packet_t packet;
2693 cam_ctrl_dimension_t dim;
2694
2695 ALOGV("%s: E", __func__);
2696
2697 #if 0
2698 // get dim on the fly
2699 memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
2700 ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
2701 if (NO_ERROR != ret) {
2702 ALOGE("%s: error - can't get dimension!", __func__);
2703 return FAILED_TRANSACTION;
2704 }
2705
2706 // send main frame mapping through domain socket
2707 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN,
2708 frame->snapshot.main.idx,
2709 frame->snapshot.main.frame->fd,
2710 dim.picture_frame_offset.frame_len, mCameraId,
2711 CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
2712 ALOGE("%s: sending main frame mapping buf msg Failed", __func__);
2713 ret = FAILED_TRANSACTION;
2714 goto end;
2715 }
2716
2717 // send thumbnail frame mapping through domain socket
2718 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL,
2719 frame->snapshot.thumbnail.idx,
2720 frame->snapshot.thumbnail.frame->fd,
2721 dim.display_frame_offset.frame_len, mCameraId,
2722 CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
2723 ALOGE("%s: sending thumbnail frame mapping buf msg Failed", __func__);
2724 ret = FAILED_TRANSACTION;
2725 goto end;
2726 }
2727
2728#endif
2729 // ask deamon to start wdn operation
2730 if (NO_ERROR != sendWDenoiseStartMsg(frame)) {
2731 ALOGE("%s: sending thumbnail frame mapping buf msg Failed", __func__);
2732 ret = FAILED_TRANSACTION;
2733 goto end;
2734 }
2735
2736end:
2737 ALOGV("%s: X", __func__);
2738 return ret;
2739}
2740
2741status_t QCameraStream_Snapshot::sendWDenoiseStartMsg(mm_camera_ch_data_buf_t * frame)
2742{
2743 cam_sock_packet_t packet;
2744 memset(&packet, 0, sizeof(cam_sock_packet_t));
2745 packet.msg_type = CAM_SOCK_MSG_TYPE_WDN_START;
2746 packet.payload.wdn_start.cookie = (unsigned long)frame;
2747 packet.payload.wdn_start.num_frames = MM_MAX_WDN_NUM;
2748 packet.payload.wdn_start.ext_mode[0] = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
2749 packet.payload.wdn_start.ext_mode[1] = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
2750 packet.payload.wdn_start.frame_idx[0] = frame->snapshot.main.idx;
2751 packet.payload.wdn_start.frame_idx[1] = frame->snapshot.thumbnail.idx;
2752 if ( cam_ops_sendmsg(mCameraId, &packet, sizeof(packet), 0) <= 0 ) {
2753 ALOGE("%s: sending start wavelet denoise msg failed", __func__);
2754 return FAILED_TRANSACTION;
2755 }
2756 return NO_ERROR;
2757}
2758
2759status_t QCameraStream_Snapshot::doHdrProcessing( )
2760{
2761 status_t rc = NO_ERROR;
2762 cam_sock_packet_t packet;
2763 int i;
2764 memset(&packet, 0, sizeof(cam_sock_packet_t));
2765 packet.msg_type = CAM_SOCK_MSG_TYPE_HDR_START;
2766 packet.payload.hdr_pkg.cookie = (unsigned long)this;
2767 packet.payload.hdr_pkg.num_hdr_frames = mHdrInfo.num_frame;
2768 ALOGV("%s num frames = %d ", __func__, mHdrInfo.num_frame);
2769 for (i = 0; i < mHdrInfo.num_frame; i++) {
2770 packet.payload.hdr_pkg.hdr_main_idx[i] =mHdrInfo.recvd_frame[i]->snapshot.main.idx;
2771 packet.payload.hdr_pkg.hdr_thm_idx[i] = mHdrInfo.recvd_frame[i]->snapshot.thumbnail.idx;
2772 packet.payload.hdr_pkg.exp[i] = mHdrInfo.exp[i];
2773 ALOGV("%s Adding buffer M %d T %d Exp %d into hdr pkg ", __func__,
2774 packet.payload.hdr_pkg.hdr_main_idx[i],
2775 packet.payload.hdr_pkg.hdr_thm_idx[i],
2776 packet.payload.hdr_pkg.exp[i]);
2777 }
2778 if (cam_ops_sendmsg(mCameraId, &packet, sizeof(packet), 0) <= 0) {
2779 ALOGE("%s: sending start HDR msg failed", __func__);
2780 rc= FAILED_TRANSACTION;
2781 }
2782 return rc;
2783}
2784
2785void QCameraStream_Snapshot::InitHdrInfoForSnapshot(bool Hdr_on, int number_frames, int *exp )
2786{
2787 mHdrInfo.hdr_on = Hdr_on;
2788 mHdrInfo.num_frame = number_frames;
2789 mHdrInfo.num_raw_received = 0;
2790
2791 if(number_frames) {
2792 memcpy(mHdrInfo.exp, exp, sizeof(int)*number_frames);
2793 }
2794 memset(&mHdrInfo.recvd_frame, 0,
2795 sizeof(mm_camera_ch_data_buf_t *)*MAX_HDR_EXP_FRAME_NUM);
2796}
2797
2798
2799void QCameraStream_Snapshot::notifyHdrEvent(cam_ctrl_status_t status, void * cookie)
2800{
2801 camera_notify_callback notifyCb;
2802 camera_data_callback dataCb, jpgDataCb;
2803 int rc[3];
2804 mm_camera_ch_data_buf_t *frame;
2805 int i;
2806
2807 ALOGV("%s: HDR Done status (%d) received",__func__,status);
2808 Mutex::Autolock lock(mStopCallbackLock);
2809 /* Regular frame */
2810 frame = mHdrInfo.recvd_frame[0];
2811 rc[0] = encodeDisplayAndSave(frame, 0);
2812 /* HDR frame */
2813 frame = mHdrInfo.recvd_frame[2];
2814 rc[2] = encodeDisplayAndSave(frame,0);
2815
2816 // send upperlayer callback for raw image (data or notify, not both)
2817 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
2818 dataCb = mHalCamCtrl->mDataCb;
2819 } else {
2820 dataCb = NULL;
2821 }
2822 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){
2823 notifyCb = mHalCamCtrl->mNotifyCb;
2824 } else {
2825 notifyCb = NULL;
2826 }
2827 if(mHalCamCtrl->mDataCb &&
2828 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2829 /* get picture failed. Give jpeg callback with NULL data
2830 * to the application to restore to preview mode
2831 */
2832 jpgDataCb = mHalCamCtrl->mDataCb;
2833 } else {
2834 jpgDataCb = NULL;
2835 }
2836
2837 mStopCallbackLock.unlock();
2838
2839 for (i =0; i<= 2; i++) {
2840 if(i==1)
2841 continue;
2842 if (rc[i] != NO_ERROR)
2843 {
2844 ALOGE("%s: Error while encoding/displaying/saving image", __func__);
2845 if (frame) {
2846 cam_evt_buf_done(mCameraId, mHdrInfo.recvd_frame[i]);
2847 }
2848
2849 if (dataCb) {
2850 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
2851 1, NULL, mHalCamCtrl->mCallbackCookie);
2852 }
2853 if (notifyCb) {
2854 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
2855 }
2856 if (jpgDataCb) {
2857 jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE,
2858 NULL, 0, NULL,
2859 mHalCamCtrl->mCallbackCookie);
2860 }
2861
2862 if ( mHdrInfo.recvd_frame[i] != NULL) {
2863 free( mHdrInfo.recvd_frame[i]);
2864 mHdrInfo.recvd_frame[i] = NULL;
2865 }
2866 }
2867 }
2868
2869 if (mHdrInfo.recvd_frame[1]) {
2870 cam_evt_buf_done(mCameraId, mHdrInfo.recvd_frame[1]);
2871 free( mHdrInfo.recvd_frame[1]);
2872 mHdrInfo.recvd_frame[1] = NULL;
2873 }
2874}
2875
2876}; // namespace android
2877