houxiao
2017-08-16 a188ad2e23ef190c8a044b17bc467fa3e2ae0ca5
VisitFace/RtspNativeCodec/app/src/main/cpp/FaceCacheForPLBG.cpp
@@ -18,254 +18,298 @@
struct OutRGBBufferWrapper
{
    uint8_t* buffer;
    size_t buffSize;
   uint8_t* buffer;
   size_t buffSize;
    OutRGBBufferWrapper() : buffer(nullptr), buffSize(0)
    { }
   OutRGBBufferWrapper() : buffer(nullptr), buffSize(0)
   { }
    OutRGBBufferWrapper(uint8_t* _buffer, size_t _buffSize) : buffer(_buffer), buffSize(_buffSize)
    { }
   OutRGBBufferWrapper(uint8_t* _buffer, size_t _buffSize) : buffer(_buffer), buffSize(_buffSize)
   { }
};
struct FcPmBreackerContextPLBG
{
    plbg_output_vec_t lastOutputs;
    std::vector<OutRGBBufferWrapper> lastOutputsRGBBufs;
   plbg_output_vec_t lastOutputs;
   std::vector<OutRGBBufferWrapper> lastOutputsRGBBufs;
    uint8_t frameYUV[1920*1080*4];
    size_t frameYUVSize;
    uint8_t frameRGB[1920*1080*4];
    size_t frameRGBSize;
    bool frameTruncated;
   uint8_t frameYUV[1920*1080*4];
   size_t frameYUVSize;
   uint8_t frameRGB[1920*1080*4];
   size_t frameRGBSize;
   bool frameTruncated;
    FcPmBreackerContextPLBG() :
            lastOutputs(), lastOutputsRGBBufs(), frameYUV(), frameYUVSize(0), frameRGB(),frameRGBSize(0),
            frameTruncated(false)
    {}
   typedef std::map<int, float> block_score_filter_map_t;
   block_score_filter_map_t blockScoreFilter;
    void reset()
    {
        lastOutputs.clear();
        lastOutputsRGBBufs.clear();
        frameYUVSize = 0;
        frameRGBSize = 0;
        frameTruncated = false;
    }
   FcPmBreackerContextPLBG() :
         lastOutputs(), lastOutputsRGBBufs(), frameYUV(), frameYUVSize(0), frameRGB(),frameRGBSize(0),
         frameTruncated(false),
         blockScoreFilter()
   {}
    void copy_data()
    {
        uint8_t* bufPtr = frameYUV;
        for (plbg_output_vec_t::iterator iter = lastOutputs.begin(); iter != lastOutputs.end(); ++iter)
        {
            const uint8_t* originBuf = iter->croppedData;
            if (originBuf == nullptr || iter->croppedDataSize == 0)
                continue;
   void reset()
   {
      lastOutputs.clear();
      lastOutputsRGBBufs.clear();
      frameYUVSize = 0;
      frameRGBSize = 0;
      frameTruncated = false;
   }
            if (sizeof(frameYUV) - (bufPtr - frameYUV) < iter->croppedDataSize)
            {
                frameTruncated = true;
                LOG_WARN << "yuv buffer truncated" << LOG_ENDL;
                break;
            }
   void copy_data()
   {
      uint8_t* bufPtr = frameYUV;
      for (plbg_output_vec_t::iterator iter = lastOutputs.begin(); iter != lastOutputs.end(); ++iter)
      {
         const uint8_t* originBuf = iter->croppedData;
         if (originBuf == nullptr || iter->croppedDataSize == 0)
            continue;
            iter->croppedData = bufPtr;
            memcpy(bufPtr, originBuf, iter->croppedDataSize);
            bufPtr += iter->croppedDataSize;
            frameYUVSize += iter->croppedDataSize;
        }
    }
         if (sizeof(frameYUV) - (bufPtr - frameYUV) < iter->croppedDataSize)
         {
            frameTruncated = true;
            LOG_WARN << "yuv buffer truncated" << LOG_ENDL;
            break;
         }
    void convert_data()
    {
        uint8_t* bufPtr = frameRGB;
        for (plbg_output_vec_t::iterator iter = lastOutputs.begin(); iter != lastOutputs.end(); ++iter)
        {
            if (iter->croppedData == nullptr || iter->croppedDataSize == 0)
            {
                OutRGBBufferWrapper bw;
                lastOutputsRGBBufs.push_back(bw);
                continue;
            }
         iter->croppedData = bufPtr;
         memcpy(bufPtr, originBuf, iter->croppedDataSize);
         bufPtr += iter->croppedDataSize;
         frameYUVSize += iter->croppedDataSize;
      }
   }
            OutRGBBufferWrapper bw;
            bw.buffer = bufPtr;
            bw.buffSize = iter->rectInOriginFrame.width() * iter->rectInOriginFrame.height() * 2; //RGB565
            if (sizeof(frameRGB) - (bufPtr - frameRGB) < bw.buffSize)
            {
                frameTruncated = true;
                OutRGBBufferWrapper bw;
                lastOutputsRGBBufs.push_back(bw);
                LOG_WARN << "rgb buffer truncated" << LOG_ENDL;
                continue;
            }
   void convert_data()
   {
      uint8_t* bufPtr = frameRGB;
      for (plbg_output_vec_t::iterator iter = lastOutputs.begin(); iter != lastOutputs.end(); ++iter)
      {
         if (iter->croppedData == nullptr || iter->croppedDataSize == 0)
         {
            OutRGBBufferWrapper bw;
            lastOutputsRGBBufs.push_back(bw);
            continue;
         }
            convertYUV420ToRGB565(*iter, bw.buffer);
         OutRGBBufferWrapper bw;
         bw.buffer = bufPtr;
         bw.buffSize = iter->rectInOriginFrame.rect.width() * iter->rectInOriginFrame.rect.height() * 2; //RGB565
         if (sizeof(frameRGB) - (bufPtr - frameRGB) < bw.buffSize)
         {
            frameTruncated = true;
            OutRGBBufferWrapper bw;
            lastOutputsRGBBufs.push_back(bw);
            LOG_WARN << "rgb buffer truncated" << LOG_ENDL;
            continue;
         }
            lastOutputsRGBBufs.push_back(bw);
            bufPtr += bw.buffSize;
            frameRGBSize += bw.buffSize;
        }
    }
         convertYUV420ToRGB565(*iter, bw.buffer);
         lastOutputsRGBBufs.push_back(bw);
         bufPtr += bw.buffSize;
         frameRGBSize += bw.buffSize;
      }
   }
private:
    bool convertYUV420ToRGB565(const PLBG_Output& out, uint8_t* rgbBuff)
    {
        int src_height = out.rectInOriginFrame.height();
        int src_width = out.rectInOriginFrame.width();
        const uint8* src_y = (const uint8*)(out.croppedData);
        const uint8* src_u = (const uint8*)(src_y + (src_height * src_width));
        const uint8* src_v = (const uint8*)(src_u + (src_height * src_width / 4));
   bool convertYUV420ToRGB565(const PLBG_Output& out, uint8_t* rgbBuff)
   {
      int src_height = out.rectInOriginFrame.rect.height();
      int src_width = out.rectInOriginFrame.rect.width();
      const uint8* src_y = (const uint8*)(out.croppedData);
      const uint8* src_u = (const uint8*)(src_y + (src_height * src_width));
      const uint8* src_v = (const uint8*)(src_u + (src_height * src_width / 4));
        if (out.originframe->type == MB_Frame::MBFT_YUV420)
        {
            libyuv::I420ToRGB565(src_y, src_width,
                                 src_v, MH_SUBSAMPLE1(src_width, 2),
                                 src_u, MH_SUBSAMPLE1(src_width, 2),
                                 rgbBuff, 2 * src_width,
                                 src_width, src_height);
        }
        else if (out.originframe->type == MB_Frame::MBFT_NV12)
        {
            libyuv::NV12ToRGB565(src_y, src_width,
                                 src_u, src_width,
                                 rgbBuff, 2 * src_width,
                                 src_width, src_height);
        }
        else
            return false;
      if (out.originframe->type == MB_Frame::MBFT_YUV420)
      {
         libyuv::I420ToRGB565(src_y, src_width,
                         src_v, MH_SUBSAMPLE1(src_width, 2),
                         src_u, MH_SUBSAMPLE1(src_width, 2),
                         rgbBuff, 2 * src_width,
                         src_width, src_height);
      }
      else if (out.originframe->type == MB_Frame::MBFT_NV12)
      {
         libyuv::NV12ToRGB565(src_y, src_width,
                         src_u, src_width,
                         rgbBuff, 2 * src_width,
                         src_width, src_height);
      }
      else
         return false;
        //{
        //    static size_t f = 0;
        //    char fname[50];
        //    sprintf(fname, "/sdcard/face-%u-w%u-h%u.rgb", ++f, src_width, src_height);
        //    FILE *pFile = fopen(fname, "wb");
        //    fwrite(rgbBuff, 1, src_height * src_width * 2, pFile);
        //    fclose(pFile);
        //    if (f > 20)exit(0);
        //}
        return true;
    }
      //{
      //   static size_t f = 0;
      //   char fname[50];
      //   sprintf(fname, "/sdcard/face-%u-w%u-h%u.rgb", ++f, src_width, src_height);
      //   FILE *pFile = fopen(fname, "wb");
      //   fwrite(rgbBuff, 1, src_height * src_width * 2, pFile);
      //   fclose(pFile);
      //   if (f > 20)exit(0);
      //}
      return true;
   }
};
FaceCacheForPLBG::FaceCacheForPLBG() : _ctx(new FcPmBreackerContextPLBG)
FaceCacheForPLBG::FaceCacheForPLBG() : _ctx(new FcPmBreackerContextPLBG), resultBuffer(nullptr)
{
   resultBuffer = new uint8_t[FACECACHEFORPLBG_RESULT_BUFFSIZE];
}
FaceCacheForPLBG::~FaceCacheForPLBG()
{
    delete (FcPmBreackerContextPLBG*)_ctx;
   delete (FcPmBreackerContextPLBG*)_ctx;
   delete resultBuffer;
   resultBuffer = nullptr;
}
// returns count of face
int FaceCacheForPLBG::cachePm(const PipeMaterial& pm)
{
    FcPmBreackerContextPLBG& ctx(*(FcPmBreackerContextPLBG*)_ctx);
    ctx.reset();
   FcPmBreackerContextPLBG& ctx(*(FcPmBreackerContextPLBG*)_ctx);
   ctx.reset();
    plbg_output_vec_t* plbgOut = (plbg_output_vec_t*)pm.buffer;
    if (plbgOut->size() == 0)
        return 0;
   plbg_output_vec_t* plbgOut = (plbg_output_vec_t*)pm.buffer;
   if (plbgOut->size() == 0)
      return 0;
    ctx.lastOutputs = *plbgOut;
    ctx.copy_data();
    ctx.convert_data();
   ctx.lastOutputs = *plbgOut;
   ctx.copy_data();
   ctx.convert_data();
    return  ctx.lastOutputs.size();
   return  ctx.lastOutputs.size();
}
size_t FaceCacheForPLBG::getFaceCount(const PipeMaterial& pm) const
{
    plbg_output_vec_t* plbgOut = (plbg_output_vec_t*)pm.buffer;
    return plbgOut->size();
}
   FcPmBreackerContextPLBG& ctx(*(FcPmBreackerContextPLBG*)_ctx);
   plbg_output_vec_t* plbgOut = (plbg_output_vec_t*)pm.buffer;
   bool hasFiltedBlock = false;
   int min_st_track_id = 0;
   for (plbg_output_vec_t::iterator iterBGOut = plbgOut->begin(); iterBGOut != plbgOut->end(); ++iterBGOut)
   {
      int st_track_id = (int)(int64_t)(iterBGOut->rectInOriginFrame.userData);
      float score = iterBGOut->score;
      FcPmBreackerContextPLBG::block_score_filter_map_t::iterator iterFilter = ctx.blockScoreFilter.find(st_track_id);
      if (iterFilter == ctx.blockScoreFilter.end())
      {
         ctx.blockScoreFilter.insert(std::make_pair(st_track_id, score));
         hasFiltedBlock = true;
      }
      else
      {
         if (iterFilter->second < score)
         {
            iterFilter->second = score;
            hasFiltedBlock = true;
         }
      }
      if (min_st_track_id > st_track_id)
         min_st_track_id = st_track_id;
   }
   for(FcPmBreackerContextPLBG::block_score_filter_map_t::iterator iterFilter = ctx.blockScoreFilter.begin(); iterFilter != ctx.blockScoreFilter.end(); )
   {
      if (iterFilter->first < min_st_track_id)
         iterFilter = ctx.blockScoreFilter.erase(iterFilter);
      else
         ++iterFilter;
   }
   if (hasFiltedBlock)
      return plbgOut->size();
   else
      return 0;
}
bool FaceCacheForPLBG::getFaceListPb(uint8_t* buffer, size_t& buffMaxSize)
{
    FcPmBreackerContextPLBG& ctx(*(FcPmBreackerContextPLBG*)_ctx);
    if (ctx.frameTruncated)
    {
        LOG_WARN << "ctx buffer truncated" << LOG_ENDL;
        return false;
    }
   FcPmBreackerContextPLBG& ctx(*(FcPmBreackerContextPLBG*)_ctx);
   if (ctx.frameTruncated)
   {
      LOG_WARN << "ctx buffer truncated" << LOG_ENDL;
      return false;
   }
    PbFaceList pbFaceList;
    pbFaceList.set_magic(pbFaceList.magic());
    pbFaceList.set_image_count(ctx.lastOutputs.size());
    pbFaceList.set_src_width(0);
    pbFaceList.set_src_height(0);
   PbFaceList pbFaceList;
   pbFaceList.set_magic(pbFaceList.magic());
   pbFaceList.set_image_count(ctx.lastOutputs.size());
   pbFaceList.set_src_width(0);
   pbFaceList.set_src_height(0);
    for (int i = 0; i < ctx.lastOutputs.size(); i++)
    {
        PbFaceList_FaceListImage &pbFaceListImage(*(pbFaceList.add_images()));
        pbFaceListImage.set_idx(i);
        pbFaceListImage.set_st_track_id(1111111111111111);
        pbFaceListImage.set_size(ctx.lastOutputs[i].croppedDataSize);
        pbFaceListImage.set_type(PbFaceList_FaceListImage_ImageType_MBFT_NV12);
        pbFaceListImage.set_width(ctx.lastOutputs[i].rectInOriginFrame.width());
        pbFaceListImage.set_height(ctx.lastOutputs[i].rectInOriginFrame.height());
        pbFaceListImage.set_top_left_x(ctx.lastOutputs[i].rectInOriginFrame.leftTop.X);
        pbFaceListImage.set_top_left_y(ctx.lastOutputs[i].rectInOriginFrame.leftTop.Y);
   for (int i = 0; i < ctx.lastOutputs.size(); i++)
   {
      PbFaceList_FaceListImage &pbFaceListImage(*(pbFaceList.add_images()));
      pbFaceListImage.set_idx(i);
      pbFaceListImage.set_st_track_id((int)(int64_t)(ctx.lastOutputs[i].rectInOriginFrame.userData));
      pbFaceListImage.set_size(ctx.lastOutputs[i].croppedDataSize);
      pbFaceListImage.set_type(PbFaceList_FaceListImage_ImageType_MBFT_NV12);
      pbFaceListImage.set_width(ctx.lastOutputs[i].rectInOriginFrame.rect.width());
      pbFaceListImage.set_height(ctx.lastOutputs[i].rectInOriginFrame.rect.height());
      pbFaceListImage.set_top_left_x(ctx.lastOutputs[i].rectInOriginFrame.rect.leftTop.X);
      pbFaceListImage.set_top_left_y(ctx.lastOutputs[i].rectInOriginFrame.rect.leftTop.Y);
        pbFaceListImage.add_img(ctx.lastOutputs[i].croppedData, ctx.lastOutputs[i].croppedDataSize);
      pbFaceListImage.add_img(ctx.lastOutputs[i].croppedData, ctx.lastOutputs[i].croppedDataSize);
        //LOGP(ERROR, "bg output=%f", ctx.lastOutputs[i].score);
      //LOGP(ERROR, "bg output=%f", ctx.lastOutputs[i].score);
        //{
        //    static size_t f = 0;
        //    char fname[50];
        //    sprintf(fname, "/sdcard/face-%u-w%u-h%u.yuv420", ++f, ctx.lastOutputs[i].rectInOriginFrame.width(), ctx.lastOutputs[i].rectInOriginFrame.height());
        //    FILE *pFile = fopen(fname, "wb");
        //    fwrite(ctx.lastOutputs[i].croppedData, 1, ctx.lastOutputs[i].croppedDataSize, pFile);
        //    fclose(pFile);
        //    if (f > 10)exit(0);
        //}
    }
      //{
      //   static size_t f = 0;
      //   char fname[50];
      //   sprintf(fname, "/sdcard/face-%u-w%u-h%u.yuv420", ++f, ctx.lastOutputs[i].rectInOriginFrame.width(), ctx.lastOutputs[i].rectInOriginFrame.height());
      //   FILE *pFile = fopen(fname, "wb");
      //   fwrite(ctx.lastOutputs[i].croppedData, 1, ctx.lastOutputs[i].croppedDataSize, pFile);
      //   fclose(pFile);
      //   if (f > 10)exit(0);
      //}
   }
    size_t s = pbFaceList.ByteSize();
    buffMaxSize = std::min(s, buffMaxSize);
    pbFaceList.SerializeToArray(buffer, buffMaxSize);
   size_t s = pbFaceList.ByteSize();
   buffMaxSize = std::min(s, buffMaxSize);
   pbFaceList.SerializeToArray(buffer, buffMaxSize);
    return buffMaxSize > 0;
   return buffMaxSize > 0;
}
bool FaceCacheForPLBG::getFaceListImage(std::vector<NativeImgIdx>& imgIdxes, uint8_t* buffImg, size_t& buffImgMaxSize)
{
    FcPmBreackerContextPLBG& ctx(*(FcPmBreackerContextPLBG*)_ctx);
    if (ctx.frameTruncated)
    {
        LOG_WARN << "ctx buffer truncated" << LOG_ENDL;
        return false;
    }
    if (buffImgMaxSize < ctx.frameRGBSize)
    {
        LOG_WARN << "buffImg truncated" << LOG_ENDL;
        return false;
    }
   FcPmBreackerContextPLBG& ctx(*(FcPmBreackerContextPLBG*)_ctx);
   if (ctx.frameTruncated)
   {
      LOG_WARN << "ctx buffer truncated" << LOG_ENDL;
      return false;
   }
   if (buffImgMaxSize < ctx.frameRGBSize)
   {
      LOG_WARN << "buffImg truncated" << LOG_ENDL;
      return false;
   }
    imgIdxes.clear();
    size_t totalSize = 0;
   imgIdxes.clear();
   size_t totalSize = 0;
    for (int i = 0; i < ctx.lastOutputs.size(); i++)
    {
        NativeImgIdx imgidx;
        imgidx.offset = ctx.lastOutputsRGBBufs[i].buffer - ctx.frameRGB;
        imgidx.size = ctx.lastOutputsRGBBufs[i].buffSize;
        imgidx.type = MB_Frame::MBFT_RGB565;
        imgidx.width = ctx.lastOutputs[i].rectInOriginFrame.width();
        imgidx.height = ctx.lastOutputs[i].rectInOriginFrame.height();
   for (int i = 0; i < ctx.lastOutputs.size(); i++)
   {
      NativeImgIdx imgidx;
      imgidx.st_track_id =  (int)(int64_t)(ctx.lastOutputs[i].rectInOriginFrame.userData);
      imgidx.offset = ctx.lastOutputsRGBBufs[i].buffer - ctx.frameRGB;
      imgidx.size = ctx.lastOutputsRGBBufs[i].buffSize;
      imgidx.type = MB_Frame::MBFT_RGB565;
      imgidx.width = ctx.lastOutputs[i].rectInOriginFrame.rect.width();
      imgidx.height = ctx.lastOutputs[i].rectInOriginFrame.rect.height();
        imgIdxes.push_back(imgidx);
        totalSize += ctx.lastOutputsRGBBufs[i].buffSize;
    }
      imgIdxes.push_back(imgidx);
      totalSize += ctx.lastOutputsRGBBufs[i].buffSize;
   }
    memcpy(buffImg, ctx.frameRGB, totalSize);
    buffImgMaxSize = totalSize;
   memcpy(buffImg, ctx.frameRGB, totalSize);
   buffImgMaxSize = totalSize;
    return  true;
   return  true;
}