aaa
houxiao
2017-07-24 5e9814a090f20c2b9c39d6efdc9a732b6097ee7d
aaa

git-svn-id: http://192.168.1.226/svn/proxy@865 454eff88-639b-444f-9e54-f578c98de674
1个文件已删除
1个文件已添加
1 文件已重命名
12个文件已修改
880 ■■■■ 已修改文件
RtspFace/PL_AndroidMediaCodecDecoder.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_AndroidMediaCodecDecoder_ndk.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_AndroidSurfaceViewRender.cpp 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_AndroidSurfaceViewRender.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_BlockGrouping.cpp 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_ColorConv.cpp 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_Fork.cpp 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_Fork1.cpp 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_Fork1.h 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_Paint.cpp 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_Scale.cpp 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_Scale.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_SensetimeFaceTrack.cpp 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PipeLine.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/live555/testProgs/testRTSPClient.hpp 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_AndroidMediaCodecDecoder.h
@@ -38,6 +38,8 @@
    bool releaseOutputBuffIdxInPay;
    int generateDecodedDataPerFrame; // 0: do not generate, N: generate every N frame ((G . . .)/N ... (G . . .)/N ...)
    bool ptsUseAbsoluteTime;
    PL_AndroidMediaCodecDecoder_Config() : 
        ak_height(0), 
        ak_mime(), 
@@ -48,7 +50,8 @@
        releaseOutputBuffIdx(true),
        releaseOutputBuffIdxInPay(false), 
        generateDecodedDataPerFrame(0)
        generateDecodedDataPerFrame(0),
        ptsUseAbsoluteTime(false)
    {}
};
RtspFace/PL_AndroidMediaCodecDecoder_ndk.cpp
@@ -343,7 +343,11 @@
                in->lastMbfBuffer.buffSize = in->buffSize;
                in->lastMbfBuffer.width = in->config.ak_width;
                in->lastMbfBuffer.height = in->config.ak_height;
                microseconds_to_timeval(info.presentationTimeUs, in->lastMbfBuffer.pts);
                if (in->config.ptsUseAbsoluteTime)
                    gettimeofday(&(in->lastMbfBuffer.pts), nullptr);
                else
                    microseconds_to_timeval(info.presentationTimeUs, in->lastMbfBuffer.pts);
                //if (in->lastMbfBuffer.buffSize > 10)
                //{
