| | |
| | | #include "PL_Scale.h"
|
| | | #include "MaterialBuffer.h"
|
| | | #include "logger.h"
|
| | | #include "MediaHelper.h"
|
| | | #include <libyuv.h>
|
| | |
|
| | | #define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a))
|
| | |
|
| | | struct PL_Scale_Internal
|
| | | {
|
| | |
| | | PL_Scale_Config _config;
|
| | | config = _config;
|
| | |
|
| | | if (buffer != nullptr)
|
| | | {
|
| | | if (buffSizeMax > 0)
|
| | | delete[] buffer;
|
| | | buffer = nullptr;
|
| | | buffSizeMax = 0;
|
| | | }
|
| | |
|
| | | buffer = nullptr;
|
| | | buffSizeMax = 0;
|
| | | }
|
| | | };
|
| | |
|
| | |
| | |
|
| | | }
|
| | |
|
| | | bool image_scale(PL_Scale_Internal* in, |
| | | uint8_t* srcBuffer, MB_Frame::MBFType srcType, uint16_t srcWidth, uint16_t srcHeight)
|
| | | bool image_scale(PL_Scale_Internal* in, uint8_t* srcBuffer, size_t buffSize, MB_Frame::MBFType srcType, uint16_t srcWidth, uint16_t srcHeight)
|
| | | {
|
| | |
|
| | | const int dst_width = in->config.toWidth;
|
| | | const int dst_height = in->config.toHeight;
|
| | |
|
| | | size_t dstSizeMax = 0;
|
| | | if (srcType == MB_Frame::MBFT_YUV420||srcType == MB_Frame::MBFT_NV12)
|
| | | dstSizeMax = in->config.toWidth * in->config.toHeight * 1.5;
|
| | | else if (srcType == MB_Frame::MBFT_BGRA)
|
| | | dstSizeMax = in->config.toWidth * in->config.toHeight * 4;
|
| | | if ((dst_width != srcWidth && dst_height != srcHeight) || in->config.copyData)
|
| | | {
|
| | | if (srcType == MB_Frame::MBFT_YUV420 || srcType == MB_Frame::MBFT_NV12)
|
| | | dstSizeMax = in->config.toWidth * in->config.toHeight * 2; // #todo 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;
|
| | | }
|
| | | }
|
| | | else
|
| | | {
|
| | | LOG_ERROR << "srcType only support MBFT_YUV420 and MBFT_BGRA" << std::endl;
|
| | | return false;
|
| | | }
|
| | | in->buffer = srcBuffer;
|
| | | in->buffSize = buffSize;
|
| | | in->buffSizeMax = 0;
|
| | |
|
| | | 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;
|
| | | return true;
|
| | | }
|
| | |
|
| | | if (srcType == MB_Frame::MBFT_YUV420)
|
| | |
| | |
|
| | | libyuv::I420Scale(
|
| | | src_y, srcWidth,
|
| | | src_u, SUBSAMPLE(srcWidth, 2), |
| | | src_v, SUBSAMPLE(srcWidth, 2), |
| | | src_u, MH_SUBSAMPLE1(srcWidth, 2), |
| | | src_v, MH_SUBSAMPLE1(srcWidth, 2), |
| | | srcWidth, srcHeight,
|
| | | dst_y, dst_width,
|
| | | dst_u, SUBSAMPLE(dst_width, 2), |
| | | dst_v, SUBSAMPLE(dst_width, 2), |
| | | dst_u, MH_SUBSAMPLE1(dst_width, 2), |
| | | dst_v, MH_SUBSAMPLE1(dst_width, 2), |
| | | dst_width, dst_height,
|
| | | (libyuv::FilterMode)(in->config.filterMode));
|
| | |
|
| | |
| | | {
|
| | | const uint8_t* src_y = (const uint8_t*)(srcBuffer);
|
| | | const uint8_t* src_uv = (const uint8_t*)(src_y + (srcHeight * srcWidth));
|
| | | if (srcWidth != dst_width || srcHeight != dst_height)
|
| | | {
|
| | | // RK3288, 1920->640: 2.8~12ms, avg=4ms
|
| | |
|
| | | uint8_t* dst_y = (uint8_t*)(in->buffer);
|
| | | uint8_t* dst_uv = (uint8_t*)(dst_y + (dst_height * dst_width));
|
| | | // RK3288, 1920->640: 2.8~12ms, avg=4ms
|
| | | uint8_t* dst_y = (uint8_t*)(in->buffer);
|
| | | uint8_t* dst_uv = (uint8_t*)(dst_y + (dst_height * dst_width));
|
| | |
|
| | | libyuv::ScalePlane(src_y, srcWidth,
|
| | | srcWidth, srcHeight,
|
| | | dst_y, dst_width,
|
| | | dst_width, dst_height,
|
| | | libyuv::kFilterNone);
|
| | | libyuv::ScalePlane(src_y, srcWidth,
|
| | | srcWidth, srcHeight,
|
| | | dst_y, dst_width,
|
| | | dst_width, dst_height,
|
| | | libyuv::kFilterNone);
|
| | |
|
| | | libyuv::ScalePlane_16((uint16*)src_uv, SUBSAMPLE(srcWidth, 2),
|
| | | SUBSAMPLE(srcWidth, 2), SUBSAMPLE(srcHeight, 2),
|
| | | (uint16*)dst_uv, SUBSAMPLE(dst_width, 2),
|
| | | SUBSAMPLE(dst_width, 2), SUBSAMPLE(dst_height, 2),
|
| | | libyuv::kFilterNone);
|
| | | in->buffSize = dstSizeMax;
|
| | | }
|
| | | else if (srcType == MB_Frame::MBFT_BGRA)
|
| | | {
|
| | | //#todo
|
| | | LOG_ERROR << "srcType only support MBFT_YUV420 and MBFT_NV12" << std::endl;
|
| | | return false;
|
| | | }
|
| | | else
|
| | | {
|
| | | LOG_ERROR << "srcType only support MBFT_YUV420 and MBFT_NV12" << std::endl;
|
| | | return false;
|
| | | }
|
| | | return true;
|
| | | libyuv::ScalePlane_16((uint16*)src_uv, MH_SUBSAMPLE1(srcWidth, 2),
|
| | | MH_SUBSAMPLE1(srcWidth, 2), MH_SUBSAMPLE1(srcHeight, 2),
|
| | | (uint16*)dst_uv, MH_SUBSAMPLE1(dst_width, 2),
|
| | | MH_SUBSAMPLE1(dst_width, 2), MH_SUBSAMPLE1(dst_height, 2),
|
| | | libyuv::kFilterNone);
|
| | |
|
| | | in->buffSize = dstSizeMax;
|
| | | }
|
| | | else if (srcType == MB_Frame::MBFT_BGRA)
|
| | | {
|
| | | //#todo
|
| | | LOG_ERROR << "srcType only support MBFT_YUV420 and MBFT_NV12" << std::endl;
|
| | | return false;
|
| | | }
|
| | | else
|
| | | {
|
| | | LOG_ERROR << "srcType only support MBFT_YUV420 and MBFT_NV12" << std::endl;
|
| | | return false;
|
| | | }
|
| | |
|
| | | return true;
|
| | | }
|
| | |
|
| | | /*static*/ bool PL_Scale::pay_breaker_MBFT(const PipeMaterial* pm, void* args)
|
| | | {
|
| | | PL_Scale_Internal* in = (PL_Scale_Internal*)args;
|
| | |
|
| | | MB_Frame* mbf = (MB_Frame*)pm->buffer;
|
| | | in->payError = !image_scale(in, (uint8_t*)mbf->buffer, mbf->buffSize, mbf->type, mbf->width, mbf->height);
|
| | |
|
| | | if (!(in->payError))
|
| | | in->tempFrame = *mbf;
|
| | |
|
| | | 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, (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->tempFrame = *frame;
|
| | | ret = image_scale(in, (uint8_t*)frame->buffer, frame->type,
|
| | | frame->width, frame->height);
|
| | | break;
|
| | | default:
|
| | | LOG_ERROR << "Only support MBFT_YUV420 / MBFT_BGRA" << std::endl;
|
| | | return false;
|
| | | }
|
| | | }
|
| | | break;
|
| | | case PipeMaterial::PMT_PM_LIST:
|
| | | {
|
| | | // break pm list into single pm(s)
|
| | |
|
| | | MB_Frame* ppm = (MB_Frame*)pm.buffer;
|
| | | for (size_t i = 0; i < pm.buffSize; i++, ppm++)
|
| | | {
|
| | | if (ppm->type== PipeMaterial::PMT_FRAME)
|
| | | {
|
| | | MB_Frame* frame = (MB_Frame*)ppm->buffer;
|
| | | switch(frame->type)
|
| | | {
|
| | | case MB_Frame::MBFT_YUV420:
|
| | | case MB_Frame::MBFT_BGRA:
|
| | | case MB_Frame::MBFT_NV12:
|
| | | in->tempFrame = *frame;
|
| | | ret = image_scale(in, (uint8_t*)frame->buffer,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;
|
| | | in->payError = true;
|
| | | if (in->payError)
|
| | | pm.breake(PipeMaterial::PMT_FRAME_LIST, MB_Frame::MBFT_YUV420, pay_breaker_MBFT, in);
|
| | | if (in->payError)
|
| | | pm.breake(PipeMaterial::PMT_FRAME_LIST, MB_Frame::MBFT_NV12, pay_breaker_MBFT, in);
|
| | | if (in->payError)
|
| | | pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_YUV420, pay_breaker_MBFT, in);
|
| | | if (in->payError)
|
| | | pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_NV12, pay_breaker_MBFT, in);
|
| | | if (in->payError)
|
| | | pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_RGB565, pay_breaker_MBFT, in);
|
| | |
|
| | | if (!(in->payError))
|
| | | in->lastPmType = pm.type;
|
| | |
|
| | | return !(in->payError);
|
| | | }
|
| | |
|
| | | bool PL_Scale::gain(PipeMaterial& pm)
|
| | | {
|
| | | PL_Scale_Internal* in = (PL_Scale_Internal*)internal;
|
| | |
|
| | | if (in->payError)
|
| | | return false;
|
| | |
|
| | | PipeMaterial newPm;
|
| | | newPm.type = PipeMaterial::PMT_NONE;
|
| | | newPm.former = this;
|