32 #include "cxutils.h" |
30 #include "cxutils.h" |
33 #include "cxecameradevicecontrol.h" |
31 #include "cxecameradevicecontrol.h" |
34 #include "cxecameradevice.h" |
32 #include "cxecameradevice.h" |
35 #include "cxesoundplayersymbian.h" |
33 #include "cxesoundplayersymbian.h" |
36 #include "cxestillimagesymbian.h" |
34 #include "cxestillimagesymbian.h" |
37 #include "cxeviewfindercontrol.h" |
|
38 #include "cxeviewfindercontrolsymbian.h" |
35 #include "cxeviewfindercontrolsymbian.h" |
|
36 #include "cxesnapshotcontrol.h" |
39 #include "cxesettingsmappersymbian.h" |
37 #include "cxesettingsmappersymbian.h" |
40 #include "cxestate.h" |
38 #include "cxestate.h" |
41 #include "cxesettings.h" |
39 #include "cxesettings.h" |
42 #include "cxeerrormappingsymbian.h" |
40 #include "cxeerrormappingsymbian.h" |
43 #include "cxeautofocuscontrol.h" |
41 #include "cxeautofocuscontrol.h" |
51 #include "cxestillcapturecontrolsymbianTraces.h" |
49 #include "cxestillcapturecontrolsymbianTraces.h" |
52 #endif |
50 #endif |
53 |
51 |
54 |
52 |
55 // constants |
53 // constants |
56 const int KMaintainAspectRatio = false; |
54 namespace |
57 const TInt64 KMinRequiredSpaceImage = 2000000; |
55 { |
58 |
56 const TInt64 KMinRequiredSpaceImage = 2000000; |
|
57 } |
59 |
58 |
60 /** |
59 /** |
61 * Constructor. |
60 * Constructor. |
62 */ |
61 */ |
63 CxeStillCaptureControlSymbian::CxeStillCaptureControlSymbian( |
62 CxeStillCaptureControlSymbian::CxeStillCaptureControlSymbian( |
64 CxeCameraDevice &cameraDevice, |
63 CxeCameraDevice &cameraDevice, |
65 CxeViewfinderControl &viewfinderControl, |
64 CxeViewfinderControl &viewfinderControl, |
|
65 CxeSnapshotControl &snapshotControl, |
66 CxeCameraDeviceControl &cameraDeviceControl, |
66 CxeCameraDeviceControl &cameraDeviceControl, |
67 CxeFilenameGenerator &nameGenerator, |
67 CxeFilenameGenerator &nameGenerator, |
68 CxeSensorEventHandler &sensorEventHandler, |
68 CxeSensorEventHandler &sensorEventHandler, |
69 CxeAutoFocusControl &autoFocusControl, |
69 CxeAutoFocusControl &autoFocusControl, |
70 CxeSettings &settings, |
70 CxeSettings &settings, |
72 CxeFileSaveThread &fileSaveThread, |
72 CxeFileSaveThread &fileSaveThread, |
73 CxeDiskMonitor &diskMonitor) |
73 CxeDiskMonitor &diskMonitor) |
74 : CxeStateMachine("CxeStillCaptureControlSymbian"), |
74 : CxeStateMachine("CxeStillCaptureControlSymbian"), |
75 mCameraDevice(cameraDevice), |
75 mCameraDevice(cameraDevice), |
76 mViewfinderControl(viewfinderControl), |
76 mViewfinderControl(viewfinderControl), |
|
77 mSnapshotControl(snapshotControl), |
77 mCameraDeviceControl(cameraDeviceControl), |
78 mCameraDeviceControl(cameraDeviceControl), |
78 mFilenameGenerator(nameGenerator), |
79 mFilenameGenerator(nameGenerator), |
79 mSensorEventHandler(sensorEventHandler), |
80 mSensorEventHandler(sensorEventHandler), |
80 mAutoFocusControl(autoFocusControl), |
81 mAutoFocusControl(autoFocusControl), |
81 mSettings(settings), |
82 mSettings(settings), |
114 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
115 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
115 |
116 |
116 // Connect ECam image buffer ready event |
117 // Connect ECam image buffer ready event |
117 connect(&mCameraDeviceControl, SIGNAL(imageBufferReady(MCameraBuffer*,int)), |
118 connect(&mCameraDeviceControl, SIGNAL(imageBufferReady(MCameraBuffer*,int)), |
118 this, SLOT(handleImageData(MCameraBuffer*,int))); |
119 this, SLOT(handleImageData(MCameraBuffer*,int))); |
119 // Connect signals for ECam events |
120 // connect snapshot ready signal |
120 connect(&mCameraDeviceControl, SIGNAL(cameraEvent(int,int)), |
121 connect(&mSnapshotControl, SIGNAL(snapshotReady(CxeError::Id, const QPixmap&)), |
121 this, SLOT(handleCameraEvent(int,int))); |
122 this, SLOT(handleSnapshotReady(CxeError::Id, const QPixmap&))); |
122 |
123 |
123 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_MID2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
124 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_MID2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
124 |
125 |
125 mImageDataQueue = new CxeImageDataQueueSymbian(); |
126 mImageDataQueue = new CxeImageDataQueueSymbian(); |
126 mAutoFocusSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::AutoFocus); |
127 mAutoFocusSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::AutoFocus); |
215 disconnect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged())); |
216 disconnect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged())); |
216 |
217 |
217 //stop viewfinder |
218 //stop viewfinder |
218 mViewfinderControl.stop(); |
219 mViewfinderControl.stop(); |
219 |
220 |
|
221 if (state() == Capturing) { |
|
222 mCameraDevice.camera()->CancelCaptureImage(); |
|
223 } |
|
224 |
220 // disable sensor event handler. |
225 // disable sensor event handler. |
221 mSensorEventHandler.deinit(); |
226 mSensorEventHandler.deinit(); |
222 |
227 |
223 if (mCameraDevice.cameraSnapshot()) { |
228 mSnapshotControl.stop(); |
224 mCameraDevice.cameraSnapshot()->StopSnapshot(); |
229 |
225 } |
|
226 |
|
227 if (state() == Capturing) { |
|
228 mCameraDevice.camera()->CancelCaptureImage(); |
|
229 } |
|
230 setState(Uninitialized); |
230 setState(Uninitialized); |
231 |
231 |
232 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_OUT, "msg: e_CX_STILL_CAPCONT_DEINIT 0" ); |
232 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_OUT, "msg: e_CX_STILL_CAPCONT_DEINIT 0" ); |
233 CX_DEBUG_EXIT_FUNCTION(); |
233 CX_DEBUG_EXIT_FUNCTION(); |
234 } |
234 } |
330 Returns symbian error code. |
330 Returns symbian error code. |
331 */ |
331 */ |
332 int CxeStillCaptureControlSymbian::prepareStillSnapshot() |
332 int CxeStillCaptureControlSymbian::prepareStillSnapshot() |
333 { |
333 { |
334 CX_DEBUG_ENTER_FUNCTION(); |
334 CX_DEBUG_ENTER_FUNCTION(); |
335 |
335 OstTrace0( camerax_performance, DUP4_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 1" ); |
336 CCamera::CCameraSnapshot *cameraSnapshot = mCameraDevice.cameraSnapshot(); |
336 |
337 CX_ASSERT_ALWAYS(cameraSnapshot); |
337 int status(KErrNone); |
338 |
338 try { |
339 int err = KErrNone; |
339 QSize snapshotSize = mSnapshotControl.calculateSnapshotSize( |
340 // Whether or not we have postcapture on, we need the snapshot for Thumbnail Manager. |
340 mViewfinderControl.deviceDisplayResolution(), |
341 if (cameraSnapshot) { |
341 QSize(mCurrentImageDetails.mWidth, mCurrentImageDetails.mHeight)); |
342 // Cancel active snapshot |
342 mSnapshotControl.start(snapshotSize); |
343 cameraSnapshot->StopSnapshot(); |
343 } catch (...) { |
344 |
344 status = KErrGeneral; |
345 // Prepare snapshot |
345 } |
346 CCamera::TFormat snapFormat = CCamera::EFormatFbsBitmapColor16MU; |
346 OstTrace0( camerax_performance, DUP5_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 0" ); |
347 OstTrace0( camerax_performance, DUP4_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 1" ); |
347 |
348 TRAP(err, cameraSnapshot->PrepareSnapshotL(snapFormat, |
348 CX_DEBUG_EXIT_FUNCTION(); |
349 getSnapshotSize(), |
349 return status; |
350 KMaintainAspectRatio)); |
|
351 OstTrace0( camerax_performance, DUP5_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 0" ); |
|
352 CX_DEBUG(("PrepareSnapshotL done, err=%d", err)); |
|
353 |
|
354 // Start snapshot if no errors encountered. |
|
355 if (err == KErrNone) { |
|
356 CX_DEBUG(("Start still snapshot")); |
|
357 cameraSnapshot->StartSnapshot(); |
|
358 } |
|
359 } else { |
|
360 // No snapshot interface available. Report error. |
|
361 // Assert above takes care of this, but keeping this as an option. |
|
362 err = KErrNotReady; |
|
363 } |
|
364 |
|
365 CX_DEBUG_EXIT_FUNCTION(); |
|
366 |
|
367 return err; |
|
368 } |
350 } |
369 |
351 |
370 |
352 |
371 /**! |
353 /**! |
372 imageInfo contains image qualities details |
354 imageInfo contains image qualities details |
398 |
380 |
399 CX_DEBUG_EXIT_FUNCTION(); |
381 CX_DEBUG_EXIT_FUNCTION(); |
400 return err; |
382 return err; |
401 } |
383 } |
402 |
384 |
403 |
|
404 /*! |
|
405 * Returns snapshot size. Snapshot size is calculated based on the |
|
406 * display resolution and current image aspect ratio. |
|
407 */ |
|
408 TSize CxeStillCaptureControlSymbian::getSnapshotSize() const |
|
409 { |
|
410 CX_DEBUG_ENTER_FUNCTION(); |
|
411 |
|
412 TSize snapshotSize; |
|
413 |
|
414 QSize deviceResolution = mViewfinderControl.deviceDisplayResolution(); |
|
415 QSize size = QSize(mCurrentImageDetails.mWidth, mCurrentImageDetails.mHeight); |
|
416 |
|
417 // scale according to aspect ratio. |
|
418 size.scale(deviceResolution.width(), deviceResolution.height(), Qt::KeepAspectRatio); |
|
419 CX_DEBUG(("Still Snapshot size, (%d,%d)", size.width(), size.height())); |
|
420 snapshotSize.SetSize(size.width(), deviceResolution.height()); |
|
421 |
|
422 CX_DEBUG_EXIT_FUNCTION(); |
|
423 |
|
424 return snapshotSize; |
|
425 } |
|
426 |
|
427 |
|
428 /** |
385 /** |
429 * Command to start image capture now. |
386 * Command to start image capture now. |
430 */ |
387 */ |
431 void CxeStillCaptureControlSymbian::capture() |
388 void CxeStillCaptureControlSymbian::capture() |
432 { |
389 { |
479 CX_DEBUG_EXIT_FUNCTION(); |
436 CX_DEBUG_EXIT_FUNCTION(); |
480 |
437 |
481 return imgFormat; |
438 return imgFormat; |
482 } |
439 } |
483 |
440 |
484 |
|
485 /** |
|
486 * Camera events. Only relevant one(s) are handled. |
|
487 */ |
|
488 void CxeStillCaptureControlSymbian::handleCameraEvent(int eventUid, int error) |
|
489 { |
|
490 CX_DEBUG_ENTER_FUNCTION(); |
|
491 |
|
492 if (eventUid == KUidECamEventSnapshotUidValue && |
|
493 mCameraDeviceControl.mode() == Cxe::ImageMode) { |
|
494 handleSnapshotEvent(CxeErrorHandlingSymbian::map(error)); |
|
495 } |
|
496 |
|
497 CX_DEBUG_EXIT_FUNCTION(); |
|
498 } |
|
499 |
|
500 /** |
441 /** |
501 * Snapshot ready notification. Ask the snapshot from snapshot interface. |
442 * Snapshot ready notification. Ask the snapshot from snapshot interface. |
502 * NB: Typically snapshot arrives before image data but can be in reverse |
443 * NB: Typically snapshot arrives before image data but can be in reverse |
503 * order as well. |
444 * order as well. |
504 */ |
445 */ |
505 void CxeStillCaptureControlSymbian::handleSnapshotEvent(CxeError::Id error) |
446 void CxeStillCaptureControlSymbian::handleSnapshotReady(CxeError::Id status, const QPixmap& snapshot) |
506 { |
447 { |
507 CX_DEBUG_ENTER_FUNCTION(); |
448 CX_DEBUG_ENTER_FUNCTION(); |
508 |
449 if (mCameraDeviceControl.mode() == Cxe::ImageMode) { |
509 if (state() == CxeStillCaptureControl::Uninitialized) { |
450 |
510 // we ignore this event, when we are not active |
451 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 1" ); |
511 return; |
452 |
512 } |
453 // Get image container for current snapshot index. |
513 |
454 // Remember to increment counter. |
514 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 1" ); |
455 CxeStillImageSymbian* stillImage = getImageForIndex(mNextSnapshotIndex++); |
515 |
456 if (status == CxeError::None) { |
516 // Get image container for current snapshot index. |
457 stillImage->setSnapshot(snapshot); |
517 // Remember to increment counter. |
458 } |
518 CxeStillImageSymbian* stillImage = getImageForIndex(mNextSnapshotIndex++); |
459 |
519 |
460 // Emit snapshotReady signal in all cases (error or not) |
520 if (error == CxeError::None) { |
461 emit snapshotReady(status, snapshot, stillImage->id()); |
521 try { |
462 |
522 stillImage->setSnapshot(extractSnapshot()); |
463 // When the snapshot ready event is handled, prepare new filename. |
523 } catch (const std::exception& ex) { |
464 if (stillImage->filename().isEmpty()) { |
524 error = CxeError::General; |
465 // Error ignored at this point, try again when image data arrives. |
525 } |
466 prepareFilename(stillImage); |
526 } |
467 } |
527 |
468 |
528 // Emit snapshotReady signal in all cases (error or not) |
469 OstTrace0( camerax_performance, DUP1_CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 0" ); |
529 emit snapshotReady(error, stillImage->snapshot(), stillImage->id()); |
470 } |
530 |
471 |
531 // When the snapshot ready event is handled, prepare new filename. |
472 CX_DEBUG_EXIT_FUNCTION(); |
532 if (stillImage->filename().isEmpty()) { |
|
533 // Error ignored at this point, try again when image data arrives. |
|
534 prepareFilename(stillImage); |
|
535 } |
|
536 |
|
537 OstTrace0( camerax_performance, DUP1_CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 0" ); |
|
538 CX_DEBUG_EXIT_FUNCTION(); |
|
539 } |
|
540 |
|
541 /** |
|
542 * Gets QPixmap snapshot from ECAM buffer, if available. |
|
543 * @param buffer ECAM buffer containing the snapshot data. Will be released when this |
|
544 * method returns, even on exception. |
|
545 */ |
|
546 QPixmap CxeStillCaptureControlSymbian::extractSnapshot() |
|
547 { |
|
548 CX_DEBUG_ENTER_FUNCTION(); |
|
549 QPixmap pixmap; |
|
550 |
|
551 if (mCameraDevice.cameraSnapshot()) { |
|
552 |
|
553 QT_TRAP_THROWING({ |
|
554 RArray<TInt> frameIndex; |
|
555 CleanupClosePushL(frameIndex); |
|
556 |
|
557 MCameraBuffer &buffer(mCameraDevice.cameraSnapshot()->SnapshotDataL(frameIndex)); |
|
558 |
|
559 // Make sure buffer is released on leave / exception |
|
560 CxeCameraBufferCleanup cleaner(&buffer); |
|
561 TInt firstImageIndex(frameIndex.Find(0)); |
|
562 CFbsBitmap &snapshot(buffer.BitmapL(firstImageIndex)); |
|
563 |
|
564 CleanupStack::PopAndDestroy(); // frameIndex |
|
565 |
|
566 TSize size = snapshot.SizeInPixels(); |
|
567 TInt sizeInWords = size.iHeight * CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU) / sizeof(TUint32); |
|
568 CX_DEBUG(("size %d x %d, sizeInWords = %d", size.iWidth, size.iHeight, sizeInWords )); |
|
569 |
|
570 TUint32* pixelData = new (ELeave) TUint32[ sizeInWords ]; |
|
571 // Convert to QImage |
|
572 snapshot.LockHeap(); |
|
573 TUint32* dataPtr = snapshot.DataAddress(); |
|
574 memcpy(pixelData, dataPtr, sizeof(TUint32)*sizeInWords); |
|
575 snapshot.UnlockHeap(); |
|
576 |
|
577 CX_DEBUG(("Creating QImage")); |
|
578 QImage *snapImage = new QImage((uchar*)pixelData, size.iWidth, size.iHeight, |
|
579 CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU), |
|
580 QImage::Format_RGB32); |
|
581 |
|
582 pixmap = QPixmap::fromImage(*snapImage); |
|
583 delete [] pixelData; |
|
584 delete snapImage; |
|
585 }); |
|
586 } |
|
587 |
|
588 CX_DEBUG_EXIT_FUNCTION(); |
|
589 return pixmap; |
|
590 } |
473 } |
591 |
474 |
592 /** |
475 /** |
593 * handleImageData: Image data received from ECam |
476 * handleImageData: Image data received from ECam |
594 */ |
477 */ |