sujinwen
2017-07-25 c7caa54d8d58af6159f2c758ad5d6687d461a333
RtspFace/PL_Scale.cpp
@@ -1,8 +1,9 @@
#include "PL_Scale.h"
#include "MaterialBuffer.h"
#include "logger.h"
#include "MediaHelper.h"
#include <libyuv.h>
#include <android/native_window.h>
struct PL_Scale_Internal
{
   uint8_t* buffer;
@@ -11,12 +12,12 @@
   bool payError;
   
   PipeMaterial::PipeMaterialBufferType lastPmType;
   MB_Frame lastFrame;
   MB_Frame tempFrame;
   PL_Scale_Config config;
   PL_Scale_Internal() : 
      buffer(nullptr), buffSize(0), buffSizeMax(0), payError(true), 
      lastPmType(PipeMaterial::PMT_NONE), lastFrame(), config()
      lastPmType(PipeMaterial::PMT_NONE), tempFrame(), config()
   {
   }
   
@@ -33,18 +34,17 @@
      
      lastPmType = PipeMaterial::PMT_NONE;
      
      MB_Frame _lastFrame;
      lastFrame = _lastFrame;
      MB_Frame _tempFrame;
      tempFrame = _tempFrame;
      
      PL_Scale_Config _config;
      config = _config;
      if (buffer != nullptr)
      {
      if (buffSizeMax > 0)
         delete[] buffer;
         buffer = nullptr;
         buffSizeMax = 0;
      }
      buffer = nullptr;
      buffSizeMax = 0;
   }
};
@@ -89,32 +89,40 @@
   
}
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)
{
#define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a))
    const int dst_width = in->config.toWidth;
    const int dst_height = in->config.toHeight;
   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)
@@ -128,138 +136,96 @@
      
      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));
         
      in->buffSize = dstSizeMax;
   }
    else if (srcType == MB_Frame::MBFT_NV12)
    {
        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
   else if (srcType == MB_Frame::MBFT_NV12)
   {
      const uint8_t* src_y = (const uint8_t*)(srcBuffer);
      const uint8_t* src_uv = (const uint8_t*)(src_y + (srcHeight * srcWidth));
            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->lastFrame = *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->lastFrame = *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;
@@ -275,16 +241,16 @@
   }
   break;
   case PipeMaterial::PMT_FRAME:
    case PipeMaterial::PMT_PM_LIST:
   case PipeMaterial::PMT_PM_LIST:
   {
      newPm.type = PipeMaterial::PMT_FRAME;
      newPm.buffer = &(in->lastFrame);
      newPm.buffer = &(in->tempFrame);
      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;
      in->tempFrame.buffer = in->buffer;
      in->tempFrame.buffSize = in->buffSize;
      in->tempFrame.width = in->config.toWidth;
      in->tempFrame.height = in->config.toHeight;
   }
   break;
   default: