/*
|
* Copyright (c) 2021 by Allwinnertech Co., Ltd.
|
*
|
* 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 "CameraHALv3_V4L2Wrapper"
|
#include "v4l2_wrapper.h"
|
|
#include <android-base/unique_fd.h>
|
#include <fcntl.h>
|
#include <string.h>
|
#include <sys/stat.h>
|
#include <sys/types.h>
|
|
#include <algorithm>
|
#include <array>
|
#include <limits>
|
#include <mutex>
|
#include <vector>
|
|
#include "linux/videodev2.h"
|
#include "stream_format.h"
|
#include "type_camera.h"
|
#include "v4l2_log.h"
|
#include "v4l2_stream.h"
|
#include GPU_PUBLIC_INCLUDE
|
|
namespace v4l2_camera_hal {
|
|
V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(
|
const int id,
|
std::shared_ptr<CCameraConfig> pCameraCfg) {
|
HAL_LOG_ENTER();
|
return new V4L2Wrapper(id, pCameraCfg);
|
}
|
|
std::shared_ptr<V4L2Stream> V4L2Wrapper::getStream(STREAM_SERIAL ss) {
|
HAL_LOG_ENTER();
|
std::lock_guard<std::mutex> lock(connection_lock_);
|
STREAM_SERIAL tmpss = MAIN_STREAM;
|
switch (ss) {
|
case MAIN_STREAM:
|
case MAIN_STREAM_BLOB:
|
case MAIN_MIRROR_STREAM:
|
case MAIN_MIRROR_STREAM_BLOB:
|
tmpss = MAIN_STREAM;
|
break;
|
case SUB_0_STREAM:
|
case SUB_0_STREAM_BLOB:
|
case SUB_0_MIRROR_STREAM:
|
case SUB_0_MIRROR_STREAM_BLOB:
|
tmpss = SUB_0_STREAM;
|
break;
|
default:
|
HAL_LOGE("Failed to set stream device_path.");
|
break;
|
}
|
|
if (array_stream_obj[tmpss] == nullptr) {
|
HAL_LOGE("Failed to find stream obj, you should connect device first.");
|
return nullptr;
|
}
|
HAL_LOGV("getStream %d successfully.", tmpss);
|
return array_stream_obj[tmpss];
|
}
|
|
V4L2Wrapper::V4L2Wrapper(const int id,
|
std::shared_ptr<CCameraConfig> pCameraCfg)
|
: mCameraConfig(pCameraCfg),
|
device_id_(id),
|
has_StreamOn(false),
|
buffer_state_(BUFFER_UNINIT),
|
#ifdef USE_ISP
|
mAWIspApi(NULL),
|
mIspId(-1),
|
#endif
|
isTakePicure(false) {
|
HAL_LOG_ENTER();
|
for (int ss = 0; ss < MAX_STREAM; ss++) {
|
connection_count_[ss] = 0;
|
}
|
}
|
|
V4L2Wrapper::~V4L2Wrapper() {}
|
|
int V4L2Wrapper::Connect(STREAM_SERIAL ss, int merge_status) {
|
HAL_LOG_ENTER();
|
std::lock_guard<std::mutex> lock(connection_lock_);
|
std::string device_path;
|
STREAM_SERIAL tmpss = MAIN_STREAM;
|
int Support_Id = getSupportCameraId(device_id_);
|
HAL_LOGD("device_id:%d Support_Id:%d", device_id_, Support_Id);
|
switch (ss) {
|
case MAIN_STREAM:
|
case MAIN_STREAM_BLOB:
|
case MAIN_MIRROR_STREAM:
|
case MAIN_MIRROR_STREAM_BLOB:
|
if (device_id_ == 0 && merge_status) {
|
device_path = MAIN_MERGE_STREAM_PATH;
|
} else if (device_id_ == 0 && merge_status == 0) {
|
device_path = MAIN_STREAM_PATH;
|
}
|
tmpss = MAIN_STREAM;
|
break;
|
case SUB_0_STREAM:
|
case SUB_0_STREAM_BLOB:
|
case SUB_0_MIRROR_STREAM:
|
case SUB_0_MIRROR_STREAM_BLOB:
|
if (device_id_ == 0 && merge_status) {
|
device_path = SUB_0_MERGE_STREAM_PATH;
|
} else if (device_id_ == 0 && merge_status == 0) {
|
device_path = SUB_0_STREAM_PATH;
|
}
|
tmpss = SUB_0_STREAM;
|
break;
|
default:
|
HAL_LOGE("Failed to set stream device_path.");
|
break;
|
}
|
|
if (connected(tmpss)) {
|
HAL_LOGD("Camera stream %s is already connected.", device_path_.c_str());
|
++connection_count_[tmpss];
|
return 0;
|
}
|
|
if (Support_Id == 1 && tmpss == MAIN_STREAM) {
|
device_path = MAIN_FRONT_STREAM_PATH;
|
}
|
if (Support_Id == 1 && tmpss == SUB_0_STREAM) {
|
device_path = SUB_0_FRONT_STREAM_PATH;
|
}
|
|
std::shared_ptr<V4L2Stream> stream(V4L2Stream::NewV4L2Stream(device_id_,
|
device_path,
|
mCameraConfig,
|
merge_status
|
));
|
if (!stream) {
|
HAL_LOGE("Failed to initialize stream helper.");
|
return -1;
|
}
|
|
stream_connection[tmpss].reset(new ConnectionStream(stream, merge_status));
|
if (stream_connection[tmpss]->status()) {
|
HAL_LOGE("Failed to connect to device: %d.",
|
stream_connection[tmpss]->status());
|
return stream_connection[tmpss]->status();
|
}
|
array_stream_obj[tmpss] = stream;
|
++connection_count_[tmpss];
|
return 0;
|
}
|
|
void V4L2Wrapper::Disconnect(STREAM_SERIAL ss) {
|
HAL_LOG_ENTER();
|
std::lock_guard<std::mutex> lock(connection_lock_);
|
std::string device_path;
|
STREAM_SERIAL tmpss = MAIN_STREAM;
|
switch (ss) {
|
case MAIN_STREAM:
|
case MAIN_STREAM_BLOB:
|
case MAIN_MIRROR_STREAM:
|
case MAIN_MIRROR_STREAM_BLOB:
|
//if (device_id_ == 0) {
|
// device_path = MAIN_STREAM_PATH;
|
//}
|
tmpss = MAIN_STREAM;
|
break;
|
case SUB_0_STREAM:
|
case SUB_0_STREAM_BLOB:
|
case SUB_0_MIRROR_STREAM:
|
case SUB_0_MIRROR_STREAM_BLOB:
|
//if (device_id_ == 0) {
|
// device_path = SUB_0_STREAM_PATH;
|
//}
|
tmpss = SUB_0_STREAM;
|
break;
|
default:
|
HAL_LOGE("Failed to set stream device_path.");
|
break;
|
}
|
|
if (connection_count_[tmpss] == 0) {
|
// Not connected.
|
HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
|
device_path_.c_str());
|
return;
|
}
|
|
//if (device_id_ == 1 && tmpss == MAIN_STREAM) {
|
// device_path = MAIN_FRONT_STREAM_PATH;
|
//}
|
//if (device_id_ == 1 && tmpss == SUB_0_STREAM) {
|
// device_path = SUB_0_FRONT_STREAM_PATH;
|
//}
|
|
--connection_count_[tmpss];
|
if (connection_count_[tmpss] > 0) {
|
HAL_LOGV("Disconnected from camera device %s connections remain.",
|
device_path_.c_str());
|
return;
|
}
|
stream_connection[tmpss].reset();
|
array_stream_obj[tmpss].reset();
|
|
device_fd_[MAIN_STREAM].reset(-1); // Includes close().
|
format_.reset();
|
buffers_.clear();
|
}
|
|
} // namespace v4l2_camera_hal
|