Files
2026-08-24 10:03:24 +08:00

188 lines
5.6 KiB
C++

/*
* Copyright (C) 2022 Amlogic 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_NDEBUG 0
#define LOG_TAG "ScreenCapture"
#include "Log.h"
#include "ScreenCapture.h"
static int saveBufferAsFile(void *buffer, size_t size, char *file)
{
int fd = open(file, O_CREAT|O_RDWR, 0666);
int wrSize = 0;
int ret = 0;
if (fd < 0) {
return fd;
}
do {
int ret = write (fd, (char *)buffer + wrSize, size - wrSize);
if (ret > 0) {
wrSize += ret;
} else {
break;
}
} while (wrSize < size);
close(fd);
return ret;
}
static void checkAndSaveBufferToFile(const char *baseFile, char *filename, void *buffer, size_t size)
{
if (0 == access(baseFile, F_OK)) {
if (saveBufferAsFile(buffer, size, filename) >= 0) {
ALOGD("Save file ok: %s", filename);
} else {
ALOGW("Save file fail: %s!", filename);
}
}
}
static int getBufferSize(int width, int height, aml_capture_data_type data_type) {
int buf_size = 0;
switch (data_type) {
case SCREENCONTROL_FMT_NV21:
case SCREENCONTROL_FMT_NV12:
{
buf_size = width * height * 3 / 2;
break;
}
case SCREENCONTROL_FMT_RGB565:
buf_size = width * height * 2;
break;
case SCREENCONTROL_FMT_RGB24:
buf_size = width * height * 3;
break;
case SCREENCONTROL_FMT_ARGB888:
case SCREENCONTROL_FMT_ABGR888:
buf_size = width * height * 4;
break;
default:
ALOGD("[%s %d] Invalid format",__FUNCTION__, __LINE__);
buf_size = width * height * 3 / 2;
}
return buf_size;
}
static void VdinDataCallBack(void *user, aml_screen_buffer_info_t *buffer){
ScreenCapture *source = static_cast<ScreenCapture *>(user);
source->dataCallBack(buffer);
return;
}
ScreenCapture::ScreenCapture()
:source_(std::make_unique<vdin_screen_source>()),
width_(0),
height_(0),
buffer_size_(0),
frame_rate_(0),
data_type_(SCREENCONTROL_UNKNOWN_TYPE),
port_type_(PORTTYPE_VALUE_VIDEO_OSD_main_screen),
started_(false) {
}
ScreenCapture::~ScreenCapture() {
}
bool ScreenCapture::init(ScreenCapture_Params *params)
{
std::lock_guard<std::mutex> lock(mutex_);
ALOGD("[%s %d] width=%d ,height=%d,framerate=%d,data_type=%d,params->port_type=%d",
__FUNCTION__, __LINE__,params->width,params->height,params->framerate,params->data_type,params->port_type);
width_ = params->width;
height_ = params->height;
frame_rate_ = params->framerate;
data_type_ = params->data_type;
port_type_ = params->port_type;
buffer_size_ = getBufferSize(width_,height_,data_type_);
return true;
}
bool ScreenCapture::start()
{
if (source_->init() != 0)
return false;
if (source_->set_port_type(port_type_) != 0)
return false;
if (source_->set_frame_rate(frame_rate_) != 0)
return false;
int format = 0;
if (data_type_ == SCREENCONTROL_FMT_NV21) {
format = V4L2_PIX_FMT_NV21;
}else if (data_type_ == SCREENCONTROL_FMT_NV12) {
format = V4L2_PIX_FMT_NV12;
}else if (data_type_ == SCREENCONTROL_FMT_ARGB888) {
format = V4L2_PIX_FMT_RGB32;
}else if (data_type_ == SCREENCONTROL_FMT_ABGR888) {
format = V4L2_PIX_FMT_BGR32;
}else if (data_type_ == SCREENCONTROL_FMT_RGB565) {
format = V4L2_PIX_FMT_RGB565;
}else if (data_type_ == SCREENCONTROL_FMT_RGB24 ) {
format = V4L2_PIX_FMT_RGB24;
}else {
ALOGD("[%s %d] Invalid data_type",__FUNCTION__, __LINE__);
return false;
}
source_->set_format(width_,height_,format);
if (source_->set_data_callback(VdinDataCallBack,(void*) this) != 0)
return false;
if (source_->start() != 0)
return false;
started_ = true;
ALOGD("[%s %d] finish!",__FUNCTION__, __LINE__);
return true;
}
bool ScreenCapture::stop()
{
std::lock_guard<std::mutex> lock(mutex_);
ALOGD("[%s %d] begin",__FUNCTION__, __LINE__);
started_ = false;
source_->stop();
ALOGD("[%s %d] over",__FUNCTION__, __LINE__);
return true;
}
bool ScreenCapture::readBuffer(void *data)
{
std::lock_guard<std::mutex> lock(mutex_);
if (started_ && !buffer_list_.empty()) {
std::unique_ptr<uint8_t[]> buffer = std::move(buffer_list_.front());
buffer_list_.pop_front();
if (buffer != nullptr && data != nullptr) {
memcpy(data, buffer.get(), buffer_size_);
return true;
}else {
ALOGD("[%s %d] buffer or data invalid",__FUNCTION__, __LINE__);
}
}
return false;
}
void ScreenCapture::dataCallBack(aml_screen_buffer_info_t *data) {
std::lock_guard<std::mutex> lock(mutex_);
ALOGD("[%s %d] started_:%d",__FUNCTION__, __LINE__, started_);
if (started_) {
auto buffer = std::make_unique<uint8_t[]>(buffer_size_);
memcpy(buffer.get(), data->buffer_mem, buffer_size_);
buffer_list_.push_back(std::move(buffer));
source_->release_buffer(data->buffer_mem);
}
}