RtspFace/PL_AndroidSurfaceViewRender.cpp
@@ -130,6 +130,9 @@
bool convert_yuv420_origin_to_render(PL_ASVR_Internal* in)
{
    if (in->config.directlyDisplay)
        return true;
    int src_width = in->lastMbfBuffOrigin.width;
    int src_height = in->lastMbfBuffOrigin.height;
    const uint8_t* src_y = (const uint8_t*)(in->lastMbfBuffOrigin.buffer);
@@ -249,35 +252,11 @@
    return true;
}
bool convert_rgb565_origin_to_render(PL_ASVR_Internal *in) {
    ANativeWindow* window = (ANativeWindow*)(in->config.windowSurface);
    int widow_width = ANativeWindow_getWidth(window);
    int window_height = ANativeWindow_getHeight(window);
    int src_width = in->lastMbfBuffOrigin.width;
    int src_height = in->lastMbfBuffOrigin.height;
    if (src_width != widow_width || src_height != window_height)
    {
        uint8_t* src = (uint8_t*)in->lastMbfBuffOrigin.buffer;
        uint8_t* dst = (uint8_t*)in->buffer1;
        libyuv::ScalePlane_16((uint16*)src, src_width,
                              src_width, src_height,
                              (uint16*)dst, widow_width,
                              widow_width, window_height,
                              libyuv::kFilterNone);
        in->buff1Size = widow_width * window_height * 2;
        memcpy(in->buffer, in->buffer1, in->buff1Size);
        in->buffSize = in->buff1Size;
    }
    else
    {
        memcpy(in->buffer, in->lastMbfBuffOrigin.buffer, in->lastMbfBuffOrigin.buffSize);
        in->buffSize = in->lastMbfBuffOrigin.buffSize;
    }
    return true;
}
bool convert_nv12_origin_to_render(PL_ASVR_Internal* in)
{
    if (in->config.directlyDisplay)
        return true;
    if (false)
    {//#test test nv12 on yuv420 frame
        const int src_width = in->lastMbfBuffOrigin.width;
@@ -409,6 +388,42 @@
    return true;
}
bool convert_rgb565_origin_to_render(PL_ASVR_Internal *in)
{
    if (in->config.directlyDisplay)
        return true;
    ANativeWindow* window = (ANativeWindow*)(in->config.windowSurface);
    int src_width = in->lastMbfBuffOrigin.width;
    int src_height = in->lastMbfBuffOrigin.height;
    const int dst_width = (in->config.scaleToWidth <= 0 ? in->nativeWindowStride : in->config.scaleToWidth);
    const int dst_height = (in->config.scaleToHeight <= 0 ? in->nativeWindowHeight : in->config.scaleToHeight);
    if (src_width != dst_width || src_height != dst_height)
    {
        uint8_t* src = (uint8_t*)in->lastMbfBuffOrigin.buffer;
        uint8_t* dst = (uint8_t*)in->buffer1;
        libyuv::ScalePlane_16((uint16*)src, src_width,
                              src_width, src_height,
                              (uint16*)dst, dst_width,
                              dst_width, dst_height,
                              libyuv::kFilterNone);
        in->buff1Size = dst_width * dst_height * 2;
        memcpy(in->buffer, in->buffer1, in->buff1Size);
        in->buffSize = in->buff1Size;
    }
    else
    {
        if (!in->config.directlyDisplay)
        {
            memcpy(in->buffer, in->lastMbfBuffOrigin.buffer, in->lastMbfBuffOrigin.buffSize);
            in->buffSize = in->lastMbfBuffOrigin.buffSize;
        }
    }
    return true;
}
bool render_surface(PL_ASVR_Internal* in)
{
    ANativeWindow* window = (ANativeWindow*)(in->config.windowSurface);
@@ -422,18 +437,23 @@
            bitsSize = buffer.stride * buffer.height * 2;
        else
            bitsSize = buffer.stride * buffer.height;
        if (bitsSize > in->buffSize)
        if (in->config.directlyDisplay)
            memcpy(buffer.bits, in->lastMbfBuffOrigin.buffer,  bitsSize);
        else
        {
            LOG_WARN << "surface buffer truncated" << LOG_ENDL;
            bitsSize = in->buffSize;
        }
        else if (bitsSize < in->buffSize)
        {
            LOG_WARN << "in buffer truncated" << LOG_ENDL;
            if (bitsSize > in->buffSize)
            {
                LOG_WARN << "surface buffer truncated" << LOG_ENDL;
                bitsSize = in->buffSize;
            }
            else if (bitsSize < in->buffSize)
            {
                LOG_WARN << "in buffer truncated" << LOG_ENDL;
            }
            memcpy(buffer.bits, in->buffer, bitsSize);
        }
        memcpy(buffer.bits, in->buffer,  bitsSize);
        ANativeWindow_unlockAndPost(window);
    }
    else
@@ -512,7 +532,7 @@
    if (in->payError)
        pm.breake(PipeMaterial::PMT_FRAME_LIST, MB_Frame::MBFT_YUV420, PL_AndroidSurfaceViewRender::pay_breaker_MBFT_YUV, in);
    if (in->payError)
    pm.breake(PipeMaterial::PMT_FRAME_LIST, MB_Frame::MBFT_NV12, PL_AndroidSurfaceViewRender::pay_breaker_MBFT_YUV, in);
        pm.breake(PipeMaterial::PMT_FRAME_LIST, MB_Frame::MBFT_NV12, PL_AndroidSurfaceViewRender::pay_breaker_MBFT_YUV, in);
    if (in->payError)
        pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_YUV420, PL_AndroidSurfaceViewRender::pay_breaker_MBFT_YUV, in);
    if (in->payError)
