6e87e6f9bf05839833b43fff0fd92f223a489282
[framework/web/wrt-plugins-common.git] / src / modules / tizen / DEPRACATED / Camera / Camera.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd 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  * @author      Karol Majewski (k.majewski@samsung.com)
18  * @version     0.1
19  * @brief
20  */
21
22 #include "Camera.h"
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <dpl/assert.h>
27 #include <dpl/shared_ptr.h>
28 #include "mm_camcorder.h"
29 #include <commons/Exception.h>
30 #include "AttributeInfo.h"
31
32 namespace {
33 const unsigned int DEFAULT_CAPTURE_WIDTH = 640;
34 const unsigned int DEFAULT_CAPTURE_HEIGHT = 480;
35 } // namespace
36
37 namespace WrtPlugins {
38 namespace Platform {
39 namespace Camera {
40 //.............................................................................
41 Camera::Camera() :
42     m_camcorderHandle(NULL)
43 {
44     m_camcorderPreset.videodev_type = MM_VIDEO_DEVICE_NONE,
45     m_camcorderPreset.reserved[0] = 0;
46     m_camcorderPreset.reserved[1] = 0;
47     m_camcorderPreset.reserved[2] = 0;
48     m_camcorderPreset.reserved[3] = 0;
49
50     pthread_mutex_init(&m_stateMutex, NULL);
51     m_state = IDLE;
52     DPL::Event::ControllerEventHandler<JobDoneEvent >::Touch();
53 }
54 //.............................................................................
55 void Camera::init(MMCamPreset preset)
56 {
57     LogDebug("Creating camcorder");
58     memcpy(&m_camcorderPreset, &preset, sizeof(m_camcorderPreset));
59     int err = mm_camcorder_create(&m_camcorderHandle, &m_camcorderPreset);
60
61     logCamcorderState();
62     if (err != MM_ERROR_NONE) {
63         LogError("Creating camcorder's failed !!! " << err);
64         Throw(Commons::UnknownException);
65     }
66 }
67 //.............................................................................
68 Camera::~Camera()
69 {
70     LogDebug(__FUNCTION__);
71
72     DPL::Event::ControllerEventHandler<JobDoneEvent >::SwitchToThread(NULL);
73
74     m_state = PROCESSING;
75     pthread_mutex_lock(&m_stateMutex);
76     {
77         m_state = PROCESSING;
78
79         mm_camcorder_set_message_callback(m_camcorderHandle, NULL, NULL);
80         mm_camcorder_capture_stop(m_camcorderHandle);
81         mm_camcorder_stop(m_camcorderHandle);
82     }
83     pthread_mutex_unlock(&m_stateMutex);
84
85     unRealizeCamcoder();
86     mm_camcorder_destroy(m_camcorderHandle);
87     pthread_mutex_destroy(&m_stateMutex);
88 }
89 //.............................................................................
90 void Camera::tryIsInvalidParameterError(int errorCode)
91 {
92     switch (errorCode) {
93     case MM_ERROR_COMMON_INVALID_ATTRTYPE:
94     case MM_ERROR_COMMON_INVALID_PERMISSION:
95     case MM_ERROR_COMMON_OUT_OF_ARRAY:
96     case MM_ERROR_COMMON_OUT_OF_RANGE:
97     case MM_ERROR_COMMON_ATTR_NOT_EXIST:
98         LogDebug("Invalid Parameter error");
99         Throw(Commons::InvalidArgumentException);
100     }
101     LogDebug("it's not Invalid Parameter error");
102 }
103 //.............................................................................
104 int Camera::lockCameraMutex(Camera *camera)
105 {
106     LogDebug("Trying to lock camera mutex");
107     pthread_mutex_lock(&(camera->m_stateMutex));
108     LogDebug(".. - locked");
109
110     if (Camera::PROCESSING == camera->m_state) {
111         LogWarning(
112             "Camera object is being killed or performing some locked operations, but it's receiving the message ");
113         pthread_mutex_unlock(&(camera->m_stateMutex));
114         return -1;
115     }
116
117     if (Camera::IDLE == camera->m_state) {
118         LogWarning(
119             "Message has been received, but no one is listening any more");
120         pthread_mutex_unlock(&(camera->m_stateMutex));
121         return -1;
122     }
123
124     return 0;
125 }
126 //.............................................................................
127 void Camera::unlockCameraMutex(Camera *camera)
128 {
129     LogDebug("Unlocking camera mutex");
130     pthread_mutex_unlock(&(camera->m_stateMutex));
131 }
132 //.............................................................................
133 /* Body of the callback function msg_callback */
134 int Camera::camcorderMessageCallback(int msg_type,
135         void *msg_param,
136         void *user_param)
137 {
138     LogDebug(__FUNCTION__);
139     int error;
140
141     MMMessageParamType *m = static_cast<MMMessageParamType *>(msg_param);
142     Platform::Camera::Camera *igcamera =
143         static_cast<Platform::Camera::Camera *>(user_param);
144
145     switch (msg_type) {
146     case MM_MESSAGE_WARNING:
147         LogWarning("*MSG* Warning occured  " << std::hex << m->code);
148         break;
149     //lack of break is intended; treating all these messages as error.
150     case MM_MESSAGE_CAMCORDER_MAX_SIZE:                /**< Maximum size, camcorder waits for user's order (cam_commit/cancel).*/
151     case MM_MESSAGE_CAMCORDER_NO_FREE_SPACE:            /**< No free space, camcorder waits for user's order (cam_commit/cancel).*/
152     case MM_MESSAGE_CAMCORDER_TIME_LIMIT:            /**< Time limit, camcorder waits for user's order (cam_commit/cancel)*/
153         LogError("Unexpected camcorder message: " << std::hex << msg_type);
154         LogInfo("Force camcorder to commit caputured data");
155         mm_camcorder_stop(igcamera->m_camcorderHandle);
156         mm_camcorder_unrealize(igcamera->m_camcorderHandle);
157         igcamera->DPL::Event::ControllerEventHandler<JobDoneEvent>::PostEvent(
158             JobDoneEvent());
159         break;
160
161     case MM_MESSAGE_CAMCORDER_ERROR:
162         if (Camera::lockCameraMutex(igcamera) < 0) {
163             return -1;
164         }
165         LogError("*MSG* Error's occured.  " << std::hex << m->code);
166
167         switch (igcamera->getState()) {
168         case Camera::CAPTURING_IMAGE:
169             igcamera->m_eventTakePicture->setExceptionCode(
170                 Commons::ExceptionCodes::UnknownException);
171             break;
172         case Camera::CAPTURING_VIDEO:
173             igcamera->m_eventBeginRecording->setExceptionCode(
174                 Commons::ExceptionCodes::UnknownException);
175             break;
176         default:
177             break;
178         }
179         mm_camcorder_stop(igcamera->m_camcorderHandle);
180         mm_camcorder_unrealize(igcamera->m_camcorderHandle);
181         mm_camcorder_set_message_callback(igcamera->m_camcorderHandle,
182                                           NULL,
183                                           NULL);
184         igcamera->DPL::Event::ControllerEventHandler<JobDoneEvent>::PostEvent(
185             JobDoneEvent());
186         Camera::unlockCameraMutex(igcamera);
187         break;
188
189     case MM_MESSAGE_CAMCORDER_STATE_CHANGED:
190         if (Camera::lockCameraMutex(igcamera) < 0) {
191             return -1;
192         }
193
194         LogDebug(
195             "*MSG* State changed " << std::hex << m->state.previous <<
196             "->" << std::hex << m->state.current);
197         //2->3
198         if (MM_CAMCORDER_STATE_PREPARE == m->state.current &&
199             MM_CAMCORDER_STATE_READY == m->state.previous) {
200             LogDebug("MM_CAMCORDER_STATE_READY->MM_CAMCORDER_STATE_PREPARE ");
201             switch (igcamera->getState()) {
202             case Camera::CAPTURING_IMAGE:
203                 error = mm_camcorder_capture_start(igcamera->m_camcorderHandle);
204                 if (error != MM_ERROR_NONE) {
205                     LogError(
206                         "m_camcorderHandle capture start failed " <<
207                         std::hex << error);
208                     igcamera->m_eventTakePicture->setExceptionCode(
209                         Commons::ExceptionCodes::UnknownException);
210                     igcamera->DPL::Event::ControllerEventHandler<JobDoneEvent>::
211                         PostEvent(JobDoneEvent());
212                     mm_camcorder_stop(igcamera->m_camcorderHandle);
213                     mm_camcorder_unrealize(igcamera->m_camcorderHandle);
214                 }
215                 break;
216             case Camera::CAPTURING_VIDEO:
217                 LogDebug("CAPTURING_VIDEO " << igcamera->m_camcorderHandle);
218                 error = mm_camcorder_record(igcamera->m_camcorderHandle);
219                 if (error != MM_ERROR_NONE) {
220                     LogError(
221                         "m_camcorderHandle record start failed " <<
222                         std::hex << error);
223                     igcamera->m_eventBeginRecording->setExceptionCode(
224                         Commons::ExceptionCodes::UnknownException);
225                     igcamera->DPL::Event::ControllerEventHandler<JobDoneEvent>::
226                         PostEvent(JobDoneEvent());
227                     mm_camcorder_stop(igcamera->m_camcorderHandle);
228                     mm_camcorder_unrealize(igcamera->m_camcorderHandle);
229                 }
230                 break;
231             default:
232                 break;
233             }
234             LogDebug("Done.");
235         }
236         //3->4
237         if (MM_CAMCORDER_STATE_CAPTURING == m->state.previous &&
238             MM_CAMCORDER_STATE_PREPARE == m->state.current) {
239             /* Capture Stop */
240             LogDebug(
241                 "MM_CAMCORDER_STATE_CAPTURING->MM_CAMCORDER_STATE_PREPARE => stopping capture");
242             error = mm_camcorder_capture_stop(igcamera->m_camcorderHandle);
243             if (error != MM_ERROR_NONE) {
244                 LogError(
245                     "m_camcorderHandle capture stopfailed " << std::hex <<
246                     error);
247             }
248             igcamera->logCamcorderState();
249             mm_camcorder_stop(igcamera->m_camcorderHandle);
250             mm_camcorder_unrealize(igcamera->m_camcorderHandle);
251         }
252
253         if (MM_CAMCORDER_STATE_RECORDING == m->state.previous &&
254             MM_CAMCORDER_STATE_PREPARE == m->state.current) {
255             /* Record Stop */
256             LogDebug(
257                 "MM_CAMCORDER_STATE_CAPTURING->MM_CAMCORDER_STATE_PREPARE => stopping recording");
258
259             /// ...
260             mm_camcorder_stop(igcamera->m_camcorderHandle);
261             mm_camcorder_unrealize(igcamera->m_camcorderHandle);
262         }
263
264         Camera::unlockCameraMutex(igcamera);
265         break;
266     case MM_MESSAGE_CAMCORDER_CAPTURED:
267         if (Camera::lockCameraMutex(igcamera) < 0) {
268             return -1;
269         }
270         LogDebug("*MSG* Captured. !!!");
271         if (Camera::CAPTURING_VIDEO == igcamera->getState() ||
272             Camera::CAPTURING_IMAGE == igcamera->getState()) {
273             mm_camcorder_capture_stop(igcamera->m_camcorderHandle);
274             mm_camcorder_stop(igcamera->m_camcorderHandle);
275             mm_camcorder_unrealize(igcamera->m_camcorderHandle);
276             igcamera->DPL::Event::ControllerEventHandler<JobDoneEvent>::PostEvent(
277                 JobDoneEvent());
278         }
279         Camera::unlockCameraMutex(igcamera);
280         break;
281     default:
282         LogDebug(
283             "*MSG* Message received. MMMessageID = " << std::hex <<
284             msg_type);
285         break;
286     }
287     return true;
288 }
289 //.............................................................................
290 void Camera::OnEventReceived(const JobDoneEvent &event)
291 {
292     //if we received this event it means that we are (should be) in PROCESSING state and we need to send back the answer
293     //we need to check which one
294
295     LogDebug("JobDoneEvent received");
296     if (-1 == Camera::lockCameraMutex(this)) {
297         return;
298     }
299     if (m_eventTakePicture) {
300         Platform::EventRequestReceiver< Api::Camera::EventTakePicture >::
301             ManualAnswer(m_eventTakePicture);
302         m_eventTakePicture.Reset();
303     } else if (m_eventBeginRecording) {
304         Platform::EventRequestReceiver< Api::Camera::EventBeginRecording >::
305             ManualAnswer(m_eventBeginRecording);
306         m_eventBeginRecording.Reset();
307     } else if (NULL != m_eventEndRecording.Get()) {
308         Platform::EventRequestReceiver< Api::Camera::EventEndRecording>::
309             ManualAnswer(m_eventEndRecording);
310         m_eventEndRecording.Reset();
311     } else if (m_eventRequestLiveVideo) {
312         Platform::EventRequestReceiver< Api::Camera::EventRequestLiveVideo>::
313             ManualAnswer(m_eventRequestLiveVideo);
314         m_eventRequestLiveVideo.Reset();
315     } else {
316         LogError("This part should not be reached");
317         assert(0);
318     }
319     setState(Camera::IDLE);
320     Camera::unlockCameraMutex(this);
321     LogDebug("camera is idle now..");
322 }
323 //.............................................................................
324 void Camera::OnRequestReceived(
325         const Api::Camera::EventTakePictureSharedPtr & event)
326 {
327     int err;
328     LogDebug(__FUNCTION__);
329
330     pthread_mutex_lock(&m_stateMutex);
331     //check is camera idle and can take a picture and camera object is not currently being destructed
332     if (Camera::IDLE != m_state) {
333         pthread_mutex_unlock(&m_stateMutex);
334         event->setExceptionCode(Commons::ExceptionCodes::AlreadyInUseException);
335         return;
336     }
337
338     try
339     {
340         m_state = Camera::CAPTURING_IMAGE;
341         reInitializeCamcorderForPicture(event->getCaptureOptionsRef());
342     }
343     catch (const Commons::Exception &exc)
344     {
345         m_state = Camera::IDLE;
346         pthread_mutex_unlock(&m_stateMutex);
347         LogDebug("error's occured - invoking error callback");
348         event->setExceptionCode(exc.getCode());
349         return;
350     }
351
352     //from now on we will have to call answer manually
353     event->switchToManualAnswer();
354     m_eventTakePicture = event;
355     LogDebug("setting message callback");
356     mm_camcorder_set_message_callback(m_camcorderHandle,
357                                       Camera::camcorderMessageCallback,
358                                       this);
359
360     /* start receiving the input video stream */
361     LogDebug("mm_camcorder_start");
362     err = mm_camcorder_start(m_camcorderHandle);
363     if (err != MM_ERROR_NONE) {
364         LogError("starting camcorder failed " << std::hex << err);
365         mm_camcorder_set_message_callback(m_camcorderHandle, NULL, NULL);
366         m_state = Camera::IDLE;
367         pthread_mutex_unlock(&m_stateMutex);
368         event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
369         Platform::EventRequestReceiver< Api::Camera::EventTakePicture >::
370             ManualAnswer(event);
371         return;
372     }
373     pthread_mutex_unlock(&m_stateMutex);
374     LogDebug("leaving");
375 }
376 //.............................................................................
377 void Camera::OnRequestReceived(
378         const Api::Camera::EventBeginRecordingSharedPtr & event)
379 {
380     int err;
381     LogDebug(__FUNCTION__);
382
383     pthread_mutex_lock(&m_stateMutex);
384     //check is camera idle and can record
385     if (Camera::IDLE != m_state) {
386         pthread_mutex_unlock(&m_stateMutex);
387         event->setExceptionCode(Commons::ExceptionCodes::AlreadyInUseException);
388         return;
389     }
390
391     try
392     {
393         m_state = Camera::CAPTURING_VIDEO;
394         reInitializeCamcorderForVideo(event->getCaptureOptionsRef());
395     }
396     catch (const Commons::Exception &exc)
397     {
398         m_state = Camera::IDLE;
399         pthread_mutex_unlock(&m_stateMutex);
400         LogDebug("error's occured - invoking error callback");
401         event->setExceptionCode(exc.getCode());
402         return;
403     }
404
405     //from now on we will have to call answer manually
406     event->switchToManualAnswer();
407     m_eventBeginRecording = event;
408     LogDebug("setting message callback");
409     mm_camcorder_set_message_callback(m_camcorderHandle,
410                                       Camera::camcorderMessageCallback,
411                                       this);
412
413     /* start receiving the input video stream */
414     LogDebug("mm_camcorder_start");
415     err = mm_camcorder_start(m_camcorderHandle);
416     if (err != MM_ERROR_NONE) {
417         LogError("starting camcorder failed " << std::hex << err);
418         mm_camcorder_set_message_callback(m_camcorderHandle, NULL, NULL);
419         m_state = Camera::IDLE;
420         pthread_mutex_unlock(&m_stateMutex);
421         event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
422         Platform::EventRequestReceiver<Api::Camera::EventBeginRecording>::
423             ManualAnswer(event);
424         return;
425     }
426     pthread_mutex_unlock(&m_stateMutex);
427 }
428 //.............................................................................
429 void Camera::OnRequestReceived(
430         const Api::Camera::EventEndRecordingSharedPtr & event)
431 {
432     LogDebug("end request");
433     pthread_mutex_lock(&m_stateMutex);
434     if (m_state == Camera::CAPTURING_VIDEO) {
435         logCamcorderState();
436         int error = mm_camcorder_commit(m_camcorderHandle);
437         switch (error) {
438         case MM_ERROR_NONE:
439             break;
440         case MM_ERROR_CAMCORDER_INVALID_STATE:
441             LogError("MM_ERROR_CAMCORDER_INVALID_STATE's occured");
442             break;
443         default:
444             //capturing video is in progress but we have an error
445             LogError(
446                 "mm_camcorder_commit error occured " << std::hex <<
447                 error << " stopping it");
448             mm_camcorder_cancel(m_camcorderHandle);
449             mm_camcorder_stop(m_camcorderHandle);
450             mm_camcorder_unrealize(m_camcorderHandle);
451             event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
452             m_state = Camera::IDLE;
453             break;
454         }
455     } else {
456         LogDebug("stopVideo has been called but no recording is in progress");
457         event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
458     }
459     pthread_mutex_unlock(&m_stateMutex);
460 }
461 //.............................................................................
462 void Camera::OnRequestReceived(
463         const DPL::SharedPtr<Api::Camera::EventRequestLiveVideo> & event)
464 {
465     ///TODO Not supported
466     event->setExceptionCode(Commons::ExceptionCodes::UnsupportedException);
467 }
468 //.............................................................................
469 void Camera::logCamcorderState()
470 {
471     MMCamcorderStateType state;
472     int retValue = mm_camcorder_get_state(m_camcorderHandle, &state);
473     if (MM_ERROR_NONE == retValue) {
474         LogDebug("camcorder's state: " << std::hex << state);
475     } else {
476         LogDebug("getting camcorder's state's failed: " << std::hex << retValue);
477     }
478 }
479 //.............................................................................
480 std::string Camera::getDescription() const
481 {
482     std::string desc;
483     char *err_attr_name = NULL;
484     char *description = NULL;
485     int size = 0;
486
487     if (mm_camcorder_get_attributes(m_camcorderHandle, &err_attr_name,
488                                     "camera-device-name", &description, &size,
489                                     NULL) < 0) {
490         LogError("GetDescription problem ");
491         if (err_attr_name) {
492             LogError("mm_camcorder_get_attributes " << err_attr_name);
493         }
494         std::ostringstream oss;
495         oss << m_camcorderPreset.videodev_type;
496         desc.assign(oss.str());
497     } else {
498         desc.assign(description);
499     }
500     if (err_attr_name) {
501         LogDebug("free err_attr_name");
502         free(err_attr_name);
503     }
504     LogDebug("desc" << desc);
505     return desc;
506 }
507 //.............................................................................
508 int Camera::camcorderVideoCaptureCallback(MMCamcorderCaptureDataType *src,
509         MMCamcorderCaptureDataType *thumb,
510         void *data)
511 {
512     LogDebug(__FUNCTION__);
513     Platform::Camera::Camera *camera =
514         static_cast<Platform::Camera::Camera *>(data);
515
516     if (Camera::CAPTURING_IMAGE != camera->getState()) {
517         return 1;
518     }
519
520     assert(src->format == MM_PIXEL_FORMAT_ENCODED);
521
522     printf(
523         "MM_PIXEL_FORMAT_ENCODED src->data=%p src->length=%d, src->width=%d, src->heigtht=%d \n\n",
524         src->data,
525         src->length,
526         src->width,
527         src->height);
528     std::string fileName =
529         camera->m_eventTakePicture->getCaptureOptionsRef()->getFileName();
530
531     FILE* fp = fopen(fileName.c_str(), "w+");
532     if (fp == NULL) {
533         LogError("file opening error!!");
534         return -1;
535     } else {
536         LogDebug("open success");
537         if (fwrite(src->data, src->length, 1, fp) != 1) {
538             LogError("file writing error!!");
539             fclose(fp);
540             return -1;
541         }
542         LogDebug("success");
543     }
544     fclose(fp);
545     return 0;
546 }
547 //.............................................................................
548 void Camera::setCaptureOptions(
549         const Api::Camera::ICaptureOptionsPtr &captureOptions)
550 {
551     LogDebug("enter");
552
553     if (NULL == captureOptions) {
554         return;
555     }
556     bool ret = realizeCamcoder();
557     if (ret == FALSE) {
558         LogError("Realize camcoreder failed");
559         return;
560     }
561
562     char *err_attr_name = NULL;
563     int retValue = 0;
564
565     if (captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
566                                              SETTED_WIDTH)) {
567         LogDebug("setting width");
568         short width = captureOptions->getWidth();
569         retValue = mm_camcorder_set_attributes(m_camcorderHandle,
570                                                &err_attr_name,
571                                                MMCAM_CAPTURE_WIDTH,
572                                                width,
573                                                NULL);
574         if (retValue < 0) {
575             free(err_attr_name);
576             LogDebug("couldn't set width attribute " << std::hex << retValue);
577             Throw(Commons::InvalidArgumentException);
578         }
579     }
580
581     if (captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
582                                              SETTED_HEIGHT)) {
583         LogDebug("setting height");
584         short height = captureOptions->getHeight();
585         retValue = mm_camcorder_set_attributes(m_camcorderHandle,
586                                                &err_attr_name,
587                                                MMCAM_CAPTURE_HEIGHT,
588                                                height,
589                                                NULL);
590         if (retValue < 0) {
591             free(err_attr_name);
592             LogDebug("couldn't set height attribute " << std::hex << retValue);
593             Throw(Commons::InvalidArgumentException);
594         }
595     }
596
597     if (captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
598                                              SETTED_FRAME_RATE)) {
599         LogDebug("setting frame rate");
600         short frameRate = captureOptions->getFrameRate();
601         retValue = mm_camcorder_set_attributes(m_camcorderHandle,
602                                                &err_attr_name,
603                                                MMCAM_CAMERA_FPS,
604                                                frameRate,
605                                                NULL);
606         if (retValue < 0) {
607             free(err_attr_name);
608             LogDebug(
609                 "couldn't set frameRate attribute " << std::hex <<
610                 retValue);
611             Throw(Commons::InvalidArgumentException);
612         }
613     }
614
615     if (captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
616                                              SETTED_MAX_BITRATE)) {
617         unsigned long bitrate = captureOptions->getMaximumBitrate();
618         LogDebug("setting max bitrate: " << bitrate);
619         retValue = mm_camcorder_set_attributes(m_camcorderHandle,
620                                                &err_attr_name,
621                                                MMCAM_AUDIO_ENCODER_BITRATE,
622                                                bitrate,
623                                                MMCAM_VIDEO_ENCODER_BITRATE,
624                                                bitrate,
625                                                NULL);
626         if (retValue < 0) {
627             free(err_attr_name);
628             LogDebug("couldn't set bitrate attribute " << std::hex << retValue);
629             Throw(Commons::InvalidArgumentException);
630         }
631     }
632
633     if (captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
634                                              SETTED_IMAGE_RESOLUTION)) {
635         LogDebug("setting image resolution");
636         Api::Camera::ICaptureOptions::ImageResolution imageResolution =
637             captureOptions->getImageResolution();
638
639         //getting possible range of this argument
640         MMCamAttrsInfo info;
641         retValue = mm_camcorder_get_attribute_info(m_camcorderHandle,
642                                                    MMCAM_IMAGE_ENCODER_QUALITY,
643                                                    &info);
644         if (retValue < 0) {
645             free(err_attr_name);
646             LogDebug(
647                 "couldn't get MMCAM_IMAGE_ENCODER_QUALITY resolution attribute info"
648                 << std::hex << retValue);
649             Throw(Commons::InvalidArgumentException);
650         }
651
652         assert(MM_CAM_ATTRS_VALID_TYPE_INT_RANGE == info.validity_type);
653         int quality = 0;
654         switch (imageResolution) {
655         case Api::Camera::ICaptureOptions::IMAGE_RESOLUTION_LOW:
656             quality = info.int_range.min;
657             break;
658         case Api::Camera::ICaptureOptions::IMAGE_RESOLUTION_HIGH:
659             quality = info.int_range.max;
660             break;
661         case Api::Camera::ICaptureOptions::IMAGE_RESOLUTION_DEFAULT:
662             quality = info.int_range.def;
663             break;
664         default:
665             break;
666         }
667         retValue = mm_camcorder_set_attributes(m_camcorderHandle,
668                                                &err_attr_name,
669                                                MMCAM_IMAGE_ENCODER_QUALITY,
670                                                quality,
671                                                NULL);
672         if (retValue < 0) {
673             free(err_attr_name);
674             LogDebug(
675                 "couldn't set image quality attribute " << std::hex <<
676                 retValue);
677             Throw(Commons::InvalidArgumentException);
678         }
679
680         if (!captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
681                                                   SETTED_WIDTH) &&
682             !captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
683                                                   SETTED_HEIGHT) &&
684             (Api::Camera::ICaptureOptions::IMAGE_RESOLUTION_DEFAULT !=
685              captureOptions->getImageResolution())) {
686             Resolution res = getCaptureResolution(
687                     Api::Camera::ICaptureOptions::IMAGE_RESOLUTION_LOW ==
688                     captureOptions->getImageResolution()
689                     );
690             LogDebug("Resolution: " << res.getWidth() << "x" << res.getHeight());
691             retValue = mm_camcorder_set_attributes(m_camcorderHandle,
692                                                    &err_attr_name,
693                                                    MMCAM_CAPTURE_WIDTH,
694                                                    res.getWidth(),
695                                                    MMCAM_CAPTURE_HEIGHT,
696                                                    res.getHeight(),
697                                                    NULL);
698             if (retValue < 0) {
699                 free(err_attr_name);
700                 LogDebug(
701                     "couldn't set image resolution attribute " <<
702                     std::hex << retValue);
703                 Throw(Commons::InvalidArgumentException);
704             }
705         }
706     }
707
708     ///"you can't set a file name with "MMCAM_TARGET_FILENAME" when capturing still image"
709     if (captureOptions->isAttributeValid(Api::Camera::ICaptureOptions::
710                                              SETTED_FILE_NAME)) {
711         LogDebug("setting target filename");
712         std::string fileName = captureOptions->getFileName();
713         /*
714          * Not using Api::Filesystem::IManager::access() intentionally - to not
715          * introduce dependencies between Camera and Filesystem modules for such
716          * a minor feature. What's more it allows for a small optimization - only
717          * one access() call is needed when in case of Filesystem::IManager::access()
718          * two would be required (no way to get to `errno` variable).
719          */
720         errno = 0;
721         if (access(fileName.c_str(), W_OK) != 0) {
722             if (ENOENT != errno) {
723                 ThrowMsg(Commons::PlatformException,
724                          "Can't write to specified file.");
725             }
726         } else if (!captureOptions->getOverwrite()) {
727             ThrowMsg(
728                 Commons::PlatformException,
729                 "Output file already exists but overwrite has not been set.");
730         }
731
732         if (Camera::CAPTURING_VIDEO == m_state) {
733             retValue = mm_camcorder_set_attributes(m_camcorderHandle,
734                                                    &err_attr_name,
735                                                    MMCAM_TARGET_FILENAME,
736                                                    fileName.c_str(),
737                                                    fileName.length() *
738                                                    sizeof(char),
739                                                    NULL);
740             if (retValue < 0) {
741                 free(err_attr_name);
742                 LogDebug(
743                     "couldn't set file name attribute " << std::hex <<
744                     retValue);
745                 Throw(Commons::InvalidArgumentException);
746             }
747         }
748     }
749 }
750 //.............................................................................
751 int Camera::reInitializeCamcorderForPicture(
752         const Api::Camera::ICaptureOptionsPtr &captureOptions)
753 {
754     int err;
755     /*"However, you have to set every attribute to fit to video mode, but it's tiresome.
756        So, I recommend to you to call destroy also.
757        Like this, MMCamcorderStop() -> MMCamcorderUnrealize() ->
758        MMCamcorderDestroy() -> MMCamcorderCreate()..
759        get a new handle -> MMCamcorderRealize() ->
760        set  MM_CAMCORDER_MODE_VIDEO -> MMCamcorderStart()"*/
761     LogDebug("Reinitializing camcorder for picture capturing");
762     mm_camcorder_stop(m_camcorderHandle);
763     mm_camcorder_unrealize(m_camcorderHandle);
764     mm_camcorder_destroy(m_camcorderHandle);
765
766     err = mm_camcorder_create(&m_camcorderHandle, &m_camcorderPreset);
767     if (err < 0) {
768         LogError("creating camcorder has failed " << std::hex << err);
769         Throw(Commons::UnknownException);
770     }
771
772     char *err_attr_name = NULL;
773     err = mm_camcorder_set_attributes(
774             m_camcorderHandle, &err_attr_name,
775             MMCAM_MODE, MM_CAMCORDER_MODE_IMAGE,
776             MMCAM_IMAGE_ENCODER, MM_IMAGE_CODEC_JPEG,
777             MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_YUYV,
778             MMCAM_CAMERA_FPS, 30,
779             MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_NONE,
780             MMCAM_CAPTURE_FORMAT, MM_PIXEL_FORMAT_ENCODED,
781             MMCAM_CAPTURE_WIDTH, DEFAULT_CAPTURE_WIDTH,
782             MMCAM_CAPTURE_HEIGHT, DEFAULT_CAPTURE_HEIGHT,
783             MMCAM_CAPTURE_COUNT, 1,
784             MMCAM_DISPLAY_VISIBLE, false,
785             NULL);
786
787     if (err != 0) {
788         LogError("error: " << err_attr_name);
789         free(err_attr_name);
790         Throw(Commons::InvalidArgumentException);
791     }
792     mm_camcorder_set_video_capture_callback(
793         m_camcorderHandle,
794         (mm_camcorder_video_capture_callback) Camera::
795             camcorderVideoCaptureCallback,
796         static_cast<void*>(this));
797     setCaptureOptions(captureOptions);
798     return 0;
799 }
800 //.............................................................................
801 int Camera::reInitializeCamcorderForVideo(
802         const Api::Camera::ICaptureOptionsPtr &captureOptions)
803 {
804     /*"However, you have to set every attribute to fit to video mode, but it's tiresome.
805        So, I recommend to you to call destroy also.
806        Like this, MMCamcorderStop() -> MMCamcorderUnrealize() ->
807        MMCamcorderDestroy() -> MMCamcorderCreate()..
808        get a new handle -> MMCamcorderRealize() ->
809        set  MM_CAMCORDER_MODE_VIDEO -> MMCamcorderStart()"*/
810
811     LogDebug("Reinitializing camcorder for video capturing");
812
813     mm_camcorder_stop(m_camcorderHandle);
814     mm_camcorder_unrealize(m_camcorderHandle);
815     mm_camcorder_destroy(m_camcorderHandle);
816     mm_camcorder_create(&m_camcorderHandle, &m_camcorderPreset);
817
818     int err;
819     char *err_attr_name = NULL;
820
821     err = mm_camcorder_set_attributes((MMHandleType)m_camcorderHandle,
822                                       &err_attr_name,
823                                       MMCAM_MODE,
824                                       MM_CAMCORDER_MODE_VIDEO,
825                                       MMCAM_AUDIO_DEVICE,
826                                       MM_AUDIO_DEVICE_MIC,
827                                       MMCAM_AUDIO_ENCODER,
828                                       MM_AUDIO_CODEC_AAC,
829                                       MMCAM_VIDEO_ENCODER,
830                                       MM_VIDEO_CODEC_MPEG4,
831                                       MMCAM_FILE_FORMAT,
832                                       MM_FILE_FORMAT_3GP,
833                                       MMCAM_CAMERA_WIDTH,
834                                       640,
835                                       MMCAM_CAMERA_HEIGHT,
836                                       480,
837                                       MMCAM_CAMERA_FORMAT,
838                                       MM_PIXEL_FORMAT_NV12,
839                                       MMCAM_CAMERA_FPS,
840                                       30,
841                                       MMCAM_DISPLAY_ROTATION,
842                                       MM_DISPLAY_ROTATION_NONE,
843                                       MMCAM_AUDIO_SAMPLERATE,
844                                       44100,
845                                       MMCAM_AUDIO_CHANNEL,
846                                       2,
847                                       MMCAM_AUDIO_INPUT_ROUTE,
848                                       MM_AUDIOROUTE_CAPTURE_NORMAL,
849                                       NULL);
850
851     if (err != 0) {
852         LogError("error: " << err_attr_name);
853         free(err_attr_name);
854         Throw(Commons::InvalidArgumentException);
855     }
856
857     setCaptureOptions(captureOptions);
858
859     return 0;
860 }
861 //.............................................................................
862 bool Camera::realizeCamcoder()
863 {
864     LogDebug(__FUNCTION__);
865     MMCamcorderStateType state;
866     int ret = mm_camcorder_get_state(m_camcorderHandle, &state);
867     if (MM_CAMCORDER_STATE_NULL == state) {
868         LogDebug("camcorder is not realized - realizing..");
869         ret = mm_camcorder_realize(m_camcorderHandle);
870         if (MM_ERROR_NONE != ret) {
871             LogError(
872                 "realizing the camcorder handle failed " << std::hex <<
873                 ret);
874             Throw(Commons::UnknownException);
875         }
876         return true;
877     } else {
878         LogDebug("camcorder's been already realized");
879     }
880     return false;
881 }
882 //.............................................................................
883 int Camera::unRealizeCamcoder()
884 {
885     if (!m_camcorderHandle) {
886         return -1;
887     }
888     MMCamcorderStateType state;
889     int ret = mm_camcorder_get_state(m_camcorderHandle, &state);
890     if (MM_CAMCORDER_STATE_READY == state) {
891         ret = mm_camcorder_unrealize(m_camcorderHandle);
892         if (MM_ERROR_NONE != ret) {
893             LogError(
894                 "unrealizing the camcorder handle's failed " <<
895                 std::hex << ret);
896             Throw(Commons::UnknownException);
897         }
898     }
899     return MM_ERROR_NONE;
900 }
901 //.............................................................................
902 Camera::Resolution Camera::getCaptureResolution(bool low) const
903 {
904     Assert(m_camcorderHandle && "Camcorder handle is not valid.");
905     Resolution result(DEFAULT_CAPTURE_WIDTH, DEFAULT_CAPTURE_HEIGHT);
906     try {
907         AttributeInfo::ArrayOfInt captureWidth =
908             AttributeInfo::toArrayOfInt(m_camcorderHandle, MMCAM_CAPTURE_WIDTH);
909
910         AttributeInfo::ArrayOfInt captureHeight =
911             AttributeInfo::toArrayOfInt(m_camcorderHandle, MMCAM_CAPTURE_HEIGHT);
912
913         if (!captureWidth.empty() && !captureHeight.empty()) {
914             if (low) {
915                 result.setSize(captureWidth.front(), captureHeight.front());
916             } else {
917                 result.setSize(captureWidth.back(), captureHeight.back());
918             }
919         }
920     }
921     catch (const Commons::Exception& ex) {
922         LogError("Exception: " << ex.GetMessage());
923         LogDebug("Falling back to default resolution.");
924     }
925     return result;
926 }
927 }
928 }
929 }