#include "PL_Paint.h" #include "MaterialBuffer.h" #include "logger.h" #include "MediaHelper.h" #include // for memcpy #include #include #ifdef ENABLE_WTEXT #include "CvUtil/CvxText.h" #endif PLPLType::PLPLType(const char* _val_s) { for (int i = 0; i < sizeof(val_s); i++) val_s[i] = _val_s[i]; } PLPLType::PLPLType(const wchar_t* _val_s) { //wchar_t* w_val_s = (wchar_t*)val_s; //for (int i = 0; i < sizeof(val_s) / sizeof(wchar_t); i++) // w_val_s[i] = _val_s[i]; memcpy(val_s, _val_s, sizeof(val_s)); } PLPLContext::~PLPLContext() { #ifdef ENABLE_WTEXT delete (CvxText*)cvxText; cvxText = nullptr; #endif } void PLPLContext::clear() { cmds.clear(); params.clear(); } struct PL_Paint_Internal { uint8_t* buffer; size_t buffSize; PL_Paint_Config config; PipeMaterial pmList[2]; MB_Frame lastMbfBuffOrigin; MB_Frame lastMbfBuffCopy; bool payError; PL_Paint_Internal() : buffer(nullptr), buffSize(), config(), pmList(), lastMbfBuffOrigin(), lastMbfBuffCopy(), payError(true) { } ~PL_Paint_Internal() { reset(); } void reset() { delete buffer; buffer = nullptr; buffSize = 0; PL_Paint_Config _config; config = _config; PipeMaterial _pm; pmList[0] = _pm; pmList[1] = _pm; MB_Frame _lastMbfBuff; lastMbfBuffOrigin = _lastMbfBuff; lastMbfBuffCopy = _lastMbfBuff; payError = true; } }; PipeLineElem* create_PL_Paint() { return new PL_Paint; } PL_Paint::PL_Paint() : internal(new PL_Paint_Internal) { } PL_Paint::~PL_Paint() { delete (PL_Paint_Internal*)internal; internal= nullptr; } bool PL_Paint::init(void* args) { PL_Paint_Internal* in = (PL_Paint_Internal*)internal; in->reset(); if (args != nullptr) { PL_Paint_Config* config = (PL_Paint_Config*)args; in->config = *config; } #ifdef ENABLE_WTEXT if(in->config.plplCtx->cvxText != nullptr) { delete (CvxText*)in->config.plplCtx->cvxText; } if(!in->config.fontPath.empty()) { CvxText* cvxText = new CvxText(in->config.fontPath.c_str()); in->config.plplCtx->cvxText = cvxText; cvxText->setBackColor(cvScalar(128, 33, 14)); CvScalar font = cvScalar(40, 1, 0.2, 1); cvxText->setFont(0, &font); } #endif return true; } void PL_Paint::finit() { PL_Paint_Internal* in = (PL_Paint_Internal*)internal; } bool plplDraw_Rect_YUV420(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { int LTX = plplCtx->params[paramOffset + 0].val_i; int LTY = plplCtx->params[paramOffset + 1].val_i; int RBX = plplCtx->params[paramOffset + 2].val_i; int RBY = plplCtx->params[paramOffset + 3].val_i; paramOffset += 4; int src_width = paintMb->width; int src_height = paintMb->height; uint8_t* src_y = (uint8_t*)(paintMb->buffer); uint8_t* src_u = (uint8_t*)(src_y + (src_height * src_width)); uint8_t* src_v = (uint8_t*)(src_u + (src_height * src_width / 4)); cv::Mat yMat(cv::Size(src_width, src_height), CV_8UC1, src_y); cv::Mat uMat(cv::Size(MH_SUBSAMPLE1(src_width, 2), MH_SUBSAMPLE1(src_height, 2)), CV_8UC1, src_u); cv::Mat vMat(cv::Size(MH_SUBSAMPLE1(src_width, 2), MH_SUBSAMPLE1(src_height, 2)), CV_8UC1, src_v); // void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) const PLGH_Color_YUV yuvColor(plplCtx->color_front.toY(), plplCtx->color_front.toU(), plplCtx->color_front.toV()); cv::rectangle(yMat, cv::Point(LTX, LTY), cv::Point(RBX, RBY), CV_RGB(yuvColor.Y, yuvColor.Y, yuvColor.Y), 4); cv::rectangle(uMat, cv::Point(MH_SUBSAMPLE1(LTX, 2), MH_SUBSAMPLE1(LTY, 2)), cv::Point(MH_SUBSAMPLE1(RBX, 2), MH_SUBSAMPLE1(RBY, 2)), CV_RGB(yuvColor.U, yuvColor.U, yuvColor.U), 2); cv::rectangle(vMat, cv::Point(MH_SUBSAMPLE1(LTX, 2), MH_SUBSAMPLE1(LTY, 2)), cv::Point(MH_SUBSAMPLE1(RBX, 2), MH_SUBSAMPLE1(RBY, 2)), CV_RGB(yuvColor.V, yuvColor.V, yuvColor.V), 2); return true; } bool plplDraw_Rect_NV12(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { int LTX = plplCtx->params[paramOffset + 0].val_i; int LTY = plplCtx->params[paramOffset + 1].val_i; int RBX = plplCtx->params[paramOffset + 2].val_i; int RBY = plplCtx->params[paramOffset + 3].val_i; paramOffset += 4; int src_width = paintMb->width; int src_height = paintMb->height; uint8_t* src_y = (uint8_t*)(paintMb->buffer); uint8_t* src_uv = (uint8_t*)(src_y + (src_height * src_width)); cv::Mat yMat(cv::Size(src_width, src_height), CV_8UC1, src_y); cv::Mat uvMat(cv::Size(MH_SUBSAMPLE1(src_width, 2), MH_SUBSAMPLE1(src_height, 2)), CV_16UC1, src_uv); // void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) const uint16_t Y = plplCtx->color_front.toY(); const uint16_t UV = plplCtx->color_front.toUV(); cv::rectangle(yMat, cv::Point(LTX, LTY), cv::Point(RBX, RBY), CV_RGB(Y, Y, Y), 4); cv::rectangle(uvMat, cv::Point(MH_SUBSAMPLE1(LTX, 2), MH_SUBSAMPLE1(LTY, 2)), cv::Point(MH_SUBSAMPLE1(RBX, 2), MH_SUBSAMPLE1(RBY, 2)), CV_RGB(UV, UV, UV), 2); return true; } bool plplDraw_Rect_RGB565(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { int LTX = plplCtx->params[paramOffset + 0].val_i; int LTY = plplCtx->params[paramOffset + 1].val_i; int RBX = plplCtx->params[paramOffset + 2].val_i; int RBY = plplCtx->params[paramOffset + 3].val_i; paramOffset += 4; int src_width = paintMb->width; int src_height = paintMb->height; uint8_t* src_rgb = (uint8_t*)(paintMb->buffer); cv::Mat rgbMat(cv::Size(src_width, src_height), CV_16UC1, src_rgb); // void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) const uint16_t RGB565 = plplCtx->color_front.toRGB565(); cv::rectangle(rgbMat, cv::Point(LTX, LTY), cv::Point(RBX, RBY), CV_RGB(RGB565, RGB565, RGB565), 4); return true; } bool plplDraw_Text_YUV420(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { return false; } bool plplDraw_Text_NV12(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { int LTX = plplCtx->params[paramOffset + 0].val_i; int LTY = plplCtx->params[paramOffset + 1].val_i; const char* TXT = plplCtx->params[paramOffset + 2].val_s; paramOffset += 3; int src_width = paintMb->width; int src_height = paintMb->height; uint8_t* src_y = (uint8_t*)(paintMb->buffer); uint8_t* src_uv = (uint8_t*)(src_y + (src_height * src_width)); cv::Mat yMat(cv::Size(src_width, src_height), CV_8UC1, src_y); cv::Mat uvMat(cv::Size(MH_SUBSAMPLE1(src_width, 2), MH_SUBSAMPLE1(src_height, 2)), CV_16UC1, src_uv); // void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) const uint16_t Y = plplCtx->color_front.toY(); const uint16_t UV = plplCtx->color_front.toUV(); cv::putText(yMat, TXT, cv::Point(LTX, LTY), CV_FONT_HERSHEY_COMPLEX, 1, CV_RGB(Y, Y, Y)); cv::putText(uvMat, TXT, cv::Point(MH_SUBSAMPLE1(LTX, 2), MH_SUBSAMPLE1(LTY, 2)), CV_FONT_HERSHEY_COMPLEX, 0.5, CV_RGB(UV, UV, UV)); return true; } bool plplDraw_Text_RGB565(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { int LTX = plplCtx->params[paramOffset + 0].val_i; int LTY = plplCtx->params[paramOffset + 1].val_i; const char* TXT = plplCtx->params[paramOffset + 2].val_s; paramOffset += 3; int src_width = paintMb->width; int src_height = paintMb->height; uint8_t* src_rgb = (uint8_t*)(paintMb->buffer); cv::Mat rgbMat(cv::Size(src_width, src_height), CV_16UC1, src_rgb); const uint16_t RGB565 = plplCtx->color_front.toRGB565(); cv::putText(rgbMat, TXT, cv::Point(LTX, LTY), CV_FONT_HERSHEY_COMPLEX, 1, CV_RGB(RGB565, RGB565, RGB565)); return true; } bool plplDraw_WText_RGB565(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { #ifdef ENABLE_WTEXT int LTX = plplCtx->params[paramOffset + 0].val_i; int LTY = plplCtx->params[paramOffset + 1].val_i; const char* WTXT = plplCtx->params[paramOffset + 2].val_s; paramOffset += 3; int src_width = paintMb->width; int src_height = paintMb->height; uint8_t* src_rgb = (uint8_t*)(paintMb->buffer); cv::Mat rgbMat(cv::Size(src_width, src_height), CV_16UC1, src_rgb); // void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) const uint16_t RGB565 = plplCtx->color_front.toRGB565(); CvxText* cvText = (CvxText*)plplCtx->cvxText; cvText->putText(rgbMat, (const wchar_t*)WTXT, cv::Point(LTX, LTY), CV_RGB(RGB565, RGB565, RGB565)); return true; #else return false; #endif } bool plplDraw_WText_NV12(PLPLContext* plplCtx, MB_Frame* paintMb, int& paramOffset) { #ifdef ENABLE_WTEXT int LTX = plplCtx->params[paramOffset + 0].val_i; int LTY = plplCtx->params[paramOffset + 1].val_i; const char* WTXT = plplCtx->params[paramOffset + 2].val_s; paramOffset += 3; int src_width = paintMb->width; int src_height = paintMb->height; uint8_t* src_y = (uint8_t*)(paintMb->buffer); uint8_t* src_uv = (uint8_t*)(src_y + (src_height * src_width)); cv::Mat yMat(cv::Size(src_width, src_height), CV_8UC1, src_y); cv::Mat uvMat(cv::Size(MH_SUBSAMPLE1(src_width, 2), MH_SUBSAMPLE1(src_height, 2)), CV_16UC1, src_uv); // void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) const uint16_t Y = plplCtx->color_front.toY(); const uint16_t UV = plplCtx->color_front.toUV(); CvxText* cvText = (CvxText*)plplCtx->cvxText; cvText->putText(yMat, (const wchar_t*)WTXT, cv::Point(LTX, LTY), CV_RGB(Y, Y, Y)); // L"中文ABCDabcd" cvText->putText(uvMat, (const wchar_t*)WTXT, cv::Point(MH_SUBSAMPLE1(LTX, 2), MH_SUBSAMPLE1(LTY, 2)), CV_RGB(UV, UV, UV)); // L"中文ABCDabcd" return true; #else return false; #endif } bool plpl_executor(PL_Paint_Internal *in) { MB_Frame* paintMb = &(in->lastMbfBuffOrigin); int ret = true; if (in->config.copyData) { if (in->buffer == nullptr) { in->buffer = new uint8_t[in->lastMbfBuffOrigin.buffSize]; in->buffSize = in->lastMbfBuffOrigin.buffSize; } in->lastMbfBuffCopy = in->lastMbfBuffOrigin; in->lastMbfBuffCopy.buffer = in->buffer; in->lastMbfBuffCopy.buffSize = in->buffSize; memcpy(in->lastMbfBuffCopy.buffer, in->lastMbfBuffOrigin.buffer, in->lastMbfBuffCopy.buffSize); paintMb = &(in->lastMbfBuffCopy); } //for (int i=640;i<2000;i++) ((uint8_t*)paintMb->buffer)[i]=255; PLPLContext* plplCtx = in->config.plplCtx; int paramOffset = 0; for (int iCmd = 0; iCmd < in->config.plplCtx->cmds.size(); iCmd++) { PLPLCmd cmd = plplCtx->cmds[iCmd]; switch(cmd) { case PLPLC_COLOR: //COLOR F/B,R,G,B,A if (plplCtx->params[paramOffset + 0].val_i == 'F') { plplCtx->color_front = PLGH_Color_RGBA(plplCtx->params[paramOffset + 1].val_i, plplCtx->params[paramOffset + 2].val_i, plplCtx->params[paramOffset + 3].val_i, plplCtx->params[paramOffset + 4].val_i); paramOffset += 5; } else if (plplCtx->params[paramOffset + 0].val_i == 'B') { plplCtx->color_back = PLGH_Color_RGBA(plplCtx->params[paramOffset + 1].val_i, plplCtx->params[paramOffset + 2].val_i, plplCtx->params[paramOffset + 3].val_i, plplCtx->params[paramOffset + 4].val_i); paramOffset += 5; } else { LOG_WARN << "plpl execute error" << LOG_ENDL; return false; } break; case PLPLC_FILL: plplCtx->fill = plplCtx->params[paramOffset + 0].val_i; paramOffset += 1; break; case PLPLC_PEN: plplCtx->pen = PLGH_Pen(plplCtx->params[paramOffset + 0].val_i, plplCtx->params[paramOffset + 1].val_i); paramOffset += 2; break; case PLPLC_RECT: //RECT LTX,LTY,RBX,RBY if (paintMb->type == MB_Frame::MBFT_YUV420) ret = plplDraw_Rect_YUV420(plplCtx, paintMb, paramOffset); else if (paintMb->type == MB_Frame::MBFT_NV12) ret = plplDraw_Rect_NV12(plplCtx, paintMb, paramOffset); else if (paintMb->type == MB_Frame::MBFT_RGB565) ret = plplDraw_Rect_RGB565(plplCtx, paintMb, paramOffset); else ret = false; break; case PLPLC_TEXT: //TEXT LTX,LTY,"STR" if (paintMb->type == MB_Frame::MBFT_YUV420) ret = plplDraw_Text_YUV420(plplCtx, paintMb, paramOffset); else if (paintMb->type == MB_Frame::MBFT_NV12) ret = plplDraw_Text_NV12(plplCtx, paintMb, paramOffset); else if (paintMb->type == MB_Frame::MBFT_RGB565) ret = plplDraw_Text_RGB565(plplCtx, paintMb, paramOffset); else ret = false; break; case PLPLC_WTEXT: //WTEXT LTX,LTY,"STR" if (paintMb->type == MB_Frame::MBFT_NV12) ret = plplDraw_WText_NV12(plplCtx, paintMb, paramOffset); else if (paintMb->type == MB_Frame::MBFT_RGB565) ret = plplDraw_WText_RGB565(plplCtx, paintMb, paramOffset); else ret = false; break; } } return ret; } /*static*/ bool PL_Paint::pay_breaker_MBFT(const PipeMaterial* pm, void* args) { PL_Paint_Internal* in = (PL_Paint_Internal*)args; MB_Frame* frame = (MB_Frame*)pm->buffer; in->lastMbfBuffOrigin.type = frame->type; in->lastMbfBuffOrigin.buffer = frame->buffer; in->lastMbfBuffOrigin.buffSize = frame->buffSize; in->lastMbfBuffOrigin.width = frame->width; in->lastMbfBuffOrigin.height = frame->height; in->lastMbfBuffOrigin.pts = frame->pts; in->payError = !plpl_executor(in); return false; } bool PL_Paint::pay(const PipeMaterial& pm) { PL_Paint_Internal* in = (PL_Paint_Internal*)internal; in->payError = true; if (in->payError) pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_YUV420, PL_Paint::pay_breaker_MBFT, in); if (in->payError) pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_NV12, PL_Paint::pay_breaker_MBFT, in); if (in->payError) pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_RGB565, PL_Paint::pay_breaker_MBFT, in); return !(in->payError); } bool PL_Paint::gain(PipeMaterial& pm) { PL_Paint_Internal* in = (PL_Paint_Internal*)internal; if (in->payError) { pm.former = this; return false; } if (!in->config.copyData) { pm.type = PipeMaterial::PMT_FRAME; pm.buffer = &(in->lastMbfBuffOrigin); pm.buffSize = 0; } else { in->pmList[0].type = PipeMaterial::PMT_FRAME; in->pmList[0].buffer = &(in->lastMbfBuffCopy); in->pmList[0].buffSize = 0; in->pmList[0].former = this; in->pmList[1].type = PipeMaterial::PMT_FRAME; in->pmList[1].buffer = &(in->lastMbfBuffOrigin); in->pmList[1].buffSize = 0; in->pmList[1].former = this; pm.type = PipeMaterial::PMT_PM_LIST; pm.buffer = in->pmList; pm.buffSize = sizeof(in->pmList) / sizeof(PipeMaterial); } pm.former = this; return true; }