From a88698ced8bcd58f0f1918b10380bc66b0bfcbbc Mon Sep 17 00:00:00 2001
From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期五, 30 十二月 2016 18:32:15 +0800
Subject: [PATCH] add pl_scale pl_fork
---
RtspFace/PL_SensetimeFaceFeatureEmit.h | 6
RtspFace/PL_Scale.cpp | 240 +++++++++++++
RtspFace/PL_SensetimeFaceTrack.cpp | 241 +++++++++++++
RtspFace/main.cpp | 48 ++
RtspFace/PL_SensetimeFaceDetect.h | 31 -
RtspFace/PL_SensetimeFaceDetect.cpp | 230 ------------
RtspFace/PipeLine.cpp | 12
RtspFace/PL_Fork.h | 24 +
RtspFace/make.sh | 8
RtspFace/PL_SensetimeFaceTrack.h | 39 ++
RtspFace/PL_Scale.h | 41 ++
RtspFace/PL_Paint.h | 24 +
RtspFace/PL_Fork.cpp | 49 ++
RtspFace/PL_H264Encoder.cpp | 21
RtspFace/logger.h | 17
15 files changed, 743 insertions(+), 288 deletions(-)
diff --git a/RtspFace/PL_Fork.cpp b/RtspFace/PL_Fork.cpp
new file mode 100644
index 0000000..9bf79c3
--- /dev/null
+++ b/RtspFace/PL_Fork.cpp
@@ -0,0 +1,49 @@
+#ifndef _PL_FORK_H_
+#define _PL_FORK_H_
+
+#include "PipeLine.h"
+
+struct PL_Fork_Config
+{
+
+};
+
+class PL_Fork : public PipeLineElem
+{
+public:
+ enum ForkBy
+ {
+ FB_NONE,
+ FB_TURNS,
+ FB_RANDOM,
+ FB_PM_TYPE,
+ FB_MB_TYPE,
+ FB_BREAK_LIST
+ };
+
+ enum ForkSync
+ {
+ FS_NONE,
+ FS_SEQUENCE,
+ FS_PARALLEL,
+ FS_MAIN_PL_FIRST,
+ FS_MAIN_PL_LAST,
+ };
+
+public:
+ PL_Fork();
+ virtual ~PL_Fork();
+
+ virtual bool init(void* args);
+ virtual void finit();
+
+ virtual bool pay(const PipeMaterial& pm);
+ virtual bool gain(PipeMaterial& pm);
+
+private:
+ void* internal;
+};
+
+PipeLineElem* create_PL_Paint();
+
+#endif
diff --git a/RtspFace/PL_Fork.h b/RtspFace/PL_Fork.h
new file mode 100644
index 0000000..865044e
--- /dev/null
+++ b/RtspFace/PL_Fork.h
@@ -0,0 +1,24 @@
+#ifndef _PL_FORK_H_
+#define _PL_FORK_H_
+
+#include "PipeLine.h"
+
+class PL_Fork : public PipeLineElem
+{
+public:
+ PL_Fork();
+ virtual ~PL_Fork();
+
+ virtual bool init(void* args);
+ virtual void finit();
+
+ virtual bool pay(const PipeMaterial& pm);
+ virtual bool gain(PipeMaterial& pm);
+
+private:
+ void* internal;
+};
+
+PipeLineElem* create_PL_Paint();
+
+#endif
diff --git a/RtspFace/PL_H264Encoder.cpp b/RtspFace/PL_H264Encoder.cpp
index 1b3123a..a4d3089 100644
--- a/RtspFace/PL_H264Encoder.cpp
+++ b/RtspFace/PL_H264Encoder.cpp
@@ -9,9 +9,9 @@
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavformat/avformat.h>
-
- #include <libyuv.h>
}
+
+#include <libyuv.h>
PL_H264Encoder_Config::PL_H264Encoder_Config() :
inBufferSize(2*1024*1024), // 2MByte
@@ -47,6 +47,8 @@
~H264Encoder_Internal()
{
+ delete[] buffer;
+ buffer = nullptr;
}
void reset()
@@ -67,8 +69,10 @@
pAVFormatContext = nullptr;
if (buffer != nullptr)
+ {
delete[] buffer;
- buffer = new uint8_t[config.inBufferSize];
+ buffer = nullptr;
+ }
}
};
@@ -97,6 +101,8 @@
PL_H264Encoder_Config* config = (PL_H264Encoder_Config*)args;
in->config = *config;
}
+
+ in->buffer = new uint8_t[in->config.inBufferSize];
return true;
}
@@ -235,7 +241,7 @@
{
in->frameCount++;
LOGP(DEBUG, "Succeed to encode (1) frame=%d, size=%d", in->frameCount, pAVPacket.size);
- memcpy(in->buffer, pAVPacket.data, pAVPacket.size);
+ memcpy(in->buffer, pAVPacket.data, pAVPacket.size);//#todo check inBufferSize
in->buffSize = pAVPacket.size;
av_free_packet(&pAVPacket);
}
@@ -361,8 +367,11 @@
in->lastFrame.buffSize = in->buffSize;
in->lastFrame.width = frame->width;
in->lastFrame.height = frame->height;
- in->lastFrame.pts = frame->pts;
- //#todo resetPts
+
+ if (in->config.resetPTS)
+ gettimeofday(&(in->lastFrame.pts),NULL);
+ else
+ in->lastFrame.pts = frame->pts;
}
return ret;
diff --git a/RtspFace/PL_Paint.h b/RtspFace/PL_Paint.h
new file mode 100644
index 0000000..9421a02
--- /dev/null
+++ b/RtspFace/PL_Paint.h
@@ -0,0 +1,24 @@
+#ifndef _PL_PAINT_H_
+#define _PL_PAINT_H_
+
+#include "PipeLine.h"
+
+class PL_Paint : public PipeLineElem
+{
+public:
+ PL_Paint();
+ virtual ~PL_Paint();
+
+ virtual bool init(void* args);
+ virtual void finit();
+
+ virtual bool pay(const PipeMaterial& pm);
+ virtual bool gain(PipeMaterial& pm);
+
+private:
+ void* internal;
+};
+
+PipeLineElem* create_PL_Paint();
+
+#endif
diff --git a/RtspFace/PL_Scale.cpp b/RtspFace/PL_Scale.cpp
new file mode 100644
index 0000000..bd6c507
--- /dev/null
+++ b/RtspFace/PL_Scale.cpp
@@ -0,0 +1,240 @@
+#include "PL_Scale.h"
+#include "MaterialBuffer.h"
+#include "logger.h"
+
+#include <libyuv.h>
+
+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";
+ 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";
+ 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;
+ }
+
+ 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";
+ 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";
+ 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";
+ return false;
+ }
+ }
+ break;
+ default:
+ LOG_ERROR << "Only support PMT_BYTES / PMT_FRAME";
+ 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";
+ }
+
+ pm = newPm;
+ return !in->payError;
+}
diff --git a/RtspFace/PL_Scale.h b/RtspFace/PL_Scale.h
new file mode 100644
index 0000000..76e00b5
--- /dev/null
+++ b/RtspFace/PL_Scale.h
@@ -0,0 +1,41 @@
+#ifndef _PL_SCALE_H_
+#define _PL_SCALE_H_
+
+#include "PipeLine.h"
+
+struct PL_Scale_Config
+{
+ uint16_t toWidth;
+ uint16_t toHeight;
+ int filterMode; // libyuv/scale.h/FilterMode
+
+ // Used only pm.type==PMT_BYTES
+ 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)
+ { }
+};
+
+class PL_Scale : public PipeLineElem
+{
+public:
+ PL_Scale();
+ virtual ~PL_Scale();
+
+ virtual bool init(void* args);
+ virtual void finit();
+
+ virtual bool pay(const PipeMaterial& pm);
+ virtual bool gain(PipeMaterial& pm);
+
+private:
+ void* internal;
+};
+
+PipeLineElem* create_PL_Scale();
+
+#endif
diff --git a/RtspFace/PL_SensetimeFaceDetect.cpp b/RtspFace/PL_SensetimeFaceDetect.cpp
index 435bea3..cc04c79 100644
--- a/RtspFace/PL_SensetimeFaceDetect.cpp
+++ b/RtspFace/PL_SensetimeFaceDetect.cpp
@@ -1,231 +1 @@
#include "PL_SensetimeFaceDetect.h"
-#include "MaterialBuffer.h"
-#include "logger.h"
-
-#include <opencv2/opencv.hpp>
-#include <cv_face.h>
-
-struct PL_SensetimeFaceDetect_Internal
-{
- //uint8_t buffer[1920*1080*4];
- //size_t buffSize;
- //size_t buffSizeMax;
- MB_Frame lastFrame;
- SensetimeFaceDetectConfig config;
-
- bool payError;
-
- cv_handle_t handle_track;
-
- PL_SensetimeFaceDetect_Internal() :
- //buffSize(0), buffSizeMax(sizeof(buffer)),
- lastFrame(), config(), payError(true),
- handle_track(nullptr)
- {
- }
-
- ~PL_SensetimeFaceDetect_Internal()
- {
- }
-
- void reset()
- {
- //buffSize = 0;
- payError = true;
-
- MB_Frame _lastFrame;
- lastFrame = _lastFrame;
- SensetimeFaceDetectConfig _config;
- config = _config;
-
- handle_track = nullptr;
- }
-};
-
-PipeLineElem* create_PL_SensetimeFaceDetect()
-{
- return new PL_SensetimeFaceDetect;
-}
-
-PL_SensetimeFaceDetect::PL_SensetimeFaceDetect() : internal(new PL_SensetimeFaceDetect_Internal)
-{
-}
-
-PL_SensetimeFaceDetect::~PL_SensetimeFaceDetect()
-{
- delete (PL_SensetimeFaceDetect_Internal*)internal;
- internal= nullptr;
-}
-
-bool PL_SensetimeFaceDetect::init(void* args)
-{
- PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
- in->reset();
-
- SensetimeFaceDetectConfig* config = (SensetimeFaceDetectConfig*)args;
- in->config = *config;
- if (in->config.point_size == 21)
- in->config.point_size_config = CV_DETECT_ENABLE_ALIGN_21;
- else if (in->config.point_size == 106)
- in->config.point_size_config = CV_DETECT_ENABLE_ALIGN_106;
- else
- {
- LOG_ERROR << "alignment point size must be 21 or 106";
- return false;
- }
-
- // 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);
- if (cv_result != CV_OK)
- {
- LOG_ERROR << "cv_face_create_tracker failed, error code" << cv_result;
- return false;
- }
-
- int val = 0;
- cv_result = cv_face_track_set_detect_face_cnt_limit(in->handle_track, in->config.detect_face_cnt_limit, &val);
- if (cv_result != CV_OK)
- {
- LOG_ERROR << "cv_face_track_set_detect_face_cnt_limit failed, error : " << cv_result;
- return false;
- }
- else
- LOG_ERROR << "detect face count limit : " << val;
-
- return true;
-}
-
-void PL_SensetimeFaceDetect::finit()
-{
- PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
-
- // destroy track handle
- cv_face_destroy_tracker(in->handle_track);
- in->handle_track = nullptr;
-}
-
-int doFaceDetect(PL_SensetimeFaceDetect_Internal* in,
- uint8_t* buffer, size_t width, size_t height, size_t stride, cv_pixel_format cvPixFmt)
-{
- //resize(bgr_frame, bgr_frame, Size(frame_width, frame_height), 0, 0, INTER_LINEAR);
-
- int face_count = 0;
- cv_result_t cv_result = CV_OK;
- cv_face_t* p_face = nullptr;
-
- // realtime track
- 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;
- cv_face_release_tracker_result(p_face, face_count);
- return -1;
- }
-
- // draw the video
- cv::Mat yuvMat(cv::Size(1920,1080), CV_8UC3, buffer);//#todo
- cv::Mat yMat(cv::Size(1920,1080), CV_8UC1, buffer);
- for (int i = 0; i < face_count; i++)
- {
- 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);
-
- 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);
-
- cv::Scalar scalar_color = CV_RGB(p_face[i].ID * 53 % 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);
-
- for (int j = 0; j < p_face[i].points_count; j++)
- {
- cv::circle(yMat, cv::Point2f(p_face[i].points_array[j].x,
- p_face[i].points_array[j].y), 1, cv::Scalar(255, 255, 255));
- }
- }
-
- //if (face_count > 0)
- //{
- // static size_t f=0;
- // char fname[50];
- // sprintf(fname, "face-%u.yuv420", ++f);
- // FILE * pFile = fopen (fname,"wb");
- // fwrite (yuvMat.data , sizeof(char), 1920*1080*1.5, pFile);
- // printf("write face file %s\n", fname);
- // fclose(pFile);
- //}
-
- // release the memory of face
- cv_face_release_tracker_result(p_face, face_count);
-
- return face_count;
-}
-
-bool PL_SensetimeFaceDetect::pay(const PipeMaterial& pm)
-{
- PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
-
- if (pm.type != PipeMaterial::PMT_FRAME)
- {
- LOG_ERROR << "PL_H264Encoder::pay only support PMT_FRAME";
- return false;
- }
-
- if (pm.buffer == nullptr)
- return false;
-
- MB_Frame* frame = (MB_Frame*)pm.buffer;
- if (frame->type != MB_Frame::MBFT_YUV420)
- {
- LOG_ERROR << "PL_H264Encoder::pay only support MBFT_YUV420";
- return false;
- }
-
- int face_count = doFaceDetect(in, (uint8_t*)frame->buffer, 1920, 1080, 1920, CV_PIX_FMT_YUV420P);//#todo
- if (face_count < 0)
- {
- in->payError = true;
- return false;
- }
- else
- in->payError = false;
-
- //in->buffer readly
-
- in->lastFrame.type = MB_Frame::MBFT_YUV420;
- in->lastFrame.buffer = frame->buffer;//#todo should copy
- in->lastFrame.buffSize = frame->buffSize;
- in->lastFrame.width = frame->width;
- in->lastFrame.height = frame->height;
- in->lastFrame.pts = frame->pts;
-
- return true;
-}
-
-bool PL_SensetimeFaceDetect::gain(PipeMaterial& pm)
-{
- PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
-
- if (!in->payError)
- {
- pm.type = PipeMaterial::PMT_FRAME;
- pm.buffer = &(in->lastFrame);
- pm.buffSize = 0;
- pm.former = this;
- }
- pm.former = this;
- return !in->payError;
-}
diff --git a/RtspFace/PL_SensetimeFaceDetect.h b/RtspFace/PL_SensetimeFaceDetect.h
index 0d876c0..19d48c4 100644
--- a/RtspFace/PL_SensetimeFaceDetect.h
+++ b/RtspFace/PL_SensetimeFaceDetect.h
@@ -1,35 +1,4 @@
#ifndef _PL_PL_SENSETIMEFACEDETECT_H_
#define _PL_PL_SENSETIMEFACEDETECT_H_
-#include "PipeLine.h"
-
-struct SensetimeFaceDetectConfig
-{
- int point_size; // 21 / 106
- int point_size_config; // CV_DETECT_ENABLE_ALIGN_21 / CV_DETECT_ENABLE_ALIGN_106
- int detect_face_cnt_limit; // -1
-
- SensetimeFaceDetectConfig() :
- point_size(21), point_size_config(-1), detect_face_cnt_limit(-1)
- { }
-};
-
-class PL_SensetimeFaceDetect : public PipeLineElem
-{
-public:
- PL_SensetimeFaceDetect();
- virtual ~PL_SensetimeFaceDetect();
-
- virtual bool init(void* args);
- virtual void finit();
-
- virtual bool pay(const PipeMaterial& pm);
- virtual bool gain(PipeMaterial& pm);
-
-private:
- void* internal;
-};
-
-PipeLineElem* create_PL_SensetimeFaceDetect();
-
#endif
diff --git a/RtspFace/PL_SensetimeFaceFeatureEmit.h b/RtspFace/PL_SensetimeFaceFeatureEmit.h
new file mode 100644
index 0000000..c312a0c
--- /dev/null
+++ b/RtspFace/PL_SensetimeFaceFeatureEmit.h
@@ -0,0 +1,6 @@
+#ifndef _PL_SENSETIMEFACEFEATUREEMIT_H_
+#define _PL_SENSETIMEFACEFEATUREEMIT_H_
+
+#include "PipeLine.h"
+
+#endif
diff --git a/RtspFace/PL_SensetimeFaceTrack.cpp b/RtspFace/PL_SensetimeFaceTrack.cpp
new file mode 100644
index 0000000..71cb4d3
--- /dev/null
+++ b/RtspFace/PL_SensetimeFaceTrack.cpp
@@ -0,0 +1,241 @@
+#include "PL_SensetimeFaceTrack.h"
+#include "MaterialBuffer.h"
+#include "logger.h"
+
+#include <opencv2/opencv.hpp>
+#include <cv_face.h>
+
+struct PL_SensetimeFaceTrack_Internal
+{
+ //uint8_t buffer[1920*1080*4];
+ //size_t buffSize;
+ //size_t buffSizeMax;
+ MB_Frame lastFrame;
+ SensetimeFaceTrackConfig config;
+
+ bool payError;
+
+ cv_handle_t handle_track;
+
+ PL_SensetimeFaceTrack_Internal() :
+ //buffSize(0), buffSizeMax(sizeof(buffer)),
+ lastFrame(), config(), payError(true),
+ handle_track(nullptr)
+ {
+ }
+
+ ~PL_SensetimeFaceTrack_Internal()
+ {
+ }
+
+ void reset()
+ {
+ //buffSize = 0;
+ payError = true;
+
+ MB_Frame _lastFrame;
+ lastFrame = _lastFrame;
+ SensetimeFaceTrackConfig _config;
+ config = _config;
+
+ handle_track = nullptr;
+ }
+};
+
+PipeLineElem* create_PL_SensetimeFaceTrack()
+{
+ return new PL_SensetimeFaceTrack;
+}
+
+PL_SensetimeFaceTrack::PL_SensetimeFaceTrack() : internal(new PL_SensetimeFaceTrack_Internal)
+{
+}
+
+PL_SensetimeFaceTrack::~PL_SensetimeFaceTrack()
+{
+ delete (PL_SensetimeFaceTrack_Internal*)internal;
+ internal= nullptr;
+}
+
+bool PL_SensetimeFaceTrack::init(void* args)
+{
+ PL_SensetimeFaceTrack_Internal* in = (PL_SensetimeFaceTrack_Internal*)internal;
+ in->reset();
+
+ SensetimeFaceTrackConfig* config = (SensetimeFaceTrackConfig*)args;
+ in->config = *config;
+ if (in->config.point_size == 21)
+ in->config.point_size_config = CV_DETECT_ENABLE_ALIGN_21;
+ else if (in->config.point_size == 106)
+ in->config.point_size_config = CV_DETECT_ENABLE_ALIGN_106;
+ else
+ {
+ LOG_ERROR << "alignment point size must be 21 or 106";
+ return false;
+ }
+
+ // 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);
+ if (cv_result != CV_OK)
+ {
+ LOG_ERROR << "cv_face_create_tracker failed, error code" << cv_result;
+ return false;
+ }
+
+ int val = 0;
+ cv_result = cv_face_track_set_detect_face_cnt_limit(in->handle_track, in->config.detect_face_cnt_limit, &val);
+ if (cv_result != CV_OK)
+ {
+ LOG_ERROR << "cv_face_track_set_detect_face_cnt_limit failed, error : " << cv_result;
+ return false;
+ }
+ else
+ LOG_ERROR << "detect face count limit : " << val;
+
+ 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;
+}
+
+int doFaceTrack(PL_SensetimeFaceTrack_Internal* in,
+ uint8_t* buffer, size_t width, size_t height, size_t stride, cv_pixel_format cvPixFmt)
+{
+ //resize(bgr_frame, bgr_frame, Size(frame_width, frame_height), 0, 0, INTER_LINEAR);
+
+ int face_count = 0;
+ cv_result_t cv_result = CV_OK;
+ cv_face_t* p_face = nullptr;
+
+ // realtime track
+ 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;
+ cv_face_release_tracker_result(p_face, face_count);
+ return -1;
+ }
+
+ // draw the video
+ //cv::Mat yuvMat(cv::Size(width,height), CV_8UC3, buffer);
+ cv::Mat yMat(cv::Size(width,height), CV_8UC1, buffer);
+ for (int i = 0; i < face_count; i++)
+ {
+ 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);
+
+ 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);
+
+ 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);
+
+ //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);
+ }
+
+
+ for (int j = 0; j < p_face[i].points_count; j++)
+ {
+
+
+ if (in->config.draw_face_feature_point)
+ {
+ cv::circle(yMat, cv::Point2f(p_face[i].points_array[j].x,
+ p_face[i].points_array[j].y), 1, cv::Scalar(255, 255, 255));
+ }
+ }
+ }
+
+ //if (face_count > 0)
+ //{
+ // static size_t f=0;
+ // char fname[50];
+ // sprintf(fname, "face-%u.yuv420", ++f);
+ // FILE * pFile = fopen (fname,"wb");
+ // fwrite (yuvMat.data , sizeof(char), 1920*1080*1.5, pFile);
+ // printf("write face file %s\n", fname);
+ // fclose(pFile);
+ //}
+
+ // release the memory of face
+ cv_face_release_tracker_result(p_face, face_count);
+
+ return face_count;
+}
+
+bool PL_SensetimeFaceTrack::pay(const PipeMaterial& pm)
+{
+ PL_SensetimeFaceTrack_Internal* in = (PL_SensetimeFaceTrack_Internal*)internal;
+
+ if (pm.type != PipeMaterial::PMT_FRAME)
+ {
+ LOG_ERROR << "PL_H264Encoder::pay only support PMT_FRAME";
+ return false;
+ }
+
+ if (pm.buffer == nullptr)
+ return false;
+
+ MB_Frame* frame = (MB_Frame*)pm.buffer;
+ if (frame->type != MB_Frame::MBFT_YUV420)
+ {
+ LOG_ERROR << "PL_H264Encoder::pay only support MBFT_YUV420";
+ return false;
+ }
+
+ int face_count = doFaceTrack(
+ in, (uint8_t*)frame->buffer, frame->width, frame->height, frame->width, CV_PIX_FMT_YUV420P);
+ if (face_count < 0)
+ {
+ in->payError = true;
+ return false;
+ }
+ else
+ in->payError = false;
+
+ //in->buffer readly
+
+ in->lastFrame.type = MB_Frame::MBFT_YUV420;
+ in->lastFrame.buffer = frame->buffer;//#todo should copy
+ in->lastFrame.buffSize = frame->buffSize;
+ in->lastFrame.width = frame->width;
+ in->lastFrame.height = frame->height;
+ in->lastFrame.pts = frame->pts;
+
+ return true;
+}
+
+bool PL_SensetimeFaceTrack::gain(PipeMaterial& pm)
+{
+ PL_SensetimeFaceTrack_Internal* in = (PL_SensetimeFaceTrack_Internal*)internal;
+
+ if (!in->payError)
+ {
+ pm.type = PipeMaterial::PMT_FRAME;
+ pm.buffer = &(in->lastFrame);
+ pm.buffSize = 0;
+ pm.former = this;
+ }
+ pm.former = this;
+ return !in->payError;
+}
diff --git a/RtspFace/PL_SensetimeFaceTrack.h b/RtspFace/PL_SensetimeFaceTrack.h
new file mode 100644
index 0000000..8ce9f5c
--- /dev/null
+++ b/RtspFace/PL_SensetimeFaceTrack.h
@@ -0,0 +1,39 @@
+#ifndef _PL_PL_SENSETIMEFACETRACK_H_
+#define _PL_PL_SENSETIMEFACETRACK_H_
+
+#include "PipeLine.h"
+
+struct SensetimeFaceTrackConfig
+{
+ int point_size; // 21 / 106
+ int point_size_config; // CV_DETECT_ENABLE_ALIGN_21 / CV_DETECT_ENABLE_ALIGN_106
+ int detect_face_cnt_limit; // -1
+ bool draw_face_rect;
+ bool draw_face_feature_point;
+ bool generate_face_feature; // for PL_SensetimeFaceFeatureEmit
+
+ SensetimeFaceTrackConfig() :
+ point_size(21), point_size_config(-1), detect_face_cnt_limit(-1),
+ draw_face_rect(true), draw_face_feature_point(true), generate_face_feature(false)
+ { }
+};
+
+class PL_SensetimeFaceTrack : public PipeLineElem
+{
+public:
+ PL_SensetimeFaceTrack();
+ virtual ~PL_SensetimeFaceTrack();
+
+ virtual bool init(void* args);
+ virtual void finit();
+
+ virtual bool pay(const PipeMaterial& pm);
+ virtual bool gain(PipeMaterial& pm);
+
+private:
+ void* internal;
+};
+
+PipeLineElem* create_PL_SensetimeFaceDetect();
+
+#endif
diff --git a/RtspFace/PipeLine.cpp b/RtspFace/PipeLine.cpp
index 3547d94..1f3aba9 100644
--- a/RtspFace/PipeLine.cpp
+++ b/RtspFace/PipeLine.cpp
@@ -90,16 +90,16 @@
PipeDebugger(PipeLine* _pipeLine) :
pipeLine(_pipeLine), retElem(nullptr), pm(nullptr)
{
- LOG_DEBUG << "pipe line begin";
+ //LOG_DEBUG << "pipe line begin";
}
~PipeDebugger()
{
- bool retOK = (*(pipeLine->elems).rbegin() == retElem);
- if (retOK)
- LOG_DEBUG << "pipe line end, ret OK";
- else
- LOG_WARN << "pipe line end, ret ERROR";
+ //bool retOK = (*(pipeLine->elems).rbegin() == retElem);
+ //if (retOK)
+ // LOG_DEBUG << "pipe line end, ret OK";
+ //else
+ // LOG_WARN << "pipe line end, ret ERROR";
}
};
diff --git a/RtspFace/logger.h b/RtspFace/logger.h
index 5d7b344..b0b0ffa 100644
--- a/RtspFace/logger.h
+++ b/RtspFace/logger.h
@@ -16,6 +16,14 @@
#include "log4cpp/FileAppender.hh"
#include "log4cpp/PatternLayout.hh"
+enum LoggerVerbose
+{
+ LV_ERROR,
+ LV_WARN,
+ LV_NOTICE,
+ LV_INFO,
+ LV_DEBUG
+};
#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << __FILE__ << ":" << __LINE__ << "\t"
#define LOGP(__level, __format, arg...) log4cpp::Category::getRoot().log(log4cpp::Priority::__level, "%s:%d\t" __format, __FILE__, __LINE__, ##arg);
@@ -26,7 +34,7 @@
#define LOG_WARN LOG(WARN) // Important event or input which will lead to errors
#define LOG_ERROR LOG(ERROR) // Error message means program running in an abnormal (not expected) way
-inline void initLogger(int verbose)
+inline void initLogger(LoggerVerbose verbose)
{
// initialize log4cpp
log4cpp::Category &log = log4cpp::Category::getRoot();
@@ -43,8 +51,11 @@
}
switch (verbose)
{
- case 2: log.setPriority(log4cpp::Priority::DEBUG); break;
- case 1: log.setPriority(log4cpp::Priority::INFO); break;
+ case LV_DEBUG: log.setPriority(log4cpp::Priority::DEBUG); break;
+ case LV_INFO: log.setPriority(log4cpp::Priority::INFO); break;
+ case LV_NOTICE: log.setPriority(log4cpp::Priority::NOTICE); break;
+ case LV_WARN: log.setPriority(log4cpp::Priority::WARN); break;
+ case LV_ERROR: log.setPriority(log4cpp::Priority::ERROR); break;
default: log.setPriority(log4cpp::Priority::NOTICE); break;
}
diff --git a/RtspFace/main.cpp b/RtspFace/main.cpp
index 8b87ae0..412c1ac 100644
--- a/RtspFace/main.cpp
+++ b/RtspFace/main.cpp
@@ -6,14 +6,15 @@
#include "PL_AVFrameYUV420.h"
#include "PL_AVFrameBGRA.h"
#include "PL_Queue.h"
+#include "PL_Scale.h"
-#include "PL_SensetimeFaceDetect.h"
+#include "PL_SensetimeFaceTrack.h"
#include "logger.h"
int main(int argc, char** argv)
{
- initLogger(2);
+ initLogger(LV_DEBUG);
PipeLine pipeLine;
@@ -23,8 +24,9 @@
pipeLine.register_elem_creator("PL_AVFrameYUV420", create_PL_AVFrameYUV420);
pipeLine.register_elem_creator("PL_H264Encoder", create_PL_H264Encoder);
pipeLine.register_elem_creator("PL_Queue", create_PL_Queue);
+ pipeLine.register_elem_creator("PL_Scale", create_PL_Scale);
- pipeLine.register_elem_creator("PL_SensetimeFaceDetect", create_PL_SensetimeFaceDetect);
+ pipeLine.register_elem_creator("PL_SensetimeFaceTrack", create_PL_SensetimeFaceTrack);
{
PL_RTSPClient* rtspClient = (PL_RTSPClient*)pipeLine.push_elem("PL_RTSPClient");
@@ -45,18 +47,41 @@
{
PL_H264Decoder* h264Decoder = (PL_H264Decoder*)pipeLine.push_elem("PL_H264Decoder");
- h264Decoder->init(nullptr);
+ bool ret = h264Decoder->init(nullptr);
+ if (!ret)
+ {
+ LOG_ERROR << "PL_H264Decoder.init error";
+ exit(EXIT_FAILURE);
+ }
}
{
PL_AVFrameYUV420* avFrameYUV420 = (PL_AVFrameYUV420*)pipeLine.push_elem("PL_AVFrameYUV420");
- avFrameYUV420->init(nullptr);
+ bool ret = avFrameYUV420->init(nullptr);
+ if (!ret)
+ {
+ LOG_ERROR << "PL_AVFrameYUV420.init error";
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ {
+ PL_Scale_Config config;
+ config.toWidth = 800;
+ config.toHeight = 600;
+ PL_Scale* pl = (PL_Scale*)pipeLine.push_elem("PL_Scale");
+ bool ret = pl->init(&config);
+ if (!ret)
+ {
+ LOG_ERROR << "PL_Scale.init error";
+ exit(EXIT_FAILURE);
+ }
}
{
- SensetimeFaceDetectConfig config;
- PL_SensetimeFaceDetect* stFaceDetect = (PL_SensetimeFaceDetect*)pipeLine.push_elem("PL_SensetimeFaceDetect");
- stFaceDetect->init(&config);
+ SensetimeFaceTrackConfig config;
+ PL_SensetimeFaceTrack* pl = (PL_SensetimeFaceTrack*)pipeLine.push_elem("PL_SensetimeFaceTrack");
+ pl->init(&config);
}
//{//#todo queue should support deep copy
@@ -72,7 +97,12 @@
{
PL_H264Encoder* h264Encoder = (PL_H264Encoder*)pipeLine.push_elem("PL_H264Encoder");
- h264Encoder->init(nullptr);
+ bool ret = h264Encoder->init(nullptr);
+ if (!ret)
+ {
+ LOG_ERROR << "PL_H264Encoder.init error";
+ exit(EXIT_FAILURE);
+ }
}
{
diff --git a/RtspFace/make.sh b/RtspFace/make.sh
index 4a4892f..acdd829 100644
--- a/RtspFace/make.sh
+++ b/RtspFace/make.sh
@@ -51,7 +51,9 @@
g++ -g -c -std=c++11 PL_AVFrameYUV420.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 PL_AVFrameBGRA.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 PL_Queue.cpp $CFLAGS $CPPFLAGS
-g++ -g -c -std=c++11 PL_SensetimeFaceDetect.cpp $CFLAGS $CPPFLAGS
+g++ -g -c -std=c++11 PL_Scale.cpp $CFLAGS $CPPFLAGS
+
+g++ -g -c -std=c++11 PL_SensetimeFaceTrack.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 $FFMPEGRTSPSERVER_BASE/FFmpegH264Source.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 $FFMPEGRTSPSERVER_BASE/LiveRTSPServer.cpp $CFLAGS $CPPFLAGS
@@ -59,8 +61,8 @@
g++ -g -std=c++11 \
main.o PipeLine.o \
- PL_RTSPClient.o PL_H264Decoder.o PL_H264Encoder.o PL_AVFrameYUV420.o PL_AVFrameBGRA.o PL_Queue.o \
- PL_SensetimeFaceDetect.o \
+ PL_RTSPClient.o PL_H264Decoder.o PL_H264Encoder.o PL_AVFrameYUV420.o PL_AVFrameBGRA.o PL_Queue.o PL_Scale.o \
+ PL_SensetimeFaceTrack.o \
$FFMPEGRTSPSERVER_OBJ PL_RTSPServer.o \
$LDFLAGS -o rtsp_face
--
Gitblit v1.8.0