RtspFace/PL_AndroidSurfaceViewRender.h
@@ -10,13 +10,15 @@
    bool outputRenderFrame;
    int scaleToWidth; // <=0 to fit size by windowSurfaceDecode
    int scaleToHeight;
    bool directlyDisplay;
    
    PL_AndroidSurfaceViewRender_Config() : 
        windowSurface(nullptr),
        outputOriginFrame(false),
        outputRenderFrame(true),
        scaleToWidth(0),
        scaleToHeight(0)
        scaleToHeight(0),
        directlyDisplay(false)
    {}
};
RtspFace/PL_BlockGrouping.cpp
@@ -469,8 +469,11 @@
    cv::Mat yMat(cv::Size(w, h), CV_8UC1, block.croppedData);
    cv::Mat edges;
    cv::GaussianBlur(yMat, edges, cv::Size(5, 5), 1.5, 1.5);
    cv::Canny(edges, edges, 0, 30, 3);
    cv::GaussianBlur(yMat, edges, cv::Size(5, 5), 1.5, 1.5);
    //cv::Canny(edges, edges, 50, 100, 3);
    cv::Sobel(yMat, edges, CV_8UC1, 1, 0, 3);
    //memcpy(block.croppedData, edges.data, w * h);
    size_t sum = 0;
    std::for_each(edges.begin<uint8_t>(), edges.end<uint8_t>(), [&](uint8_t v)
RtspFace/PL_ColorConv.cpp
@@ -3,7 +3,7 @@
#include "logger.h"
#include <libyuv.h>
#include <PbFaceList.pb.h>
#define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a))
struct PL_ColorConv_Internal
{
    uint8_t* buffer;
@@ -94,7 +94,7 @@
        in->buffer = new uint8_t[dstSize];
        in->buffSizeMax = dstSize;
        in->buffSize = dstSize;
        LOG_INFO << "image_scale alloc buffer size=" << dstSize << std::endl;
        LOG_INFO << "image_to_rgb565 alloc buffer size=" << dstSize << std::endl;
    }
    if (srcType == MB_Frame::MBFT_YUV420)
@@ -105,10 +105,10 @@
    }
    else if (srcType == MB_Frame::MBFT_NV12)
    {
        const uint8_t * srcBuffer = (uint8_t *)in->tempFrame.buffer;
        const uint8_t *src_y = srcBuffer;
        const uint8_t *src_uv =  src_y + (srcHeight * srcWidth);
        uint8_t *dst = (uint8_t *) (in->buffer);
        const uint8_t* srcBuffer = (uint8_t*)in->tempFrame.buffer;
        const uint8_t* src_y = srcBuffer;
        const uint8_t* src_uv =  src_y + (srcHeight * srcWidth);
        uint8_t* dst = (uint8_t*)(in->buffer);
        libyuv::NV12ToRGB565(src_y, srcWidth,
                             src_uv, srcWidth,
                             dst, srcWidth * 2,
RtspFace/PL_Fork.cpp
File was deleted
RtspFace/PL_Fork1.cpp
New file
@@ -0,0 +1,122 @@
#include "PL_Fork1.h"
#include "MaterialBuffer.h"
#include "logger.h"
struct PL_Fork1_Internal
{
    //uint8_t buffer[1920*1080*4];
    //size_t buffSize;
    //size_t buffSizeMax;
    PipeMaterial lastPm;
    MB_Frame lastFrame;
    PL_Fork1_Config config;
    bool payError;
    PL_Fork1_Internal() :
        //buffSize(0), buffSizeMax(sizeof(buffer)),
        lastPm(), lastFrame(), config(), payError(true)
    {
    }
    ~PL_Fork1_Internal()
    {
    }
    void reset()
    {
        //buffSize = 0;
        payError = true;
        PipeMaterial _lastPm;
        lastPm = _lastPm;
        MB_Frame _lastFrame;
        lastFrame = _lastFrame;
        PL_Fork1_Config _config;
        config = _config;
    }
};
PipeLineElem* create_PL_Fork1()
{
    return new PL_Fork1;
}
PL_Fork1::PL_Fork1() : internal(new PL_Fork1_Internal), pl(nullptr)
{
}
PL_Fork1::~PL_Fork1()
{
    delete (PL_Fork1_Internal*)internal;
    internal= nullptr;
}
bool PL_Fork1::init(void* args)
{
    PL_Fork1_Internal* in = (PL_Fork1_Internal*)internal;
    in->reset();
    if (args == nullptr)
    {
        LOG_ERROR << "Config should give" << std::endl;
        return false;
    }
    PL_Fork1_Config* config = (PL_Fork1_Config*)args;
    in->config = *config;
    return true;
}
void PL_Fork1::finit()
{
    PL_Fork1_Internal* in = (PL_Fork1_Internal*)internal;
}
bool PL_Fork1::pay(const PipeMaterial& pm)
{
    PL_Fork1_Internal* in = (PL_Fork1_Internal*)internal;
    PL_Fork1_Config& config(in->config);
    in->lastPm = pm;
    return false;
}
bool PL_Fork1::gain(PipeMaterial& pm)
{
    PL_Fork1_Internal* in = (PL_Fork1_Internal*)internal;
    return false;
}
void PL_Fork1::attach_pipe_line(PipeLine* pl)
{
    PL_Fork1_Internal* in = (PL_Fork1_Internal*)internal;
    if (this->pl != nullptr)
    {
        LOG_ERROR << "Has areadly attached pipe line" << std::endl;
        return;
    }
    if (pl == nullptr)
    {
        LOG_NOTICE << "Detach pipe line" << std::endl;
        this->pl->remove_elem(this);
        this->pl = nullptr;
        return;
    }
    this->pl = pl;
    PipeLine* mainPipeLineManager = this->manager;
    pl->push_front_elem(this);
    this->manager = mainPipeLineManager;
}
RtspFace/PL_Fork1.h
File was renamed from RtspFace/PL_Fork.h
@@ -1,11 +1,11 @@
#ifndef _PL_FORK_H_
#define _PL_FORK_H_
#ifndef _PL_FORK1_H_
#define _PL_FORK1_H_
#include "PipeLine.h"
// p1e1 p1e2<fork> p1e3 ... p1eN
//                 p2e1  p2e2... p2eN
class PL_Fork : public PipeLineElem
class PL_Fork1 : public PipeLineElem
{
public:
    enum ForkBy
@@ -49,8 +49,8 @@
    };
public:
    PL_Fork();
    virtual ~PL_Fork();
    PL_Fork1();
    virtual ~PL_Fork1();
    virtual bool init(void* args);
    virtual void finit();
@@ -65,19 +65,19 @@
    PipeLine* pl;
};
struct PL_Fork_Config
struct PL_Fork1_Config
{
    PL_Fork::ForkBy forkBy;
    PL_Fork::ForkSync forkSync;
    PL_Fork1::ForkBy forkBy;
    PL_Fork1::ForkSync forkSync;
    
    int mainPLType;
    int branchPLType;
    
    PL_Fork_Config() :
        forkBy(PL_Fork::FB_NONE), forkSync(PL_Fork::FS_NONE), mainPLType(0), branchPLType(0)
    PL_Fork1_Config() :
        forkBy(PL_Fork1::FB_NONE), forkSync(PL_Fork1::FS_NONE), mainPLType(0), branchPLType(0)
    { }
};
PipeLineElem* create_PL_Fork();
PipeLineElem* create_PL_Fork1();
#endif
RtspFace/PL_Paint.cpp
@@ -308,7 +308,7 @@
#endif
}
bool plplExecutor_YUV(PL_Paint_Internal *in)
bool plpl_executor(PL_Paint_Internal *in)
{
    MB_Frame* paintMb = &(in->lastMbfBuffOrigin);
    int ret = true;
@@ -426,7 +426,7 @@
    in->lastMbfBuffOrigin.height = frame->height;
    in->lastMbfBuffOrigin.pts = frame->pts;
    in->payError = !plplExecutor_YUV(in);
    in->payError = !plpl_executor(in);
    return false;
}
@@ -435,29 +435,12 @@
{
    PL_Paint_Internal* in = (PL_Paint_Internal*)internal;
    in->payError = true;
    if (pm.type != PipeMaterial::PMT_FRAME)
    {
        LOG_ERROR << "Only support PMT_FRAME" << LOG_ENDL;
        return false;
    }
    if (pm.buffer == nullptr)
        return false;
    MB_Frame* frame = (MB_Frame*)pm.buffer;
    switch(frame->type)
    {
        case MB_Frame::MBFT_YUV420:
        case MB_Frame::MBFT_NV12:
        case MB_Frame::MBFT_RGB565:
            pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_RGB565, PL_Paint::pay_breaker_MBFT, in);
            return !(in->payError);
        default:
            LOG_ERROR << "Only support MBFT_YUV420 / MBFT_NV12 / MBFT_RGB565" << LOG_ENDL;
            in->payError = true;
            break;
    }
    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);
}
RtspFace/PL_Scale.cpp
@@ -1,9 +1,8 @@
#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
{
@@ -41,12 +40,11 @@
        PL_Scale_Config _config;
        config = _config;
        if (buffer != nullptr)
        {
        if (buffSizeMax > 0)
            delete[] buffer;
            buffer = nullptr;
            buffSizeMax = 0;
        }
        buffer = nullptr;
        buffSizeMax = 0;
    }
};
@@ -91,31 +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)
{
    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)
