blob: 10fb71e08257a8f9597847ff739a291ef0088ef5 [file] [log] [blame]
/*
* Copyright (C) 2015-2020 Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "V4l2DeviceFactory"
#include <fcntl.h>
#include "iutils/CameraLog.h"
#include "V4l2DeviceFactory.h"
namespace icamera {
std::map<int, V4l2DeviceFactory*> V4l2DeviceFactory::sInstances;
Mutex V4l2DeviceFactory::sLock;
V4l2DeviceFactory::V4l2DeviceFactory(int cameraId) : mCameraId(cameraId)
{
LOG1("V4l2DeviceFactory created for id:%d", mCameraId);
}
V4l2DeviceFactory::~V4l2DeviceFactory()
{
LOG1("V4l2DeviceFactory released for id:%d", mCameraId);
}
/**
* Create a static instance of V4l2DeviceFactory for cameraId.
* It should be called before any device is used.
*/
void V4l2DeviceFactory::createDeviceFactory(int cameraId)
{
AutoMutex lock(sLock);
getInstance(cameraId);
}
/**
* Release the static instance of V4l2DeviceFactory for cameraId.
* All device related to the instance of of V4l2DeviceFactory will be release here as well
* After calling this function, all device could not be used anymore.
*/
void V4l2DeviceFactory::releaseDeviceFactory(int cameraId)
{
AutoMutex lock(sLock);
V4l2DeviceFactory* factory = getInstance(cameraId);
sInstances.erase(cameraId);
factory->releaseSubDevices(cameraId);
delete factory;
}
/**
* Get an opened sub device
*
* The caller is supposed to get an opened sub device.
* If openSubDev failed, it just return non-opened instance,
* and using this instance to call its funtion will cause 'device not open' error,
*
* Return a not nullptr sub device pointer
*/
V4L2Subdevice* V4l2DeviceFactory::getSubDev(int cameraId, const std::string& devName)
{
AutoMutex lock(sLock);
V4l2DeviceFactory* factory = getInstance(cameraId);
// If an existing sub device found, then just return it.
if (factory->mDevices.find(devName) != factory->mDevices.end()) {
return factory->mDevices[devName];
}
// Create a new sub device for devName, since it's not created before.
V4L2Subdevice* subdev = new V4L2Subdevice(devName);
// Make sure the caller always got an opened device.
subdev->Open(O_RDWR);
// Add the new allocated sub device into device map.
factory->mDevices[devName] = subdev;
return subdev;
}
/**
* Release all sub devices in device map
*
* It's a private function with no lock in it, must be called with lock protection.
*
* It MUST be called after all sub devices are not used anymore
*/
void V4l2DeviceFactory::releaseSubDevices(int /*cameraId*/)
{
for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
V4L2Subdevice* subdev = it->second;
if (subdev) {
subdev->Close();
delete subdev;
}
}
mDevices.clear();
}
/**
* Private function with no lock in it, must be called with lock protection
*/
V4l2DeviceFactory* V4l2DeviceFactory::getInstance(int cameraId)
{
if (sInstances.find(cameraId) != sInstances.end()) {
return sInstances[cameraId];
}
sInstances[cameraId] = new V4l2DeviceFactory(cameraId);
return sInstances[cameraId];
}
} //namespace icamera