From 44e4c5efe06a912fdc2dde234e05f8db62b535ac Mon Sep 17 00:00:00 2001 From: MistEO Date: Fri, 14 Jan 2022 19:59:45 +0800 Subject: [PATCH] =?UTF-8?q?fix.=E9=87=8D=E6=9E=84=E5=B9=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=88=AA=E5=9B=BE=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resource/config.json | 28 +++--- src/MeoAssistant/AsstDef.h | 20 ++++- src/MeoAssistant/Controller.cpp | 128 +++++++++++++++++++-------- src/MeoAssistant/Controller.h | 3 +- src/MeoAssistant/GeneralConfiger.cpp | 4 +- 5 files changed, 125 insertions(+), 58 deletions(-) diff --git a/resource/config.json b/resource/config.json index 03338300bc..8ff486f960 100644 --- a/resource/config.json +++ b/resource/config.json @@ -40,8 +40,8 @@ "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", "displayFormat": "cur=%dx%d", - "screencap": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", - "screencapGzip": true, + "screencapRawWithGzip": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", + "screencapEncode": "[Adb] -s [Address] exec-out screencap -p", "release": "[Adb] kill-server" } }, @@ -62,8 +62,8 @@ "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", "displayFormat": "cur=%dx%d", - "screencap": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", - "screencapGzip": true, + "screencapRawWithGzip": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", + "screencapEncode": "[Adb] -s [Address] exec-out screencap -p", "release": "[Adb] kill-server" } }, @@ -84,8 +84,8 @@ "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", "displayFormat": "cur=%dx%d", - "screencap": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", - "screencapGzip": true, + "screencapRawWithGzip": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", + "screencapEncode": "[Adb] -s [Address] exec-out screencap -p", "release": "[Adb] kill-server" } }, @@ -107,8 +107,8 @@ "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", "displayFormat": "cur=%dx%d", - "screencap": "[Adb] -s [Address] shell \"screencap | gzip -1\"", - "screencapGzip": true, + "screencapRawWithGzip": "[Adb] -s [Address] shell \"screencap | gzip -1\"", + "screencapEncode": "[Adb] -s [Address] shell screencap -p", "release": "[Adb] kill-server" } }, @@ -130,8 +130,8 @@ "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", "displayFormat": "cur=%dx%d", - "screencap": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", - "screencapGzip": true, + "screencapRawWithGzip": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", + "screencapEncode": "[Adb] -s [Address] exec-out screencap -p", "release": "[Adb] kill-server" } }, @@ -152,8 +152,8 @@ "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init=", "displayFormat": " init=%dx%d", - "screencap": "[Adb] -s [Address] shell \"screencap | gzip -1\"", - "screencapGzip": true, + "screencapRawWithGzip": "[Adb] -s [Address] shell \"screencap | gzip -1\"", + "screencapEncode": "[Adb] -s [Address] shell screencap -p", "release": "[Adb] kill-server" } }, @@ -174,8 +174,8 @@ "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init=", "displayFormat": " init=%dx%d", - "screencap": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", - "screencapGzip": true, + "screencapRawWithGzip": "[Adb] -s [Address] exec-out \"screencap | gzip -1\"", + "screencapEncode": "[Adb] -s [Address] exec-out screencap -p", "release": "[Adb] kill-server" } } diff --git a/src/MeoAssistant/AsstDef.h b/src/MeoAssistant/AsstDef.h index 3403d24932..602ff7ee13 100644 --- a/src/MeoAssistant/AsstDef.h +++ b/src/MeoAssistant/AsstDef.h @@ -239,12 +239,28 @@ namespace asst std::string swipe; std::string display; std::string display_format; - std::string screencap; - bool screencap_gzip = false; + std::string screencap_raw_with_gzip; + std::string screencap_encode; std::string release; //std::string pullscreen; int display_width = 0; int display_height = 0; + + enum class ScreencapEndOfLine + { + UnknownYet, + CRLF, + LF, + CR + } screencap_end_of_line = ScreencapEndOfLine::UnknownYet; + + enum class ScreencapMethod + { + UnknownYet, + Default, + RawWithGzip, + Encode + } screencap_method = ScreencapMethod::UnknownYet; }; struct EmulatorInfo diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index 6ee6447b9f..bce5d929a1 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -157,7 +157,8 @@ bool asst::Controller::connect_adb(const std::string & address) m_emulator_info.adb.click = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.click, "[Adb]", m_emulator_info.adb.path), "[Address]", address); m_emulator_info.adb.swipe = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.swipe, "[Adb]", m_emulator_info.adb.path), "[Address]", address); - m_emulator_info.adb.screencap = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.screencap, "[Adb]", m_emulator_info.adb.path), "[Address]", address); + m_emulator_info.adb.screencap_raw_with_gzip = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.screencap_raw_with_gzip, "[Adb]", m_emulator_info.adb.path), "[Address]", address); + m_emulator_info.adb.screencap_encode = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.screencap_encode, "[Adb]", m_emulator_info.adb.path), "[Address]", address); m_emulator_info.adb.release = utils::string_replace_all(m_emulator_info.adb.release, "[Adb]", m_emulator_info.adb.path); return true; @@ -564,7 +565,7 @@ int asst::Controller::push_cmd(const std::string & cmd) m_cmd_queue.emplace(cmd); m_cmd_condvar.notify_one(); return ++m_push_id; -} +} void asst::Controller::wait(unsigned id) const noexcept { @@ -579,54 +580,103 @@ bool asst::Controller::screencap() LogTraceFunction; auto& adb = m_emulator_info.adb; - auto ret = call_command(adb.screencap); + + DecodeFunc decode_raw_with_gzip = [&](const std::vector& data) -> bool { + auto unzip_data = gzip::decompress(data.data(), data.size()); + Log.trace("unzip data size:", unzip_data.size()); + if (unzip_data.empty()) { + return false; + } + size_t std_size = adb.display_height * adb.display_width * 4; + if (unzip_data.size() < std_size) { + return false; + } + size_t header_size = unzip_data.size() - std_size; + Log.trace("header size:", header_size); + m_cache_image = cv::Mat( + adb.display_height, + adb.display_width, + CV_8UC4, + unzip_data.data() + header_size); + cv::cvtColor(m_cache_image, m_cache_image, cv::COLOR_RGB2BGR); + return !m_cache_image.empty(); + }; + + DecodeFunc decode_encode = [&](const std::vector& data) -> bool { + m_cache_image = cv::imdecode(data, cv::IMREAD_COLOR); + return !m_cache_image.empty(); + }; + + switch (adb.screencap_method) { + case AdbCmd::ScreencapMethod::UnknownYet: + { + if (screencap(adb.screencap_raw_with_gzip, decode_raw_with_gzip)) { + adb.screencap_method = AdbCmd::ScreencapMethod::RawWithGzip; + return true; + } + else if (screencap(adb.screencap_encode, decode_encode)) { + adb.screencap_method = AdbCmd::ScreencapMethod::Encode; + return true; + } + else { + return false; + } + } + case AdbCmd::ScreencapMethod::RawWithGzip: + { + return screencap(adb.screencap_raw_with_gzip, decode_raw_with_gzip); + } + break; + case AdbCmd::ScreencapMethod::Encode: + { + return screencap(adb.screencap_encode, decode_encode); + } + break; + } + + return false; +} + +bool asst::Controller::screencap(const std::string & cmd, DecodeFunc decode_func) +{ + LogTraceFunction; + + auto& adb = m_emulator_info.adb; + auto ret = call_command(cmd); if (!ret || ret.value().empty()) { - Log.error("Data is empty!"); + Log.error("data is empty!"); return false; } auto data = std::move(ret).value(); - if (m_image_convert_lf) { + + if (adb.screencap_end_of_line == AdbCmd::ScreencapEndOfLine::CRLF) { convert_lf(data); } - std::function&)> decode_func = nullptr; - if (adb.screencap_gzip) { - decode_func = [&](const std::vector& data) -> bool { - auto unzip_data = gzip::decompress(data.data(), data.size()); - Log.trace("unzip data size:", unzip_data.size()); - if (unzip_data.empty()) { - return false; - } - constexpr static int BmpHeaderSize = 12; - size_t std_size = adb.display_height * adb.display_width * 4 + BmpHeaderSize; - if (unzip_data.size() != std_size) { - return false; - } - m_cache_image = cv::Mat(adb.display_height, adb.display_width, CV_8UC4, unzip_data.data() + BmpHeaderSize); - cv::cvtColor(m_cache_image, m_cache_image, cv::COLOR_RGB2BGR); - return !m_cache_image.empty(); - }; - } - else { - decode_func = [&](const std::vector& data) -> bool { - m_cache_image = cv::imdecode(data, cv::IMREAD_COLOR); - return !m_cache_image.empty(); - }; - } - - if (!decode_func(data)) { - Log.info("Data is not empty, but image is empty, try to convert lf"); - convert_lf(data); - if (!decode_func(data)) { - m_image_convert_lf = false; - Log.error("convert lf and retry decode falied!"); - return false; + if (decode_func(data)) { + if (adb.screencap_end_of_line == AdbCmd::ScreencapEndOfLine::UnknownYet) { + adb.screencap_end_of_line = AdbCmd::ScreencapEndOfLine::LF; } - m_image_convert_lf = true; return true; } - return true; + else { + Log.info("data is not empty, but image is empty"); + + if (adb.screencap_end_of_line == AdbCmd::ScreencapEndOfLine::UnknownYet) { + Log.info("try to cvt lf"); + convert_lf(data); + + if (decode_func(data)) { + adb.screencap_end_of_line = AdbCmd::ScreencapEndOfLine::CRLF; + return true; + } + else { + Log.error("convert lf and retry decode falied!"); + } + } + return false; + } } int asst::Controller::click(const Point & p, bool block) diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index 44cb24961c..b90ae96429 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -69,6 +69,8 @@ namespace asst std::optional> call_command(const std::string& cmd); int push_cmd(const std::string& cmd); bool screencap(); + using DecodeFunc = std::function&)>; + bool screencap(const std::string& cmd, DecodeFunc decode_func); Point rand_point_in_rect(const Rect& rect); void random_delay() const; @@ -89,7 +91,6 @@ namespace asst //std::shared_mutex m_image_mutex; cv::Mat m_cache_image; - bool m_image_convert_lf = false; constexpr static int PipeBuffSize = 4 * 1024 * 1024; // 管道缓冲区大小 std::unique_ptr m_pipe_buffer = nullptr; diff --git a/src/MeoAssistant/GeneralConfiger.cpp b/src/MeoAssistant/GeneralConfiger.cpp index d142aca5dd..9803aa0e26 100644 --- a/src/MeoAssistant/GeneralConfiger.cpp +++ b/src/MeoAssistant/GeneralConfiger.cpp @@ -51,8 +51,8 @@ bool asst::GeneralConfiger::parse(const json::value& json) emulator_info.adb.swipe = adb_json.at("swipe").as_string(); emulator_info.adb.display = adb_json.at("display").as_string(); emulator_info.adb.display_format = adb_json.at("displayFormat").as_string(); - emulator_info.adb.screencap = adb_json.at("screencap").as_string(); - emulator_info.adb.screencap_gzip = adb_json.get("screencapGzip", false); + emulator_info.adb.screencap_raw_with_gzip = adb_json.at("screencapRawWithGzip").as_string(); + emulator_info.adb.screencap_encode = adb_json.at("screencapEncode").as_string(); emulator_info.adb.release = adb_json.at("release").as_string(); //emulator_info.adb.pullscreen = adb_json.at("pullscreen").as_string();