From 23ea44a8fa33d0d27cda9ac6e91063604c2f7a05 Mon Sep 17 00:00:00 2001 From: Sun-woo Nam Date: Wed, 22 Mar 2023 12:50:37 +0530 Subject: [PATCH] [M108 Migration] ImageCapture support for video capture device. - ImageCapture support for video capture device. - Don't expose CAPI camera handle. - Re-select Camera Preview Format. Migrated from: https://review.tizen.org/gerrit/#/c/279886/ Change-Id: I31470b8471ddef942655df59d2202237bd1ab863 Signed-off-by: Suhaspoornachandra --- media/capture/mojom/BUILD.gn | 4 + media/capture/mojom/video_capture_types.mojom | 2 + .../mojom/video_capture_types_mojom_traits.cc | 3 + .../mojom/video_capture_types_mojom_traits.h | 6 + media/capture/video_capture_types.h | 3 + .../capture/video/tizen/camera_device_tizen.cc | 260 +++++++++++++- .../capture/video/tizen/camera_device_tizen.h | 77 +++- .../tizen/video_capture_device_factory_tizen.cc | 6 +- .../video/tizen/video_capture_device_tizen.cc | 393 ++++++++++++++++----- .../video/tizen/video_capture_device_tizen.h | 43 ++- 10 files changed, 694 insertions(+), 103 deletions(-) diff --git a/media/capture/mojom/BUILD.gn b/media/capture/mojom/BUILD.gn index 65cd420..9f0823f 100644 --- a/media/capture/mojom/BUILD.gn +++ b/media/capture/mojom/BUILD.gn @@ -9,6 +9,10 @@ if (use_aura) { } enabled_features = [] +if (tizen_multimedia) { + enabled_features += [ "tizen_multimedia" ] +} + if (tizen_tbm_support) { enabled_features += [ "tizen_tbm_support" ] } diff --git a/media/capture/mojom/video_capture_types.mojom b/media/capture/mojom/video_capture_types.mojom index e58304e..8b23d5e 100644 --- a/media/capture/mojom/video_capture_types.mojom +++ b/media/capture/mojom/video_capture_types.mojom @@ -295,6 +295,8 @@ struct VideoCaptureParams { ResolutionChangePolicy resolution_change_policy; PowerLineFrequency power_line_frequency; bool enable_face_detection; + [EnableIf=tizen_multimedia] + bool lazy_start; }; [Stable, RenamedFrom="media.mojom.VideoFrameFeedback"] diff --git a/media/capture/mojom/video_capture_types_mojom_traits.cc b/media/capture/mojom/video_capture_types_mojom_traits.cc index aa05fa7..be79c50 100644 --- a/media/capture/mojom/video_capture_types_mojom_traits.cc +++ b/media/capture/mojom/video_capture_types_mojom_traits.cc @@ -1821,6 +1821,9 @@ bool StructTraitspower_line_frequency)) return false; out->enable_face_detection = data.enable_face_detection(); +#if defined(TIZEN_MULTIMEDIA) + out->lazy_start = data.lazy_start(); +#endif return true; } diff --git a/media/capture/mojom/video_capture_types_mojom_traits.h b/media/capture/mojom/video_capture_types_mojom_traits.h index b0e4c82..51f8c41 100644 --- a/media/capture/mojom/video_capture_types_mojom_traits.h +++ b/media/capture/mojom/video_capture_types_mojom_traits.h @@ -172,6 +172,12 @@ struct COMPONENT_EXPORT(MEDIA_CAPTURE_MOJOM_TRAITS) return params.enable_face_detection; } +#if defined(TIZEN_MULTIMEDIA) + static bool lazy_start(const media::VideoCaptureParams& params) { + return params.lazy_start; + } +#endif + static bool Read(media::mojom::VideoCaptureParamsDataView data, media::VideoCaptureParams* out); }; diff --git a/media/capture/video_capture_types.h b/media/capture/video_capture_types.h index e6d8961..9f48d90 100644 --- a/media/capture/video_capture_types.h +++ b/media/capture/video_capture_types.h @@ -333,6 +333,9 @@ struct CAPTURE_EXPORT VideoCaptureParams { // exposures around the face area. Currently only applicable on // Android platform with Camera2 driver support. bool enable_face_detection; +#if defined(TIZEN_MULTIMEDIA) + bool lazy_start{false}; +#endif }; } // namespace media diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc index 703389c..65356f6 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc +++ b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc @@ -6,12 +6,16 @@ #include "media/capture/video/tizen/video_capture_device_tizen.h" -namespace media { +namespace { enum { kMaxWidth = 1280 }; enum { kMaxHeight = 720 }; enum { kMaxFramerate = CAMERA_ATTR_FPS_30 }; +constexpr int kMinIso = 50; +constexpr int kMaxIso = 3200; +constexpr int kStepIso = 50; + media::VideoPixelFormat toChromiumType(camera_pixel_format_e e) { switch (e) { case CAMERA_PIXEL_FORMAT_NV12: @@ -33,11 +37,55 @@ media::VideoPixelFormat toChromiumType(camera_pixel_format_e e) { case CAMERA_PIXEL_FORMAT_JPEG: return media::PIXEL_FORMAT_MJPEG; default: - NOTREACHED(); + NOTREACHED() << "Unknown format #" << e; } return media::PIXEL_FORMAT_UNKNOWN; } +int FromIsoToInteger(camera_attr_iso_e mode) { + switch (mode) { + case CAMERA_ATTR_ISO_50: + return 50; + case CAMERA_ATTR_ISO_100: + return 100; + case CAMERA_ATTR_ISO_200: + return 200; + case CAMERA_ATTR_ISO_400: + return 400; + case CAMERA_ATTR_ISO_800: + return 800; + case CAMERA_ATTR_ISO_1600: + return 1600; + case CAMERA_ATTR_ISO_3200: + return 3200; + + // return minimum value in default case + default: + LOG(ERROR) << "Unknown mode (" << mode << ") Returning " << kMinIso; + return kMinIso; + } +} + +camera_attr_iso_e FromIntegerToCapiIsoFormat(unsigned int value) { + if (value == kMinIso) + return CAMERA_ATTR_ISO_50; + if (value == 100) + return CAMERA_ATTR_ISO_100; + if (value == 200) + return CAMERA_ATTR_ISO_200; + if (value == 400) + return CAMERA_ATTR_ISO_400; + if (value == 800) + return CAMERA_ATTR_ISO_800; + if (value == 1600) + return CAMERA_ATTR_ISO_1600; + if (value == kMaxIso) + return CAMERA_ATTR_ISO_3200; + + LOG(ERROR) << "Unknown value (" << value << ") Returning ISO Auto"; + return CAMERA_ATTR_ISO_AUTO; +} + bool OnCameraSupportedPreviewResolution(int width, int height, void* user_data) { @@ -98,35 +146,133 @@ void GenerateChromiumVideoCaptureFormat( } } -CameraHandle::CameraHandle() : camera_handle_(NULL), client_(NULL) { +} // anonymous namespace + +namespace media { + +mojom::RangePtr SetRange(double min, double max, double current, double step) { + mojom::RangePtr range_ptr = mojom::Range::New(); + range_ptr->min = min; + range_ptr->max = max; + range_ptr->current = current; + range_ptr->step = step; + return range_ptr; +} + +mojom::RedEyeReduction PhotoCapabilities::GetRedEyeReduction() { + camera_attr_flash_mode_e mode = CAMERA_ATTR_FLASH_MODE_OFF; + camera_attr_get_flash_mode(camera_, &mode); + if (mode != CAMERA_ATTR_FLASH_MODE_REDEYE_REDUCTION) + return mojom::RedEyeReduction::CONTROLLABLE; + return mojom::RedEyeReduction::NEVER; +} + +mojom::RangePtr PhotoCapabilities::GetExposureCompensation() { + if (exposureCompensation_.min == -1) + camera_attr_get_exposure_range(camera_, &exposureCompensation_.min, + &exposureCompensation_.max); + + if (exposureCompensation_.min != -1) { + int current = -1; + if (CAMERA_ERROR_NONE == camera_attr_get_exposure(camera_, ¤t)) + return SetRange(exposureCompensation_.min, exposureCompensation_.max, + current, 1.0); + } + return mojom::Range::New(); +} + +mojom::RangePtr PhotoCapabilities::GetIso() { + camera_attr_iso_e current_iso = CAMERA_ATTR_ISO_AUTO; + if (CAMERA_ERROR_NONE == camera_attr_get_iso(camera_, ¤t_iso)) + return SetRange(kMinIso, kMaxIso, FromIsoToInteger(current_iso), kStepIso); + + return mojom::Range::New(); +} + +mojom::RangePtr PhotoCapabilities::GetBrightness() { + if (brightness_.min == -1) + camera_attr_get_brightness_range(camera_, &brightness_.min, + &brightness_.max); + + if (brightness_.min != -1) { + int current = -1; + if (CAMERA_ERROR_NONE == camera_attr_get_brightness(camera_, ¤t)) + return SetRange(brightness_.min, brightness_.max, current, 1.0); + } + return mojom::Range::New(); +} + +mojom::RangePtr PhotoCapabilities::GetContrast() { + if (contrast_.min == -1) + camera_attr_get_contrast_range(camera_, &contrast_.min, &contrast_.max); + + if (contrast_.min != -1) { + int current = -1; + if (CAMERA_ERROR_NONE == camera_attr_get_contrast(camera_, ¤t)) + return SetRange(contrast_.min, contrast_.max, current, 1.0); + } + return mojom::Range::New(); +} + +mojom::RangePtr PhotoCapabilities::GetImageHeight() { + // TODO: Remove hardcoding height and width values + return SetRange(480, 480, 480, 0.0); +} + +mojom::RangePtr PhotoCapabilities::GetImageWidth() { + return SetRange(640, 640, 640, 0.0); +} + +mojom::RangePtr PhotoCapabilities::GetZoom() { + if (zoom_.min == -1) + camera_attr_get_zoom_range(camera_, &zoom_.min, &zoom_.max); + + if (zoom_.min != -1) { + int current = -1; + if (CAMERA_ERROR_NONE == camera_attr_get_zoom(camera_, ¤t)) + return SetRange(zoom_.min, zoom_.max, current, 1.0); + } + return mojom::Range::New(); +} + +CameraHandle::CameraHandle() : camera_handle_(nullptr), client_(nullptr) { LOG(INFO) << "Creating the camera instance"; device_name_ = CAMERA_DEVICE_CAMERA0; ResetHandle(device_name_); } CameraHandle::~CameraHandle() { - if (camera_handle_ != NULL) + if (camera_handle_ != nullptr) { camera_destroy(camera_handle_); + camera_handle_ = nullptr; + } } void CameraHandle::ResetHandle(camera_device_e device_name) { - if (camera_handle_ != NULL) { - if (client_ != NULL) + int err = 0; + if (camera_handle_ != nullptr) { + if (client_ != nullptr) client_->OnStreamStopped(); - camera_destroy(camera_handle_); - camera_handle_ = NULL; + if (CAMERA_ERROR_NONE != (err = camera_destroy(camera_handle_))) { + LOG(ERROR) << "camera_destroy error : " + << media::VideoCaptureDeviceTizen::GetErrorString(err); + } + + camera_handle_ = nullptr; } - int err = 0; if (CAMERA_ERROR_NONE != (err = camera_create(device_name, &camera_handle_))) { - camera_handle_ = NULL; + camera_handle_ = nullptr; LOG(ERROR) << "Cannot create camera, Error:" << media::VideoCaptureDeviceTizen::GetErrorString(err); + return; } else { device_name_ = device_name; } + + capabilities_.reset(new PhotoCapabilities(camera_handle_)); } void CameraHandle::SetClient(CameraHandleClient* client) { @@ -135,7 +281,7 @@ void CameraHandle::SetClient(CameraHandleClient* client) { void CameraHandle::UnsetClient(CameraHandleClient* client) { if (client_ == client) - client_ = NULL; + client_ = nullptr; } CameraHandle* CameraHandle::GetInstance() { @@ -143,7 +289,7 @@ CameraHandle* CameraHandle::GetInstance() { } bool CameraHandle::IsValid() { - return camera_handle_ != NULL; + return camera_handle_ != nullptr; } bool CameraHandle::GetSupportedPreviewResolutions( @@ -251,4 +397,94 @@ int CameraHandle::GetDeviceCounts() { return device_count; } +// Set Photo Capabilities +bool CameraHandle::SetZoom(int value) { + return CAMERA_ERROR_NONE == camera_attr_set_zoom(camera_handle_, value); +} + +bool CameraHandle::SetResolution(int width, int height) { + return CAMERA_ERROR_NONE == + camera_set_capture_resolution(camera_handle_, width, height); +} + +bool CameraHandle::SetBrightness(int value) { + return CAMERA_ERROR_NONE == camera_attr_set_brightness(camera_handle_, value); +} + +bool CameraHandle::SetContrast(int value) { + return CAMERA_ERROR_NONE == camera_attr_set_contrast(camera_handle_, value); +} + +bool CameraHandle::SetIso(int value) { + return CAMERA_ERROR_NONE == + camera_attr_set_iso(camera_handle_, FromIntegerToCapiIsoFormat(value)); +} + +bool CameraHandle::SetExposure(int value) { + return CAMERA_ERROR_NONE == camera_attr_set_exposure(camera_handle_, value); +} + +int CameraHandle::CameraStartPreview() { + return camera_start_preview(camera_handle_); +} + +int CameraHandle::CameraStopPreview() { + return camera_stop_preview(camera_handle_); +} + +camera_attr_fps_e CameraHandle::CameraGetPreviewFps() { + camera_attr_fps_e current_fps = static_cast(30); + camera_attr_get_preview_fps(camera_handle_, ¤t_fps); + return current_fps; +} + +int CameraHandle::CameraSetDisplay(camera_display_type_e type, + camera_display_h display) { + return camera_set_display(camera_handle_, type, display); +} + +int CameraHandle::CameraSetCaptureFormat(camera_pixel_format_e format) { + return camera_set_capture_format(camera_handle_, format); +} + +int CameraHandle::CameraStartCapture(camera_capturing_cb capturingCB, + camera_capture_completed_cb completedCB, + void* data) { + return camera_start_capture(camera_handle_, capturingCB, completedCB, data); +} + +int CameraHandle::CameraSetPreviewResolution(int width, int height) { + return camera_set_preview_resolution(camera_handle_, width, height); +} + +int CameraHandle::CameraSetPreviewFormat(camera_pixel_format_e format) { + return camera_set_preview_format(camera_handle_, format); +} + +int CameraHandle::CameraSetPreviewFps(camera_attr_fps_e fps) { + return camera_attr_set_preview_fps(camera_handle_, fps); +} + +int CameraHandle::CameraSetPreviewCb(camera_preview_cb callback, void* data) { + return camera_set_preview_cb(camera_handle_, callback, data); +} + +int CameraHandle::CameraUnsetPreviewCb() { + return camera_unset_preview_cb(camera_handle_); +} + +int CameraHandle::CameraSetMediapacketPreviewCb( + camera_media_packet_preview_cb callback, + void* data) { + return camera_set_media_packet_preview_cb(camera_handle_, callback, data); +} + +int CameraHandle::CameraUnsetMediapacketPreviewCb() { + return camera_unset_media_packet_preview_cb(camera_handle_); +} + +int CameraHandle::CameraSetStreamFlip(camera_flip_e flip) { + return camera_attr_set_stream_flip(camera_handle_, flip); +} + } // namespace media diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h index f649d04..91c6dda 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h +++ b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h @@ -10,8 +10,11 @@ #include "base/memory/singleton.h" #include "media/base/video_types.h" +#include "media/capture/mojom/image_capture.mojom.h" #include "ui/gfx/gpu_memory_buffer.h" +using media::mojom::MeteringMode; + namespace media { struct VideoCaptureFormat; @@ -29,6 +32,42 @@ struct CameraCapability { Fps fps; }; +struct Range { + int min = -1; + int max = -1; +}; + +class PhotoCapabilities { + public: + mojom::RedEyeReduction GetRedEyeReduction(); + mojom::MeteringMode GetWhiteBalanceMode() { + return mojom::MeteringMode::NONE; + } + mojom::MeteringMode GetExposureMode() { return MeteringMode::NONE; } + mojom::MeteringMode GetFocusMode() { return MeteringMode::NONE; } + mojom::RangePtr GetColorTemperature() { return mojom::Range::New(); } + mojom::RangePtr GetExposureCompensation(); + mojom::RangePtr GetIso(); + mojom::RangePtr GetBrightness(); + mojom::RangePtr GetContrast(); + mojom::RangePtr GetSaturation() { return mojom::Range::New(); } + mojom::RangePtr GetSharpness() { return mojom::Range::New(); } + mojom::RangePtr GetImageHeight(); + mojom::RangePtr GetImageWidth(); + mojom::RangePtr GetZoom(); + + private: + PhotoCapabilities(camera_h camera) : camera_(camera) {} + + camera_h camera_; + Range exposureCompensation_; + Range brightness_; + Range contrast_; + Range zoom_; + + friend class CameraHandle; +}; + class CameraHandleClient { public: virtual void OnStreamStopped() {} @@ -41,7 +80,6 @@ class CameraHandle final { public: static CameraHandle* GetInstance(); - camera_h GetCameraHandle() { return camera_handle_; } camera_device_e GetDeviceName() { return device_name_; } bool IsValid(); @@ -54,6 +92,43 @@ class CameraHandle final { void SetClient(CameraHandleClient* client); void UnsetClient(CameraHandleClient* client); + // Set Photo Capabilities + bool SetZoom(int value); + bool SetResolution(int width, int height); + bool SetBrightness(int value); + bool SetContrast(int value); + bool SetIso(int value); + bool SetExposure(int value); + + std::unique_ptr capabilities_; + + int CameraStartCapture(camera_capturing_cb capturingCB, + camera_capture_completed_cb completedCB, + void* data); + int CameraSetCaptureFormat(camera_pixel_format_e format); + int CameraSetCaptureResolution(int width, int height); + + // camera apis + int CameraStartPreview(); + int CameraStopPreview(); + int CameraSetStreamFlip(camera_flip_e flip); + + // getter + camera_attr_fps_e CameraGetPreviewFps(); + + // setter + int CameraSetDisplay(camera_display_type_e type, camera_display_h display); + int CameraSetPreviewResolution(int width, int height); + int CameraSetPreviewFormat(camera_pixel_format_e format); + int CameraSetPreviewFps(camera_attr_fps_e fps); + + // callbacks + int CameraSetPreviewCb(camera_preview_cb callback, void* data); + int CameraUnsetPreviewCb(); + int CameraSetMediapacketPreviewCb(camera_media_packet_preview_cb callback, + void* data); + int CameraUnsetMediapacketPreviewCb(); + private: CameraHandle(); ~CameraHandle(); diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc index aa935bb..b3f3bf3 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc +++ b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc @@ -33,13 +33,11 @@ void VideoCaptureDeviceFactoryTizen::GetDevicesInfo( GetDevicesInfoCallback callback) { std::vector devices_info; CameraHandle* camera_handle = CameraHandle::GetInstance(); - LOG(INFO) << "Received the camera handle:" - << camera_handle->GetCameraHandle(); - - if (!camera_handle->IsValid()) { + if (camera_handle == nullptr || !camera_handle->IsValid()) { LOG(ERROR) << "Cannot use camera"; return; } + LOG(INFO) << "Received the camera handle:" << camera_handle; int device_count = camera_handle->GetDeviceCounts(); if (device_count == 0) { diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc index 85251ff..e57ee7a 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc +++ b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc @@ -5,6 +5,8 @@ #include "media/capture/video/tizen/video_capture_device_tizen.h" #include "base/bind.h" +#include "media/base/video_color_space.h" +#include "media/capture/mojom/image_capture_types.h" #include "third_party/libyuv/include/libyuv.h" #include "tizen/system_info.h" #include "ui/display/display.h" @@ -19,7 +21,6 @@ namespace { enum { kMjpegWidth = 640 }; enum { kMjpegHeight = 480 }; -enum { kTypicalFramerate = 30 }; enum CameraOrientation { DEGREE_0 = 0, DEGREE_90 = 90, @@ -28,7 +29,7 @@ enum CameraOrientation { DEGREE_360 = 360, }; -camera_pixel_format_e toCapiType(media::VideoPixelFormat e) { +camera_pixel_format_e ToCapiType(media::VideoPixelFormat e) { switch (e) { case media::PIXEL_FORMAT_NV12: return CAMERA_PIXEL_FORMAT_NV12; @@ -51,6 +52,7 @@ camera_pixel_format_e toCapiType(media::VideoPixelFormat e) { default: NOTREACHED(); } + LOG(ERROR) << __func__ << " " << e; return CAMERA_PIXEL_FORMAT_INVALID; } @@ -116,7 +118,7 @@ static CameraOrientation GetCameraOrientation(const char* device_id) { VideoCaptureDeviceTizen::VideoCaptureDeviceTizen( const VideoCaptureDeviceDescriptor& device_descriptor) - : camera_(nullptr), + : camera_instance_(nullptr), buffer_(), device_descriptor_(device_descriptor), worker_("VideoCapture"), @@ -126,15 +128,15 @@ VideoCaptureDeviceTizen::VideoCaptureDeviceTizen( #if TIZEN_MM_DEBUG_VIDEO_DUMP_DECODED_FRAME == 1 frameDumper = new FrameDumper(); #endif - - if (IsMobileProfile()) - use_media_packet_ = true; } VideoCaptureDeviceTizen::~VideoCaptureDeviceTizen() { - CameraHandle::GetInstance()->UnsetClient(this); + if (camera_instance_ != nullptr) + camera_instance_->UnsetClient(this); + state_ = kIdle; DCHECK(!worker_.IsRunning()); + photo_callbacks_.clear(); } void VideoCaptureDeviceTizen::OnStreamStopped() { @@ -147,13 +149,13 @@ void VideoCaptureDeviceTizen::AllocateAndStart( DCHECK(!worker_.IsRunning()); worker_.Start(); worker_.task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&VideoCaptureDeviceTizen::OnAllocateAndStart, - base::Unretained(this), - params.requested_format.frame_size.width(), - params.requested_format.frame_size.height(), - params.requested_format.frame_rate, - params.requested_format.pixel_format, std::move(client))); + FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::OnAllocateAndStart, + base::Unretained(this), + params.requested_format.frame_size.width(), + params.requested_format.frame_size.height(), + params.requested_format.frame_rate, + params.requested_format.pixel_format, + params.lazy_start, std::move(client))); } void VideoCaptureDeviceTizen::StopAndDeAllocate() { @@ -164,6 +166,91 @@ void VideoCaptureDeviceTizen::StopAndDeAllocate() { worker_.Stop(); } +void VideoCaptureDeviceTizen::OnGetPhotoState(GetPhotoStateCallback callback) { + DCHECK(worker_.task_runner()->BelongsToCurrentThread()); + + mojom::PhotoStatePtr photo_capabilities = mojo::CreateEmptyPhotoState(); + + photo_capabilities->iso = camera_instance_->capabilities_->GetIso(); + photo_capabilities->height = + camera_instance_->capabilities_->GetImageHeight(); + photo_capabilities->width = camera_instance_->capabilities_->GetImageWidth(); + photo_capabilities->zoom = camera_instance_->capabilities_->GetZoom(); + photo_capabilities->current_focus_mode = + camera_instance_->capabilities_->GetFocusMode(); + photo_capabilities->current_exposure_mode = + camera_instance_->capabilities_->GetExposureMode(); + photo_capabilities->exposure_compensation = + camera_instance_->capabilities_->GetExposureCompensation(); + photo_capabilities->current_white_balance_mode = + camera_instance_->capabilities_->GetWhiteBalanceMode(); + photo_capabilities->red_eye_reduction = + camera_instance_->capabilities_->GetRedEyeReduction(); + photo_capabilities->color_temperature = + camera_instance_->capabilities_->GetColorTemperature(); + photo_capabilities->brightness = + camera_instance_->capabilities_->GetBrightness(); + photo_capabilities->contrast = camera_instance_->capabilities_->GetContrast(); + photo_capabilities->saturation = + camera_instance_->capabilities_->GetSaturation(); + photo_capabilities->sharpness = + camera_instance_->capabilities_->GetSharpness(); + std::move(callback).Run(std::move(photo_capabilities)); +} + +void VideoCaptureDeviceTizen::TakePhoto(TakePhotoCallback callback) { + int err = 0; + if (CAMERA_ERROR_NONE != (err = camera_instance_->CameraSetCaptureFormat( + CAMERA_PIXEL_FORMAT_JPEG))) { + SetErrorState(GetErrorString(err), FROM_HERE); + return; + } + + std::unique_ptr heap_callback( + new TakePhotoCallback(std::move(callback))); + + if (CAMERA_ERROR_NONE != + (err = camera_instance_->CameraStartCapture( + VideoCaptureDeviceTizen::CapturedCb, + VideoCaptureDeviceTizen::CaptureCompletedCb, this))) { + SetErrorState(GetErrorString(err), FROM_HERE); + return; + } + photo_callbacks_.push_back(std::move(heap_callback)); +} + +void VideoCaptureDeviceTizen::SetPhotoOptions( + mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) { + DCHECK(worker_.IsRunning()); + worker_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::OnSetPhotoOptions, + base::Unretained(this), std::move(settings), + std::move(callback))); +} + +void VideoCaptureDeviceTizen::OnSetPhotoOptions( + mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) { + DCHECK(worker_.task_runner()->BelongsToCurrentThread()); + + if (SetCameraZoom(settings) && SetCameraResolution(settings) && + SetCameraExposure(settings) && SetCameraBrightness(settings) && + SetCameraContrast(settings) && SetCameraIso(settings)) { + std::move(callback).Run(true); + } else { + LOG(ERROR) << "Fail to set camera properties."; + std::move(callback).Run(false); + } +} + +void VideoCaptureDeviceTizen::GetPhotoState(GetPhotoStateCallback callback) { + DCHECK(worker_.IsRunning()); + worker_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::OnGetPhotoState, + base::Unretained(this), std::move(callback))); +} + camera_device_e VideoCaptureDeviceTizen::DeviceNameToCameraId( const VideoCaptureDeviceDescriptor& device_descriptor) { if (device_descriptor.device_id.compare("0") == 0) { @@ -215,19 +302,15 @@ void VideoCaptureDeviceTizen::PreviewCameraCaptured(ScopedMediaPacket pkt) { format.reset(fmt); media_format_mimetype_e mime; - int width, height, avg_bps, max_bps; + int width, height, avg_bps, max_bps, orientation; media_format_get_video_info(format.get(), &mime, &width, &height, &avg_bps, &max_bps); - CHECK((mime == MEDIA_FORMAT_I420) || (mime == MEDIA_FORMAT_NV12)); - - camera_attr_fps_e current_fps = - static_cast(kTypicalFramerate); - camera_attr_get_preview_fps(camera_, ¤t_fps); + CHECK((mime == MEDIA_FORMAT_I420) || (mime == MEDIA_FORMAT_NV12) || + (mime == MEDIA_FORMAT_H264_SP)); - int orientation = + orientation = display::Screen::GetScreen()->GetPrimaryDisplay().RotationAsDegree(); - gfx::Size target_resolution(width, height); int target_rotation = @@ -240,8 +323,10 @@ void VideoCaptureDeviceTizen::PreviewCameraCaptured(ScopedMediaPacket pkt) { media::VideoCaptureFormat videocaptureformat; videocaptureformat.frame_size = gfx::Size(width, height); - videocaptureformat.frame_rate = static_cast(current_fps); - videocaptureformat.pixel_format = media::PIXEL_FORMAT_I420; + videocaptureformat.frame_rate = frame_rate_; + videocaptureformat.pixel_format = + (mime == MEDIA_FORMAT_H264_SP ? media::PIXEL_FORMAT_ENCODED + : media::PIXEL_FORMAT_I420); int dest_width = width; int dest_height = height; @@ -329,16 +414,14 @@ void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, VideoCaptureDeviceTizen* self = static_cast(data); if (!self->client_) return; - camera_attr_fps_e current_fps = - static_cast(kTypicalFramerate); - camera_attr_get_preview_fps(self->camera_, ¤t_fps); - DVLOG(3) << " width:" << frame->width << " height:" << frame->height; - - const display::Display display = - display::Screen::GetScreen()->GetPrimaryDisplay(); + int orientation = DEGREE_0; + display::Screen* screen = display::Screen::GetScreen(); + if (screen) { + display::Display Display = screen->GetPrimaryDisplay(); + orientation = Display.RotationAsDegree(); + } - int orientation = display.RotationAsDegree(); gfx::Size target_resolution(frame->width, frame->height); int target_rotation = (orientation + @@ -350,7 +433,7 @@ void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, media::VideoCaptureFormat videocaptureformat; videocaptureformat.frame_size = gfx::Size(frame->width, frame->height); - videocaptureformat.frame_rate = static_cast(current_fps); + videocaptureformat.frame_rate = self->frame_rate_; videocaptureformat.pixel_format = media::PIXEL_FORMAT_I420; int dest_width = frame->width; @@ -415,64 +498,132 @@ void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, now - self->first_ref_time_); } +bool VideoCaptureDeviceTizen::SetCameraZoom( + const mojom::PhotoSettingsPtr& settings) { + if (settings->has_zoom) + return camera_instance_->SetZoom(settings->zoom); + return true; +} + +bool VideoCaptureDeviceTizen::SetCameraResolution( + const mojom::PhotoSettingsPtr& settings) { + const size_t DEFAULT_WIDTH = 640; + const size_t DEFAULT_HEIGHT = 480; + const int width = settings->has_width ? settings->width : DEFAULT_WIDTH; + const int height = settings->has_height ? settings->height : DEFAULT_HEIGHT; + return camera_instance_->SetResolution(width, height); +} + +bool VideoCaptureDeviceTizen::SetCameraExposure( + const mojom::PhotoSettingsPtr& settings) { + if (settings->has_exposure_compensation) + return camera_instance_->SetExposure(settings->exposure_compensation); + return true; +} + +bool VideoCaptureDeviceTizen::SetCameraBrightness( + const mojom::PhotoSettingsPtr& settings) { + if (settings->has_brightness) + return camera_instance_->SetBrightness(settings->brightness); + return true; +} + +bool VideoCaptureDeviceTizen::SetCameraContrast( + const mojom::PhotoSettingsPtr& settings) { + if (settings->has_contrast) + return camera_instance_->SetContrast(settings->contrast); + return true; +} + +bool VideoCaptureDeviceTizen::SetCameraIso( + const mojom::PhotoSettingsPtr& settings) { + if (settings->has_iso) + return camera_instance_->SetIso(settings->iso); + return true; +} + +VideoPixelFormat VideoCaptureDeviceTizen::ReselectCameraPreviewFormat( + const std::vector& support_formats) { + if (std::find(support_formats.begin(), support_formats.end(), + PIXEL_FORMAT_ENCODED) != support_formats.end()) + return PIXEL_FORMAT_ENCODED; + else if (std::find(support_formats.begin(), support_formats.end(), + PIXEL_FORMAT_MJPEG) != support_formats.end()) + return PIXEL_FORMAT_MJPEG; + + if (support_formats.size()) + return support_formats[0]; + + return PIXEL_FORMAT_UNKNOWN; +} + void VideoCaptureDeviceTizen::OnAllocateAndStart( int width, int height, int frame_rate, VideoPixelFormat format, + bool lazy_start, std::unique_ptr client) { - DVLOG(3) << " width:" << width << " height:" << height - << " frame_rate:" << frame_rate - << " format:" << media::VideoPixelFormatToString(format).c_str(); + LOG(INFO) << " width:" << width << " height:" << height + << " frame_rate:" << frame_rate + << " format:" << media::VideoPixelFormatToString(format).c_str() + << " lazy_start:" << lazy_start; DCHECK(worker_.task_runner()->BelongsToCurrentThread()); client_ = std::move(client); + format_ = format; - CameraHandle* camera_instance = CameraHandle::GetInstance(); - if (camera_instance == nullptr) { + camera_instance_ = CameraHandle::GetInstance(); + if (camera_instance_ == nullptr) { SetErrorState("Failed to get camera instance", FROM_HERE); return; } - if (camera_instance->GetDeviceName() != + if (camera_instance_->GetDeviceName() != DeviceNameToCameraId(device_descriptor_)) { - camera_instance->ResetHandle(DeviceNameToCameraId(device_descriptor_)); + camera_instance_->ResetHandle(DeviceNameToCameraId(device_descriptor_)); } - camera_instance->SetClient(this); - camera_ = camera_instance->GetCameraHandle(); - if (camera_ == nullptr) { - SetErrorState("Camera creation failed", FROM_HERE); + camera_instance_->SetClient(this); + if (!camera_instance_->IsValid()) { + SetErrorState("Camera handle is invalid", FROM_HERE); return; } - int err = camera_set_display(camera_, CAMERA_DISPLAY_TYPE_NONE, nullptr); + int err = + camera_instance_->CameraSetDisplay(CAMERA_DISPLAY_TYPE_NONE, nullptr); if (CAMERA_ERROR_NONE != err) { SetErrorState(GetErrorString(err), FROM_HERE); return; } - err = camera_set_preview_format(camera_, toCapiType(format)); + err = camera_instance_->CameraSetPreviewFormat(ToCapiType(format)); if (CAMERA_ERROR_NONE != err) { - LOG(ERROR) << "camera_set_preview_format failed. Error# " + LOG(ERROR) << "camera_set_preview_format (" << format << ") failed. Error# " << GetErrorString(err); std::vector supported_formats; - if (!camera_instance->GetSupportedPreviewPixelFormats(supported_formats)) { - SetErrorState("Camera internal error", FROM_HERE); + if (!camera_instance_->GetSupportedPreviewPixelFormats(supported_formats)) { + SetErrorState( + "Camera internal error: GetSupportedPreviewPixelFormats Failed", + FROM_HERE); return; } - LOG(ERROR) << "Trying with format (" << supported_formats[0] << ")"; - err = camera_set_preview_format(camera_, toCapiType(supported_formats[0])); + VideoPixelFormat reselected_format = + ReselectCameraPreviewFormat(supported_formats); + + LOG(ERROR) << "Trying with format (" << reselected_format << ")"; + err = + camera_instance_->CameraSetPreviewFormat(ToCapiType(reselected_format)); if (CAMERA_ERROR_NONE != err) { SetErrorState(GetErrorString(err), FROM_HERE); return; } } - err = camera_set_preview_resolution(camera_, width, height); + err = camera_instance_->CameraSetPreviewResolution(width, height); if (CAMERA_ERROR_NONE != err) { LOG(ERROR) << "camera_set_preview_resolution failed. Error#" << err << ". Trying default resolution: " << kMjpegWidth << " x " @@ -480,77 +631,78 @@ void VideoCaptureDeviceTizen::OnAllocateAndStart( width = kMjpegWidth; height = kMjpegHeight; - err = camera_set_preview_resolution(camera_, width, height); + err = camera_instance_->CameraSetPreviewResolution(width, height); if (CAMERA_ERROR_NONE != err) { SetErrorState(GetErrorString(err), FROM_HERE); return; } } - if (use_media_packet_) { - err = camera_set_media_packet_preview_cb( - camera_, OnCameraCapturedWithMediaPacket, this); - if (CAMERA_ERROR_NONE != err) { - SetErrorState(GetErrorString(err), FROM_HERE); - return; - } - } else { - err = camera_set_preview_cb(camera_, OnCameraCaptured, this); + err = camera_instance_->CameraSetMediapacketPreviewCb( + OnCameraCapturedWithMediaPacket, this); + if (CAMERA_ERROR_NONE == err) + use_media_packet_ = true; + else { + err = camera_instance_->CameraSetPreviewCb(OnCameraCaptured, this); if (CAMERA_ERROR_NONE != err) { SetErrorState(GetErrorString(err), FROM_HERE); return; } + use_media_packet_ = false; } - err = camera_attr_set_preview_fps(camera_, - static_cast(frame_rate)); + frame_rate_ = frame_rate; + err = camera_instance_->CameraSetPreviewFps( + static_cast(frame_rate)); if (CAMERA_ERROR_NONE != err) { - LOG(ERROR) << "camera_attr_set_preview_fps failed. Error# " << err; + LOG(ERROR) << "cameraSetPreviewFps failed. Error# " << err; - int max_supported_fps = camera_instance->GetMaxFrameRate( + int max_supported_fps = camera_instance_->GetMaxFrameRate( CameraCapability::Resolution(width, height)); if (!max_supported_fps) { - SetErrorState("Camera internal error", FROM_HERE); + SetErrorState("Camera internal error : GetMaxFrameRate Failed", + FROM_HERE); return; } - err = camera_attr_set_preview_fps( - camera_, static_cast(max_supported_fps)); + frame_rate_ = max_supported_fps; + + err = camera_instance_->CameraSetPreviewFps( + static_cast(max_supported_fps)); if (CAMERA_ERROR_NONE != err) { SetErrorState(GetErrorString(err), FROM_HERE); return; } } - if (IsMobileProfile() && - (camera_instance->GetDeviceName() == CAMERA_DEVICE_CAMERA1)) { - err = camera_attr_set_stream_flip(camera_, CAMERA_FLIP_VERTICAL); + if (IsMobileProfile() && !IsEmulatorArch() && + (camera_instance_->GetDeviceName() == CAMERA_DEVICE_CAMERA1)) { + err = camera_instance_->CameraSetStreamFlip(CAMERA_FLIP_VERTICAL); if (CAMERA_ERROR_NONE != err) { SetErrorState(GetErrorString(err), FROM_HERE); return; } } - state_ = kCapturing; - - err = camera_start_preview(camera_); - if (CAMERA_ERROR_NONE != err) { - SetErrorState(GetErrorString(err), FROM_HERE); - return; + state_ = kAllocated; + if (!lazy_start) { + if (!StartPreview()) { + LOG(ERROR) << "StartPreview failed!!!"; + return; + } } - if (IsMobileProfile()) - WakeUpDisplayAndAcquireDisplayLock(); + client_->OnStarted(); } void VideoCaptureDeviceTizen::OnStopAndDeAllocate() { DCHECK(worker_.task_runner()->BelongsToCurrentThread()); if (use_media_packet_) - camera_unset_media_packet_preview_cb(camera_); + camera_instance_->CameraUnsetMediapacketPreviewCb(); else - camera_unset_preview_cb(camera_); - camera_stop_preview(camera_); + camera_instance_->CameraUnsetPreviewCb(); + camera_instance_->CameraStopPreview(); if (IsMobileProfile()) ReleaseDisplayLock(); @@ -596,4 +748,79 @@ void VideoCaptureDeviceTizen::SetErrorState(const char* error, error); } +void VideoCaptureDeviceTizen::CapturedCb(camera_image_data_s* image, + camera_image_data_s* postview, + camera_image_data_s* thumbnail, + void* userData) { + LOG(INFO) << "CapturedCb!"; + VideoCaptureDeviceTizen* handle = + static_cast(userData); + + if (handle->photo_callbacks_.empty()) + return; + + mojom::BlobPtr blob = mojom::Blob::New(); + blob->data.resize(image->size); + memcpy(blob->data.data(), image->data, image->size); + + if (blob) { + TakePhotoCallback cb = std::move(*(handle->photo_callbacks_.front().get())); + handle->photo_callbacks_.pop_front(); + std::move(cb).Run(std::move(blob)); + } +} + +void VideoCaptureDeviceTizen::CaptureCompletedCb(void* userData) { + LOG(INFO) << "Capture Completed!"; + VideoCaptureDeviceTizen* handle = + static_cast(userData); + + handle->worker_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::OnCaptureCompletedCb, + base::Unretained(handle))); +} + +void VideoCaptureDeviceTizen::OnCaptureCompletedCb() { + if (!camera_instance_) { + SetErrorState("Failed to get camera instance!", FROM_HERE); + return; + } + + int err = 0; + if (CAMERA_ERROR_NONE != (err = camera_instance_->CameraStartPreview())) { + SetErrorState(GetErrorString(err), FROM_HERE); + return; + } +} + +bool VideoCaptureDeviceTizen::StartPreview() { + if (state_ != kAllocated) + return false; + + LOG(INFO) << "VideoCaptureDeviceTizen::StartPreview()"; + state_ = kCapturing; + + int err = camera_instance_->CameraStartPreview(); + if (CAMERA_ERROR_NONE != err) { + SetErrorState(GetErrorString(err), FROM_HERE); + return false; + } + + if (IsMobileProfile() || IsWearableProfile()) + WakeUpDisplayAndAcquireDisplayLock(); + + return true; +} + +void VideoCaptureDeviceTizen::StopPreview() { + if (state_ != kCapturing) + return; + + state_ = kAllocated; + + int err = camera_instance_->CameraStopPreview(); + if (CAMERA_ERROR_NONE != err) + SetErrorState(GetErrorString(err), FROM_HERE); +} + } // namespace media diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h index 9e732e3..9b26e82 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h +++ b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h @@ -34,12 +34,22 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, VideoCaptureDeviceTizen(const VideoCaptureDeviceTizen&) = delete; VideoCaptureDeviceTizen& operator=(const VideoCaptureDeviceTizen&) = delete; + // Implements CameraHandleClient + void OnStreamStopped() override; + + // Implements VideoCaptureDevice void AllocateAndStart(const VideoCaptureParams& params, std::unique_ptr client) override; void StopAndDeAllocate() override; - void OnStreamStopped() override; + bool StartPreview(); + void StopPreview(); + + void GetPhotoState(GetPhotoStateCallback callback) override; + void SetPhotoOptions(mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) override; + void TakePhoto(TakePhotoCallback callback) override; static camera_device_e DeviceNameToCameraId( const VideoCaptureDeviceDescriptor& device_descriptor); @@ -49,10 +59,16 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, static void OnCameraCaptured(camera_preview_data_s* frame, void* data); static const char* GetErrorString(int err_code); + static void CapturedCb(camera_image_data_s* image, + camera_image_data_s* postview, + camera_image_data_s* thumbnail, + void* userData); + static void CaptureCompletedCb(void* userData); private: enum InternalState { kIdle, // The device driver is opened but camera is not in use. + kAllocated, // This device is configured, but preview is not started kCapturing, // Video is being captured. kError // Error accessing HW functions. // User needs to recover by destroying the object. @@ -62,8 +78,8 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, int height, int frame_rate, VideoPixelFormat format, + bool lazy_start, std::unique_ptr client); - void OnStopAndDeAllocate(); // For handling the camera preview callback returning mediapacket bool IsCapturing(); @@ -72,7 +88,23 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, void SetErrorState(const char* reason, const base::Location& location); - camera_h camera_; + void OnStopAndDeAllocate(); + + void OnGetPhotoState(GetPhotoStateCallback callback); + void OnSetPhotoOptions(mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback); + void OnCaptureCompletedCb(); + + bool SetCameraZoom(const mojom::PhotoSettingsPtr& settings); + bool SetCameraResolution(const mojom::PhotoSettingsPtr& settings); + bool SetCameraExposure(const mojom::PhotoSettingsPtr& settings); + bool SetCameraBrightness(const mojom::PhotoSettingsPtr& settings); + bool SetCameraContrast(const mojom::PhotoSettingsPtr& settings); + bool SetCameraIso(const mojom::PhotoSettingsPtr& settings); + VideoPixelFormat ReselectCameraPreviewFormat( + const std::vector& support_formats); + + CameraHandle* camera_instance_; std::unique_ptr client_; VideoCaptureDevice::Client::Buffer buffer_; base::Lock capturing_state_lock_; @@ -85,6 +117,11 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, InternalState state_; base::TimeTicks first_ref_time_; + int frame_rate_{0}; + media::VideoPixelFormat format_{media::PIXEL_FORMAT_UNKNOWN}; + + // List of |photo_callbacks_| in flight. + std::list> photo_callbacks_; }; } // namespace media -- 2.7.4