#include "media/capture/video/tizen/video_capture_device_factory_tizen_tv.h"
+#include <memory>
+#include <string>
+
#include "base/functional/bind.h"
-#include "base/task/bind_post_task.h"
+#include "base/location.h"
+#include "base/time/time.h"
#include "media/base/tizen/logger/media_logger.h"
#include "media/base/video_types.h"
#include "media/capture/video/tizen/camera_utils.h"
namespace media {
+namespace {
+
+constexpr VideoCaptureError kCameraCreateError = VideoCaptureError::
+ kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested;
+
+} // namespace
+
VideoCaptureDeviceFactoryTizenTv::VideoCaptureDeviceFactoryTizenTv() {
- weak_this_ = weak_factory_.GetWeakPtr();
int err = camera_device_manager_initialize(&handle_);
if (err != CAMERA_ERROR_NONE) {
TIZEN_MEDIA_LOG(ERROR) << "Cannot initialize camera device manager: "
}
VideoCaptureDeviceFactoryTizenTv::~VideoCaptureDeviceFactoryTizenTv() {
- weak_factory_.InvalidateWeakPtrs();
+ base::AutoLock lock(devices_lock_);
+ devices_cache_.clear();
+
if (handle_) {
camera_device_manager_deinitialize(handle_);
}
const VideoCaptureDeviceDescriptor& device_descriptor) {
// Ensure that other thread won't try allocating camera device.
base::AutoLock lock(devices_lock_);
+ auto cached_device_it = devices_cache_.find(device_descriptor);
+ if (cached_device_it != devices_cache_.end()) {
+ TIZEN_MEDIA_LOG(INFO) << "CreateDevice: "
+ << device_descriptor.GetNameAndModel()
+ << " found in cache.";
+ auto device = std::make_unique<VideoCaptureDeviceTizenTv>(
+ std::move(cached_device_it->second.camera));
+ devices_cache_.erase(cached_device_it);
+ return VideoCaptureErrorOrDevice(std::move(device));
+ }
TIZEN_MEDIA_LOG(INFO) << "CreateDevice: "
<< device_descriptor.GetNameAndModel();
int err = camera_device_manager_get_device_list(handle_, &list);
if (err != CAMERA_ERROR_NONE) {
TIZEN_MEDIA_LOG(ERROR) << "Cannot get device list: " << err;
- return VideoCaptureErrorOrDevice(
- VideoCaptureError::
- kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested);
+ return VideoCaptureErrorOrDevice(kCameraCreateError);
}
for (size_t i = 0; i < list.count; ++i) {
}
auto camera = Camera::Create(list.device[i].index, list.device[i].type);
- supported_formats_cache_.emplace(list.device[i].index,
- GetSupportedFormats(camera.get()));
- auto destroy_cb = base::BindPostTaskToCurrentDefault(
- base::BindOnce(&VideoCaptureDeviceFactoryTizenTv::OnDeviceReleased,
- weak_factory_.GetWeakPtr(), list.device[i].index));
+ auto it = supported_formats_cache_.find(device_descriptor);
+ if (it == supported_formats_cache_.end()) {
+ supported_formats_cache_.emplace(device_descriptor,
+ GetSupportedFormats(camera.get()));
+ }
return VideoCaptureErrorOrDevice(
- std::make_unique<VideoCaptureDeviceTizenTv>(std::move(camera),
- std::move(destroy_cb)));
+ std::make_unique<VideoCaptureDeviceTizenTv>(std::move(camera)));
}
TIZEN_MEDIA_LOG(WARNING) << "Requested device not found";
- return VideoCaptureErrorOrDevice(
- VideoCaptureError::
- kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested);
-}
-
-void VideoCaptureDeviceFactoryTizenTv::OnDeviceReleased(
- camera_device_e device) {
- base::AutoLock lock(devices_lock_);
- auto it = supported_formats_cache_.find(device);
- if (it == supported_formats_cache_.end()) {
- TIZEN_MEDIA_LOG(WARNING) << "Cannot find released device";
- return;
- }
- supported_formats_cache_.erase(it);
+ return VideoCaptureErrorOrDevice(kCameraCreateError);
}
std::vector<VideoCaptureDeviceInfo>
for (size_t i = 0; i < list.count; ++i) {
std::string name(list.device[i].name);
std::string id(list.device[i].id);
- TIZEN_MEDIA_LOG(INFO) << "Name " << name << ", type " << list.device[i].type
- << ", index " << list.device[i].index << ", id "
- << id;
-
- VideoCaptureDeviceInfo info(VideoCaptureDeviceDescriptor(name, id));
- info.supported_formats =
- GetSupportedFormats(list.device[i].index, list.device[i].type);
+ TIZEN_MEDIA_LOG(VERBOSE) << "Camera #" << i
+ << ": name " << name
+ << ", type " << list.device[i].type
+ << ", index " << list.device[i].index
+ << ", id " << id;
+
+ VideoCaptureDeviceDescriptor camera_descriptor(name, id);
+ VideoCaptureDeviceInfo info(camera_descriptor);
+ info.supported_formats = GetSupportedFormats(
+ camera_descriptor, list.device[i].index, list.device[i].type);
if (info.supported_formats.empty()) {
continue;
}
}
VideoCaptureFormats VideoCaptureDeviceFactoryTizenTv::GetSupportedFormats(
+ const VideoCaptureDeviceDescriptor& device_descriptor,
camera_device_e index,
camera_device_type_e type) {
// We cannot obtain camera again if it's already allocated, so
// get cached formats.
- auto cache_it = supported_formats_cache_.find(index);
+ auto cache_it = supported_formats_cache_.find(device_descriptor);
if (cache_it != supported_formats_cache_.end()) {
return cache_it->second;
}
TIZEN_MEDIA_LOG(INFO) << "Cannot create camera, skip that one.";
return {};
}
- return GetSupportedFormats(camera.get());
+ auto supported_formats = GetSupportedFormats(camera.get());
+ supported_formats_cache_.emplace(device_descriptor, supported_formats);
+
+ auto retain_timer = std::make_unique<base::OneShotTimer>();
+ retain_timer->Start(
+ FROM_HERE, base::Seconds(2),
+ base::BindOnce(&VideoCaptureDeviceFactoryTizenTv::ReleaseCachedDevice,
+ base::Unretained(this), device_descriptor));
+ devices_cache_[device_descriptor].camera = std::move(camera);
+ devices_cache_[device_descriptor].retain_timer = std::move(retain_timer);
+ return supported_formats;
+}
+
+void VideoCaptureDeviceFactoryTizenTv::ReleaseCachedDevice(
+ const VideoCaptureDeviceDescriptor& device_descriptor) {
+ base::AutoLock lock(devices_lock_);
+ devices_cache_.erase(device_descriptor);
}
void VideoCaptureDeviceFactoryTizenTv::GetDevicesInfo(
#ifndef MEDIA_CAPTURE_VIDEO_TIZEN_VIDEO_CAPTURE_DEVICE_FACTORY_TIZEN_TV_H_
#define MEDIA_CAPTURE_VIDEO_TIZEN_VIDEO_CAPTURE_DEVICE_FACTORY_TIZEN_TV_H_
-#include <map>
-
#include <media/camera.h>
#include <media/camera_internal.h>
-#include "base/memory/weak_ptr.h"
+#include <map>
+
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
-#include "base/threading/thread.h"
+#include "base/timer/timer.h"
#include "media/capture/video/tizen/camera.h"
#include "media/capture/video/video_capture_device_factory.h"
VideoCaptureDeviceFactory::GetDevicesInfoCallback callback) override;
private:
+ struct CameraDeviceHolder {
+ std::unique_ptr<Camera> camera;
+ std::unique_ptr<base::OneShotTimer> retain_timer;
+ };
+
std::vector<VideoCaptureDeviceInfo> GetDevices();
- VideoCaptureFormats GetSupportedFormats(camera_device_e index,
- camera_device_type_e type)
- EXCLUSIVE_LOCKS_REQUIRED(devices_lock_);
+ VideoCaptureFormats GetSupportedFormats(
+ const VideoCaptureDeviceDescriptor& device_descriptor,
+ camera_device_e index,
+ camera_device_type_e type) EXCLUSIVE_LOCKS_REQUIRED(devices_lock_);
VideoCaptureFormats GetSupportedFormats(Camera* camera);
-
- void OnDeviceReleased(camera_device_e device);
+ void ReleaseCachedDevice(
+ const VideoCaptureDeviceDescriptor& device_descriptor);
camera_device_manager_h handle_ = nullptr;
base::Lock devices_lock_;
- std::unordered_map<camera_device_e, VideoCaptureFormats>
+ std::map<VideoCaptureDeviceDescriptor, VideoCaptureFormats>
supported_formats_cache_ GUARDED_BY(devices_lock_);
-
- base::WeakPtrFactory<VideoCaptureDeviceFactoryTizenTv> weak_factory_{this};
- base::WeakPtr<VideoCaptureDeviceFactoryTizenTv> weak_this_;
+ std::map<VideoCaptureDeviceDescriptor, CameraDeviceHolder>
+ devices_cache_ GUARDED_BY(devices_lock_);
};
} // namespace media