@@ -129,12 +136,12 @@
        
        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));
            
@@ -144,125 +151,82 @@
    {
        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;
RtspFace/PL_Scale.h
@@ -5,6 +5,8 @@
struct PL_Scale_Config
{
    bool copyData;
    uint16_t toWidth;
    uint16_t toHeight;
    int filterMode; // libyuv/scale.h/FilterMode 
@@ -13,10 +15,11 @@
    int defaultBytesType; // MBFT_YUV420 / MBFT_BGRA
    uint16_t defaultBytesWidth;
    uint16_t defaultBytesHeight;
    PL_Scale_Config() :
        toWidth(0), toHeight(0), filterMode(0),
        defaultBytesType(0), defaultBytesWidth(0), defaultBytesHeight(0)
    PL_Scale_Config() :
            copyData(true),
            toWidth(0), toHeight(0), filterMode(0),
            defaultBytesType(0), defaultBytesWidth(0), defaultBytesHeight(0)
    { }
};
@@ -34,6 +37,8 @@
    
private:
    void* internal;
    static bool pay_breaker_MBFT(const PipeMaterial* pm, void* args);
};
PipeLineElem* create_PL_Scale();
RtspFace/PL_SensetimeFaceTrack.cpp
@@ -20,40 +20,40 @@
    st_ff_vect_t faceFeatures;
    bool payError;
    cv_handle_t handle_track;
    size_t frameCount;
    PL_SensetimeFaceTrack_Internal() :
        //buffSize(0), buffSizeMax(sizeof(buffer)),
        lastFrame(), pmList(), config(), faceFeatures(), payError(true),
        handle_track(nullptr),
        frameCount(0)
    PL_SensetimeFaceTrack_Internal() :
    //buffSize(0), buffSizeMax(sizeof(buffer)),
            lastFrame(), pmList(), config(), faceFeatures(), payError(true),
            handle_track(nullptr),
            frameCount(0)
    {
    }
    ~PL_SensetimeFaceTrack_Internal()
    {
    }
    void reset()
    {
        //buffSize = 0;
        payError = true;
        MB_Frame _lastFrame;
        lastFrame = _lastFrame;
        PipeMaterial _pm;
        pmList[0] = _pm;
        pmList[1] = _pm;
        SensetimeFaceTrackConfig _config;
        config = _config;
        handle_track = nullptr;
        frameCount = 0;
    }
};
@@ -77,7 +77,7 @@
{
    PL_SensetimeFaceTrack_Internal* in = (PL_SensetimeFaceTrack_Internal*)internal;
    in->reset();
#ifdef __ANDROID__
    {
        bool retLic = false;
@@ -123,7 +123,7 @@
        }
    }
