enable dual camera
[platform/framework/native/media.git] / src / FMedia_CameraCoordinator.cpp
index 8cbe446..ad0e2b7 100755 (executable)
@@ -28,8 +28,6 @@
 #include "FMedia_CameraUtil.h"
 #include "FMedia_RecorderUtil.h"
 
-//#define _VIDEO_RECORDER_ROTATION_
-
 using namespace Tizen::Base;
 using namespace Tizen::Base::Collection;
 
@@ -120,9 +118,7 @@ _CameraCoordinator::_CameraCoordinator()
        , __recorderHandle(MM_INVALID_HANDLE)
        , __mode(_CAMERA_MODE_NONE)
        , __pListenerList(null, _ListPtrUtil::remover)
-       , __orientationFlag(0)
-       , __cameraOrientation(CAMERA_EXIF_ORIENTATION_TOP_LEFT)
-       , __recordingRotation(RECORDING_ROTATION_NONE)
+       , __reloadCameraPreviewFormat(::CAMERA_PIXEL_FORMAT_I420)
 {
 }
 
@@ -178,8 +174,30 @@ _CameraCoordinator::RemoveRecorder(_RecorderDeviceType recorderDevice)
 {
        SysLog(NID_MEDIA, "Enter. recorder device:%d", recorderDevice);
        _RecorderManager::Release(recorderDevice);
-       __recorderHandle = MM_INVALID_HANDLE;
-       __orientationFlag = __orientationFlag & (~_ORIENTATION_FOR_RECORDING);
+       if (_RecorderManager::HasInstance(recorderDevice) == null)
+       {
+               __recorderHandle = MM_INVALID_HANDLE;
+       }
+}
+
+void
+_CameraCoordinator::InitSingleton()
+{
+       result r = E_SUCCESS;
+       std::unique_ptr <_CameraCoordinatorSafeHashMapT> pMap (new (std::nothrow) _CameraCoordinatorSafeHashMapT());
+       SysTryReturnVoidResult(NID_MEDIA, pMap.get() != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.  The object is not created.");
+
+       r = pMap->Construct();
+       SysTryReturnVoidResult(NID_MEDIA, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
+
+       __pMap = pMap.release();
+       std::atexit(DestroySingleton);
+}
+
+void
+_CameraCoordinator::DestroySingleton(void)
+{
+       delete __pMap;
 }
 
 _CameraCoordinator*
@@ -189,27 +207,25 @@ _CameraCoordinator::AddInstance(_CameraDeviceType cameraDevice)
        bool out = false;
        ClearLastResult();
 
-       static bool isMapConstructed = false;
-       static _CameraCoordinatorSafeHashMapT map;
        _CameraCoordinator* pCoordinator = null;
 
        SysTryReturn(NID_MEDIA, cameraDevice > _CAMERA_DEVICE_NONE && cameraDevice < _CAMERA_DEVICE_MAX,
                                null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument(camderDevice) is used. camderDevice:%d is wrong.", cameraDevice);
 
-       if (!isMapConstructed)
+       static pthread_once_t once_block = PTHREAD_ONCE_INIT;
+       if (!__pMap)
        {
-               r = map.Construct();
-               SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
-               isMapConstructed = true;
-               __pMap = &map;
+               pthread_once(&once_block, InitSingleton);
+               r = GetLastResult();
+               SysTryReturn(NID_MEDIA, __pMap != null, null, r, "[%s] Propagating.", GetErrorMessage(r));
        }
 
-       r = map.ContainsKey(cameraDevice, out);
+       r = __pMap->ContainsKey(cameraDevice, out);
        SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
 
        if (out)
        {
-               r = map.GetValue(cameraDevice, pCoordinator);
+               r = __pMap->GetValue(cameraDevice, pCoordinator);
                SysTryReturn(NID_MEDIA, r == E_SUCCESS && pCoordinator != null, null, r, "[%s] Propagating.", GetErrorMessage(r));
        }
        else
@@ -220,7 +236,7 @@ _CameraCoordinator::AddInstance(_CameraDeviceType cameraDevice)
                r = pCoord->Construct(cameraDevice);
                SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
 
-               r = map.Add(cameraDevice, pCoord.get());
+               r = __pMap->Add(cameraDevice, pCoord.get());
                SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
 
                pCoordinator = pCoord.release();
@@ -375,6 +391,7 @@ _CameraCoordinator::AddCameraCoordinatorListener(_ICameraCoordinatorListener& li
 {
        result r = E_SUCCESS;
        r = __pListenerList->Add(&listener);
+       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
        return r;
 }
 
@@ -383,6 +400,10 @@ _CameraCoordinator::RemoveCameraCoordinatorListener(_ICameraCoordinatorListener&
 {
        result r = E_SUCCESS;
        r = __pListenerList->Remove(&listener);
+       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
+
+       r = NotifyOtherRemoved();
+       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
        return r;
 }
 
@@ -449,6 +470,28 @@ _CameraCoordinator::NotifyModeChanged(_CameraMode mode)
 }
 
 result
+_CameraCoordinator::NotifyOtherRemoved(void)
+{
+       result r = E_SUCCESS;
+       _ICameraCoordinatorListener* pListener = null;
+       SysLog(NID_MEDIA, "Enter");
+
+       std::unique_ptr <IEnumeratorT <_ICameraCoordinatorListener*> > pEnum (__pListenerList->GetEnumeratorN());
+       SysTryReturn(NID_MEDIA, pEnum.get() != null, GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
+
+       while (pEnum->MoveNext() == E_SUCCESS)
+       {
+               r = pEnum->GetCurrent(pListener);
+               SysTryReturn(NID_MEDIA, pListener != null && r == E_SUCCESS, E_SYSTEM, E_SYSTEM,
+                                  "[E_SYSTEM] A system error has been occurred.  The listener is not proper");
+
+               r = pListener->OnCameraCoordinatorOtherRemoved();
+               SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
+       }
+       return r;
+}
+
+result
 _CameraCoordinator::StartMmPreview(void)
 {
        result r = E_SUCCESS;
@@ -524,15 +567,84 @@ CATCH:
 }
 
 result
-_CameraCoordinator::ChangeMode(_CameraMode mode, bool callback)
+_CameraCoordinator::CreateVideoRecorder(void)
 {
        result r = E_SUCCESS;
-       camera_state_e cameraState = ::CAMERA_STATE_NONE;
+       _RecorderDeviceType recorderDevice = _RECORDER_DEVICE_NONE;
+       SysLog(NID_MEDIA, "enter.");
+
+       // Start recorder
+       recorderDevice = __cameraDevice == _CAMERA_DEVICE_PRIMARY ?
+       _RECORDER_DEVICE_VIDEO_PRIMARY_CAMERA : _RECORDER_DEVICE_VIDEO_SECONDARY_CAMERA;
+       r = AddRecorder(recorderDevice);                // recorder_create() will be called.
+       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+       __mode = _CAMERA_MODE_VIDEO;
+
+       return r;
+CATCH:
+       return r;
+}
+
+result
+_CameraCoordinator::DestroyVideoRecorder(void)
+{
+       result r = E_SUCCESS;
+       int err = MM_SUCCESS;
        recorder_state_e recorderState = ::RECORDER_STATE_NONE;
        _RecorderDeviceType recorderDevice = _RECORDER_DEVICE_NONE;
+       SysLog(NID_MEDIA, "enter.");
+
+       if ( __recorderHandle != MM_INVALID_HANDLE )
+       {
+               recorderState = GetRecorderState();
+               // Stop the recorder
+               switch (recorderState)
+               {
+               case ::RECORDER_STATE_NONE:
+                       break;
+
+               case ::RECORDER_STATE_CREATED:
+                       //fall through
+               case ::RECORDER_STATE_READY:
+                       recorderDevice = __cameraDevice == _CAMERA_DEVICE_PRIMARY ?
+                               _RECORDER_DEVICE_VIDEO_PRIMARY_CAMERA : _RECORDER_DEVICE_VIDEO_SECONDARY_CAMERA;
+                       RemoveRecorder(recorderDevice);
+                       __mode = _CAMERA_MODE_IMAGE;
+                       break;
+
+               case ::RECORDER_STATE_RECORDING:
+                       //fall through
+               case ::RECORDER_STATE_PAUSED:
+                       err = recorder_cancel(__recorderHandle);
+                       r = ConvertResult(err);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+                       recorderDevice = __cameraDevice == _CAMERA_DEVICE_PRIMARY ?
+                               _RECORDER_DEVICE_VIDEO_PRIMARY_CAMERA : _RECORDER_DEVICE_VIDEO_SECONDARY_CAMERA;
+                       RemoveRecorder(recorderDevice);
+                       __mode = _CAMERA_MODE_IMAGE;
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       return r;
+CATCH:
+       return r;
+}
+
+
+result
+_CameraCoordinator::ChangeFormat(_CameraMode mode, bool callback, camera_pixel_format_e reloadCameraPreviewFormat)
+{
+       result r = E_SUCCESS;
        int err = MM_SUCCESS;
+       _RecorderDeviceType recorderDevice = _RECORDER_DEVICE_NONE;
+       camera_state_e cameraState = ::CAMERA_STATE_NONE;
+       recorder_state_e recorderState = ::RECORDER_STATE_NONE;
+       SysLog(NID_MEDIA, "enter. mode:%d, callback:%d,         reloadCameraPreviewFormat:%d", mode, callback, reloadCameraPreviewFormat);
 
-       SysLog(NID_MEDIA, "Mode should be changed. mode:%d", mode);
        if (mode == _CAMERA_MODE_VIDEO)
        {
                cameraState = GetCameraState();
@@ -561,16 +673,148 @@ _CameraCoordinator::ChangeMode(_CameraMode mode, bool callback)
                        break;
                }
 
-               // Start recorder
-               if ( __recorderHandle == MM_INVALID_HANDLE )
+               __mode = _CAMERA_MODE_VIDEO;
+               __reloadCameraPreviewFormat = reloadCameraPreviewFormat;
+               if (callback)
+               {
+                       r = NotifyModeChangePrepared(mode);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+               }
+
+               switch (cameraState)
+               {
+               case ::CAMERA_STATE_NONE:
+                       //fall through
+               case ::CAMERA_STATE_CREATED:
+                       break;
+
+               case ::CAMERA_STATE_PREVIEW:
+                       r = ChangeRecorderStateTo(::RECORDER_STATE_READY);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+                       break;
+
+               case ::CAMERA_STATE_CAPTURED:
+               default:
+                       break;
+               }
+       }
+       else if ( mode == _CAMERA_MODE_IMAGE )
+       {
+               recorderState = GetRecorderState();
+
+               switch (recorderState)
                {
+               case ::RECORDER_STATE_NONE:
+                       break;
+               case ::RECORDER_STATE_CREATED:
+                       __mode = _CAMERA_MODE_IMAGE;
+                       __reloadCameraPreviewFormat = reloadCameraPreviewFormat;
+                       if (callback)
+                       {
+                               r = NotifyModeChangePrepared(mode);
+                               SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+                       }
+                       break;
+
+               case ::RECORDER_STATE_READY:
+                       r = ChangeRecorderStateTo(::RECORDER_STATE_CREATED);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+
+                       __mode = _CAMERA_MODE_IMAGE;
+                       __reloadCameraPreviewFormat = reloadCameraPreviewFormat;
+                       if (callback)
+                       {
+                               r = NotifyModeChangePrepared(mode);
+                               SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+                       }
+                       r = ChangeCameraStateTo(::CAMERA_STATE_PREVIEW);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+                       break;
+
+               case ::RECORDER_STATE_RECORDING:
+                       //fall through
+               case ::RECORDER_STATE_PAUSED:
+                       err = recorder_cancel(__recorderHandle);                // TODO
+                       r = ConvertResult(err);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+
+                       r = ChangeRecorderStateTo(::RECORDER_STATE_CREATED);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
                        recorderDevice = __cameraDevice == _CAMERA_DEVICE_PRIMARY ?
                                _RECORDER_DEVICE_VIDEO_PRIMARY_CAMERA : _RECORDER_DEVICE_VIDEO_SECONDARY_CAMERA;
-                       r = AddRecorder(recorderDevice);                // recorder_create() will be called.
+
+                       __mode = _CAMERA_MODE_IMAGE;
+                       __reloadCameraPreviewFormat = reloadCameraPreviewFormat;
+                       if (callback)
+                       {
+                               r = NotifyModeChangePrepared(mode);
+                               SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+                       }
+                       r = ChangeCameraStateTo(::CAMERA_STATE_PREVIEW);
+                       SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       if (callback)
+       {
+               // Notify that the mode is changed to callback camera and video recorder's configurations.
+               r = NotifyModeChanged(mode);
+               SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+       }
+       return r;
+CATCH:
+       return r;
+}
+
+result
+_CameraCoordinator::ChangeMode(_CameraMode mode, bool callback)
+{
+       result r = E_SUCCESS;
+       camera_state_e cameraState = ::CAMERA_STATE_NONE;
+       recorder_state_e recorderState = ::RECORDER_STATE_NONE;
+       _RecorderDeviceType recorderDevice = _RECORDER_DEVICE_NONE;
+       int err = MM_SUCCESS;
+
+       SysLog(NID_MEDIA, "Mode should be changed. mode:%d", mode);
+       if (mode == _CAMERA_MODE_VIDEO)
+       {
+               cameraState = GetCameraState();
+
+               switch (cameraState)
+               {
+               case ::CAMERA_STATE_CREATED:
+                       //fall through
+               case ::CAMERA_STATE_NONE:
+                       break;
+
+               case ::CAMERA_STATE_PREVIEW:
+                       //fall through
+               case ::CAMERA_STATE_CAPTURED:
+                       r = ChangeCameraStateTo(::CAMERA_STATE_CREATED);
                        SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
-                       __mode = _CAMERA_MODE_VIDEO;
+                       break;
+
+               case ::CAMERA_STATE_CAPTURING:
+                       r = E_INVALID_STATE;
+                       SysLogException(NID_MEDIA, r, "[E_INVALID_STATE] cameraState(%d) is in an invalid state. While the camera is capturing, the mode cannot be changed.", cameraState);
+                       goto CATCH;
+                       break;
+
+               default:
+                       break;
                }
 
+               // Start recorder
+               recorderDevice = __cameraDevice == _CAMERA_DEVICE_PRIMARY ?
+                       _RECORDER_DEVICE_VIDEO_PRIMARY_CAMERA : _RECORDER_DEVICE_VIDEO_SECONDARY_CAMERA;
+               r = AddRecorder(recorderDevice);                // recorder_create() will be called.
+               SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
+               __mode = _CAMERA_MODE_VIDEO;
+
                if (callback)
                {
                        r = NotifyModeChangePrepared(mode);
@@ -961,17 +1205,7 @@ _CameraCoordinator::StartCapture(camera_capturing_cb capturingCb , camera_captur
        result r = E_SUCCESS;
        int err = MM_SUCCESS;
 
-       if (__orientationFlag & _ORIENTATION_FOR_CAMERA)
-       {
-               r = SetCameraOrientationAttr(__cameraOrientation);
-               SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
-       }
-       else if (__orientationFlag & _ORIENTATION_FOR_RECORDING)        // If recorder setting is remained.
-       {
-               r = SetCameraOrientationAttr(CAMERA_EXIF_ORIENTATION_TOP_LEFT); // To set the init value
-               SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
-       }
-
+       __mode = _CAMERA_MODE_IMAGE;
        err = camera_start_capture(__cameraHandle, capturingCb, completedCb, pUserData);
        r = ConvertResult(err);
        SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Camera capture failed.", GetErrorMessage(r));
@@ -985,17 +1219,7 @@ _CameraCoordinator::StartRecord(void)
        result r = E_SUCCESS;
        int err = MM_SUCCESS;
 
-       if (__orientationFlag & _ORIENTATION_FOR_RECORDING)
-       {
-               r = SetRecordingOrientationAttr(__recordingRotation);
-               SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
-       }
-       else if (__orientationFlag & _ORIENTATION_FOR_CAMERA)   // If recorder setting is remained.
-       {
-               r = SetRecordingOrientationAttr(RECORDING_ROTATION_NONE);       // To set the init value
-               SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
-       }
-
+       __mode = _CAMERA_MODE_VIDEO;
        err = recorder_start(__recorderHandle);
        r = ConvertResult(err);
        SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Recorder record failed.", GetErrorMessage(r));
@@ -1003,65 +1227,10 @@ _CameraCoordinator::StartRecord(void)
        return r;
 }
 
-void
-_CameraCoordinator::SetRecordingOrientation(RecordingRotation rotation)
-{
-       __orientationFlag = __orientationFlag | _ORIENTATION_FOR_RECORDING;
-       __recordingRotation = rotation;
-}
-
-void
-_CameraCoordinator::SetCameraOrientation(CameraExifOrientation orientation)
-{
-       __orientationFlag = __orientationFlag | _ORIENTATION_FOR_CAMERA;
-       __cameraOrientation = orientation;
-}
-
-result
-_CameraCoordinator::SetRecordingOrientationAttr(RecordingRotation rotation)
-{
-       result r = E_SUCCESS;
-       int err = MM_SUCCESS;
-#if _VIDEO_RECORDER_ROTATION_
-       recorder_rotation_e mmAttr = ::RECORDER_ROTATION_NONE;
-       r = _RecorderUtil::GetMmRotation(rotation, mmAttr);
-       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating. rotation:%d", GetErrorMessage(r), rotation);
-
-       err = recorder_attr_set_recording_orientation(__recorderHandle, mmAttr);
-       r = ConvertResult(err);
-       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Camcorder set attribute failed. rotation:%d", GetErrorMessage(r), rotation);
-#else
-       CameraRotation cameraRotation = CAMERA_ROTATION_NONE;
-       r = _RecorderUtil::GetCameraRotation(rotation, cameraRotation);
-       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating. rotation:%d", GetErrorMessage(r), rotation);
-
-       camera_attr_tag_orientation_e mmOrientationAttr = CAMERA_ATTR_TAG_ORIENTATION_TOP_LEFT;
-       r = _CameraUtil::GetMmExifOrientation(cameraRotation, mmOrientationAttr);
-       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating. rotation:%d", GetErrorMessage(r), rotation);
-
-       err = camera_attr_set_tag_orientation(__cameraHandle, mmOrientationAttr);
-       r = ConvertResult(err);
-       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Camcorder set attribute failed. Mm orientation:%d", GetErrorMessage(r), mmOrientationAttr);
-#endif
-
-       return r;
-}
-
-result
-_CameraCoordinator::SetCameraOrientationAttr(CameraExifOrientation orientation)
+camera_pixel_format_e
+_CameraCoordinator::GetReloadPreviewFormat(void) const
 {
-       result r = E_SUCCESS;
-       int err = MM_SUCCESS;
-       camera_attr_tag_orientation_e attr = ::CAMERA_ATTR_TAG_ORIENTATION_TOP_LEFT;
-
-       r = _CameraUtil::GetMmExifOrientation(orientation, attr);
-       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating. orientation:%d", GetErrorMessage(r), orientation);
-
-       err = camera_attr_set_tag_orientation(__cameraHandle, attr);
-       r = ConvertResult(err);
-       SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating. orientation:%d", GetErrorMessage(r), orientation);
-
-       return r;
+       SysLog(NID_MEDIA, "reloadCameraPreviewFormat is :%d", __reloadCameraPreviewFormat);
+       return __reloadCameraPreviewFormat;
 }
-
 }}