#include "PL_Scale.h" #include "MaterialBuffer.h" #include "logger.h" #include struct PL_Scale_Internal { uint8_t* buffer; size_t buffSize; size_t buffSizeMax; bool payError; PipeMaterial::PipeMaterialBufferType lastPmType; MB_Frame lastFrame; PL_Scale_Config config; PL_Scale_Internal() : buffer(nullptr), buffSize(0), buffSizeMax(0), payError(true), lastPmType(PipeMaterial::PMT_NONE), lastFrame(), config() { } ~PL_Scale_Internal() { delete[] buffer; buffer = nullptr; } void reset() { buffSize = 0; payError = true; lastPmType = PipeMaterial::PMT_NONE; MB_Frame _lastFrame; lastFrame = _lastFrame; PL_Scale_Config _config; config = _config; if (buffer != nullptr) { delete[] buffer; buffer = nullptr; buffSizeMax = 0; } } }; PipeLineElem* create_PL_Scale() { return new PL_Scale; } PL_Scale::PL_Scale() : internal(new PL_Scale_Internal) { } PL_Scale::~PL_Scale() { delete (PL_Scale_Internal*)internal; internal= nullptr; } bool PL_Scale::init(void* args) { PL_Scale_Internal* in = (PL_Scale_Internal*)internal; in->reset(); if (args != nullptr) { PL_Scale_Config* config = (PL_Scale_Config*)args; in->config = *config; } if (in->config.toWidth <= 0 || in->config.toHeight <= 0) { LOG_ERROR << "Config toWidth and toHeight should > 0" << std::endl; return false; } return true; } void PL_Scale::finit() { PL_Scale_Internal* in = (PL_Scale_Internal*)internal; } bool image_scale(PL_Scale_Internal* in, uint8_t* srcBuffer, int srcBuffSize, MB_Frame::MBFType srcType, uint16_t srcWidth, uint16_t srcHeight) { #define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a)) const int dst_width = in->config.toWidth; const int dst_height = in->config.toHeight; size_t dstSizeMax = 0; if (srcType == MB_Frame::MBFT_YUV420) dstSizeMax = in->config.toWidth * in->config.toHeight * 1.5; else if (srcType == MB_Frame::MBFT_BGRA) dstSizeMax = in->config.toWidth * in->config.toHeight * 4; else { LOG_ERROR << "srcType only support MBFT_YUV420 and MBFT_BGRA" << std::endl; return false; } if (in->buffer == nullptr || in->buffSizeMax < dstSizeMax) { if (in->buffer != nullptr) delete[] in->buffer; in->buffer = new uint8_t[dstSizeMax]; in->buffSizeMax = dstSizeMax; LOG_INFO << "image_scale alloc buffer size=" << dstSizeMax << std::endl; } if (srcType == MB_Frame::MBFT_YUV420) { uint8_t* src_y = srcBuffer; uint8_t* src_u = src_y + srcWidth * srcHeight; uint8_t* src_v = src_u + srcWidth * srcHeight / 4; uint8_t* dst_y = in->buffer; uint8_t* dst_u = dst_y + dst_width * dst_height; uint8_t* dst_v = dst_u + dst_width * dst_height / 4; libyuv::I420Scale( src_y, srcWidth, src_u, SUBSAMPLE(srcWidth, 2), src_v, SUBSAMPLE(srcWidth, 2), srcWidth, srcHeight, dst_y, dst_width, dst_u, SUBSAMPLE(dst_width, 2), dst_v, SUBSAMPLE(dst_width, 2), dst_width, dst_height, (libyuv::FilterMode)(in->config.filterMode)); in->buffSize = dstSizeMax; } else if (srcType == MB_Frame::MBFT_BGRA) { //#todo LOG_ERROR << "srcType only support MBFT_YUV420 and MBFT_BGRA" << std::endl; return false; } } bool PL_Scale::pay(const PipeMaterial& pm) { PL_Scale_Internal* in = (PL_Scale_Internal*)internal; in->payError = true; if (pm.buffer == nullptr) return false; bool ret = false; in->lastPmType = pm.type; switch(pm.type) { case PipeMaterial::PMT_BYTES: { if (in->config.defaultBytesType <= 0 || in->config.defaultBytesWidth <= 0 || in->config.defaultBytesHeight <= 0) { LOG_ERROR << "defaultBytesType/defaultBytesWidth/defaultBytesHeight not set" << std::endl; return false; } ret = image_scale(in, (uint8_t*)pm.buffer, pm.buffSize, (MB_Frame::MBFType)(in->config.defaultBytesType), in->config.defaultBytesWidth, in->config.defaultBytesHeight); } break; case PipeMaterial::PMT_FRAME: { MB_Frame* frame = (MB_Frame*)pm.buffer; switch(frame->type) { case MB_Frame::MBFT_YUV420: case MB_Frame::MBFT_BGRA: in->lastFrame = *frame; ret = image_scale(in, (uint8_t*)frame->buffer, frame->buffSize, frame->type, frame->width, frame->height); break; default: LOG_ERROR << "Only support MBFT_YUV420 / MBFT_BGRA" << std::endl; return false; } } break; default: LOG_ERROR << "Only support PMT_BYTES / PMT_FRAME" << std::endl; return false; } in->payError = !ret; return ret; } bool PL_Scale::gain(PipeMaterial& pm) { PL_Scale_Internal* in = (PL_Scale_Internal*)internal; PipeMaterial newPm; newPm.type = PipeMaterial::PMT_NONE; newPm.former = this; switch(in->lastPmType) { case PipeMaterial::PMT_BYTES: { newPm.type = PipeMaterial::PMT_BYTES; newPm.buffer = in->buffer; newPm.buffSize = in->buffSize; } break; case PipeMaterial::PMT_FRAME: { newPm.type = PipeMaterial::PMT_FRAME; newPm.buffer = &(in->lastFrame); newPm.buffSize = 0; in->lastFrame.buffer = in->buffer; in->lastFrame.buffSize = in->buffSize; in->lastFrame.width = in->config.toWidth; in->lastFrame.height = in->config.toHeight; } break; default: LOG_ERROR << "Only support PMT_BYTES / PMT_FRAME" << std::endl; } pm = newPm; return !in->payError; }