#endif
    SensetimeFaceTrackConfig* config = (SensetimeFaceTrackConfig*)args;
    in->config = *config;
    if (in->config.point_size == 21)
@@ -145,8 +145,8 @@
    // per detect in RK3288: 800ms@1920w,200ms@640w; with CV_FACE_TRACKING_TWO_THREAD 10ms@1920w
    // init handle
    cv_result_t cv_result = cv_face_create_tracker(&(in->handle_track), nullptr,
                                in->config.point_size_config | CV_FACE_TRACKING_TWO_THREAD); // CV_FACE_TRACKING_TWO_THREAD | CV_FACE_RESIZE_IMG_XXXX
    cv_result_t cv_result = cv_face_create_tracker(&(in->handle_track), nullptr,
                                                   in->config.point_size_config | CV_FACE_TRACKING_TWO_THREAD); // CV_FACE_TRACKING_TWO_THREAD | CV_FACE_RESIZE_IMG_XXXX
    if (cv_result != CV_OK)
    {
        LOG_ERROR << "cv_face_create_tracker failed, error code" << cv_result << LOG_ENDL;
@@ -162,14 +162,14 @@
    }
    else
        LOG_ERROR << "detect face count limit : " << val << LOG_ENDL;
    return true;
}
void PL_SensetimeFaceTrack::finit()
{
    PL_SensetimeFaceTrack_Internal* in = (PL_SensetimeFaceTrack_Internal*)internal;
    // destroy track handle
    cv_face_destroy_tracker(in->handle_track);
    in->handle_track = nullptr;
@@ -189,27 +189,26 @@
                 << p_face[i].rect.bottom << "\t";
        dumpfile << p_face[i].score << "\t"
                << p_face[i].points_count << "\t"
                << p_face[i].yaw << "\t"
                << p_face[i].pitch << "\t"
                << p_face[i].roll << "\t"
                << p_face[i].eye_dist << "\t"
                << p_face[i].ID << "\t";
                 << p_face[i].points_count << "\t"
                 << p_face[i].yaw << "\t"
                 << p_face[i].pitch << "\t"
                 << p_face[i].roll << "\t"
                 << p_face[i].eye_dist << "\t"
                 << p_face[i].ID << "\t";
        cv_pointf_t points_array[256];
        for (int j = 0; j < p_face[i].points_count; j++)
        {
            dumpfile << p_face[i].points_array[j].x << "\t"
                    << p_face[i].points_array[j].y << "\t";
                     << p_face[i].points_array[j].y << "\t";
        }
        dumpfile << std::endl;
    }
}
int doFaceTrack(PL_SensetimeFaceTrack_Internal* in,
                uint8_t* buffer, size_t width, size_t height, size_t stride, cv_pixel_format cvPixFmt)
int doFaceTrack(PL_SensetimeFaceTrack_Internal* in, MB_Frame* frame)
{
    //PipeLineElemTimingDebugger td(nullptr);
@@ -218,16 +217,39 @@
    if (in->frameCount % in->config.doTrackPerFrame != 0)
        return 0;
    //if (true)
    //{
    //    struct timeval now;
    //    gettimeofday(&now, nullptr);
    //    const int fps = 20;
    //    const int ft = 1000 / fps; // ms
    //    if (now.tv_usec - frame->pts.tv_usec > 0.5 * ft * 1000)
    //        return 0;
    //}
    //resize(bgr_frame, bgr_frame, Size(frame_width, frame_height), 0, 0, INTER_LINEAR);
    uint8_t* buffer = (uint8_t*)frame->buffer;
    const size_t width = frame->width;
    const size_t height = frame->height;
    const size_t stride = frame->width;
    cv_pixel_format cvPixFmt;
    if (frame->type == MB_Frame::MBFT_YUV420)
        cvPixFmt = CV_PIX_FMT_YUV420P;
    else if (frame->type == MB_Frame::MBFT_NV12)
        cvPixFmt = CV_PIX_FMT_NV12;
    else
        return -1;
    int face_count = 0;
    cv_result_t cv_result = CV_OK;
    cv_face_t* p_face = nullptr;
    //#test
    //cvPixFmt = CV_PIX_FMT_GRAY8;
    // realtime track
    cv_result = cv_face_track(in->handle_track, buffer, cvPixFmt,
                            width, height, stride,
                            CV_FACE_UP, &p_face, &face_count);
    cv_result = cv_face_track(in->handle_track, buffer, cvPixFmt, width, height, stride, CV_FACE_UP, &p_face, &face_count);
    if (cv_result != CV_OK)
    {
        LOG_ERROR << "cv_face_track failed, error : " << cv_result << LOG_ENDL;
@@ -263,27 +285,27 @@
        faceFeature.eyeDistance = p_face[i].eye_dist;
        LOGP(DEBUG, "face: %d-----[%d, %d, %d, %d]-----id: %d", i,
            p_face[i].rect.left, p_face[i].rect.top,
            p_face[i].rect.right, p_face[i].rect.bottom, p_face[i].ID);
             p_face[i].rect.left, p_face[i].rect.top,
             p_face[i].rect.right, p_face[i].rect.bottom, p_face[i].ID);
        LOGP(DEBUG, "face pose: [yaw: %.2f, pitch: %.2f, roll: %.2f, eye distance: %.2f]",
            p_face[i].yaw,
            p_face[i].pitch, p_face[i].roll, p_face[i].eye_dist);
             p_face[i].yaw,
             p_face[i].pitch, p_face[i].roll, p_face[i].eye_dist);
#ifdef USE_OPENCV
        if (in->config.draw_face_rect)
        {
            cv::Scalar scalar_color = CV_RGB(p_face[i].ID * 53 % 256,
                p_face[i].ID * 93 % 256,
                p_face[i].ID * 143 % 256);
                                             p_face[i].ID * 93 % 256,
                                             p_face[i].ID * 143 % 256);
            //cv::rectangle(yMat, cv::Point2f(0, 0), cv::Point2f(50, 50), scalar_color, 2);
            //cv::rectangle(yMat, cv::Point2f(500, 500), cv::Point2f(550, 550), scalar_color, 2);
            cv::rectangle(yMat, cv::Point2f(static_cast<float>(p_face[i].rect.left),
                static_cast<float>(p_face[i].rect.top)),
                cv::Point2f(static_cast<float>(p_face[i].rect.right),
                static_cast<float>(p_face[i].rect.bottom)), scalar_color, 2);
                                            static_cast<float>(p_face[i].rect.top)),
                          cv::Point2f(static_cast<float>(p_face[i].rect.right),
                                      static_cast<float>(p_face[i].rect.bottom)), scalar_color, 2);
        }
#endif
@@ -320,7 +342,7 @@
        }
        if (faceFeature.rect.leftTop.X < 0 || faceFeature.rect.rightBottom.X > width ||
                faceFeature.rect.leftTop.Y < 0 || faceFeature.rect.rightBottom.Y > height)
            faceFeature.rect.leftTop.Y < 0 || faceFeature.rect.rightBottom.Y > height)
            faceFeature.outOfFrame = true;
        if (in->config.generate_face_feature)
@@ -397,7 +419,7 @@
    //    faceFeature.rect.rightBottom.x = 50+128;
    //    faceFeature.rect.rightBottom.y = 50+128;
    //    in->faceFeatures.push_back(faceFeature);
    //
    //
    //    faceFeature.rect.leftTop.x = 300;
    //    faceFeature.rect.leftTop.y = 400;
    //    faceFeature.rect.rightBottom.x = 300+50;
@@ -418,10 +440,10 @@
        LOG_ERROR << "Only support PMT_FRAME" << LOG_ENDL;
        return false;
    }
    if (pm->buffer == nullptr)
        return false;
    MB_Frame* frame = (MB_Frame*)pm->buffer;
    if (frame->type != MB_Frame::MBFT_YUV420 && frame->type != MB_Frame::MBFT_NV12)
    {
@@ -431,10 +453,8 @@
    in->faceFeatures.clear();
    int face_count = 0;
    if (frame->type == MB_Frame::MBFT_YUV420)
        face_count = doFaceTrack(in, (uint8_t*)frame->buffer, frame->width, frame->height, frame->width, CV_PIX_FMT_YUV420P);
    else if (frame->type == MB_Frame::MBFT_NV12)
        face_count = doFaceTrack(in, (uint8_t*)frame->buffer, frame->width, frame->height, frame->width, CV_PIX_FMT_NV12);
    if (frame->type == MB_Frame::MBFT_YUV420 || frame->type == MB_Frame::MBFT_NV12)
        face_count = doFaceTrack(in, frame);
    if (face_count < 0)
    {
@@ -443,7 +463,7 @@
    }
    else
        in->payError = false;
    //in->buffer readly
    in->lastFrame.type = frame->type;
@@ -452,7 +472,7 @@
    in->lastFrame.width = frame->width;
    in->lastFrame.height = frame->height;
    in->lastFrame.pts = frame->pts;
    return false;
}
@@ -472,7 +492,7 @@
        pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_NV12, PL_SensetimeFaceTrack::pay_breaker_MBFT_YUV, in);
    in->frameCount++;
    return !(in->payError);
}
@@ -498,17 +518,17 @@
        in->pmList[0].buffer = &(in->lastFrame);
        in->pmList[0].buffSize = 0;
        in->pmList[0].former = this;
        in->pmList[1].type = PipeMaterial::PMT_PTR;
        in->pmList[1].buffer = &(in->faceFeatures);
        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;
}
RtspFace/PipeLine.h
@@ -130,7 +130,7 @@
class PipeLineElemTimingDebugger
{
public:
    PipeLineElemTimingDebugger(const PipeLineElem* _elem);
    PipeLineElemTimingDebugger(const PipeLineElem* _elem = nullptr);
    ~PipeLineElemTimingDebugger();
    
    const PipeLineElem* elem;
RtspFace/live555/testProgs/testRTSPClient.hpp
@@ -36,6 +36,8 @@
// Define the size of the buffer that we'll use:
#define DUMMY_SINK_RECEIVE_BUFFER_SIZE 1920*1080*3//#todo
#define INCREASE_RECEIVE_BUFFER_TO 8000000
// If you don't want to see debugging output for each received frame, then comment out the following line:
//#define DEBUG_PRINT_EACH_RECEIVED_FRAME 1
//#define DEBUG_PRINT_NPT 1
@@ -302,44 +304,50 @@
    scs.subsession = scs.iter->next();
    if (scs.subsession != NULL)
    {
        if (_ourRTSPClient->desiredPortNum != 0)
        {
            if (_ourRTSPClient->desiredPortNum != 0)
            {
                scs.subsession->setClientPortNum(_ourRTSPClient->desiredPortNum);
                _ourRTSPClient->desiredPortNum += 2;
            }
            if (!scs.subsession->initiate())
                {
                    LOG_ERROR << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << LOG_ENDL;
                    setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
                }
            else
                {
                    LOG_INFO <<  *rtspClient << "Initiated the \"" << *scs.subsession << "\" subsession (" << LOG_ENDL;
                    if (scs.subsession->rtcpIsMuxed())
                        LOG_INFO <<  "client port " << scs.subsession->clientPortNum() << LOG_ENDL;
                    else
                        LOG_INFO <<  "client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << LOG_ENDL;
                    LOG_INFO <<  ")" << LOG_ENDL;
                    // Continue setting up this subsession, by sending a RTSP "SETUP" command:
                    rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, _ourRTSPClient->rtspConfig.requestStreamingOverTcp);
                }
            return;
            scs.subsession->setClientPortNum(_ourRTSPClient->desiredPortNum);
            _ourRTSPClient->desiredPortNum += 2;
        }
        if (!scs.subsession->initiate())
        {
            LOG_ERROR << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << LOG_ENDL;
            setupNextSubsession(rtspClient); // give up on this subsession; go to the next one
        }
        else
        {
            LOG_INFO <<  *rtspClient << "Initiated the \"" << *scs.subsession << "\" subsession (" << LOG_ENDL;
            if (scs.subsession->rtcpIsMuxed())
                LOG_INFO <<  "client port " << scs.subsession->clientPortNum() << LOG_ENDL;
            else
                LOG_INFO <<  "client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << LOG_ENDL;
            LOG_INFO <<  ")" << LOG_ENDL;
#ifdef INCREASE_RECEIVE_BUFFER_TO
            //sysctl net.core.rmem_max=40000000
            if (INCREASE_RECEIVE_BUFFER_TO > 0)
                increaseReceiveBufferTo(env, scs.subsession->rtpSource()->RTPgs()->socketNum(), INCREASE_RECEIVE_BUFFER_TO);
#endif
            // Continue setting up this subsession, by sending a RTSP "SETUP" command:
            rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, _ourRTSPClient->rtspConfig.requestStreamingOverTcp);
        }
        return;
    }
    // We've finished setting up all of the subsessions.  Now, send a RTSP "PLAY" command to start the streaming:
    if (scs.session->absStartTime() != NULL)
        {
            // Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command:
            rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
        }
    {
        // Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command:
        rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
    }
    else
        {
            scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
            rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
        }
    {
        scs.duration = scs.session->playEndTime() - scs.session->playStartTime();
        rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY);
    }
}
void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString)