From 91bcfe2c50c8732c1ccf792ca1f8964966808352 Mon Sep 17 00:00:00 2001
From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期二, 10 一月 2017 17:25:40 +0800
Subject: [PATCH] add face daemon
---
RtspFace/face_daemon_proto.h | 37 ++
RtspFace/make.sh | 8
RtspFace/ev_server.cpp | 23 +
RtspFace/ev_server.h | 11
RtspFace/main_face_daemon.cpp | 114 +++++--
RtspFace/PL_Gainer.h | 33 ++
RtspFace/PL_Payer.h | 33 ++
RtspFace/ev_proto.h | 29 +
RtspFace/PL_SensetimeFaceDetect.h | 40 ++
RtspFace/PL_Payer.cpp | 119 +++++++
RtspFace/PL_Gainer.cpp | 153 ++++++++++
RtspFace/PL_SensetimeFaceDetect.cpp | 287 +++++++++++++++++++
12 files changed, 835 insertions(+), 52 deletions(-)
diff --git a/RtspFace/PL_Gainer.cpp b/RtspFace/PL_Gainer.cpp
new file mode 100644
index 0000000..5e423dd
--- /dev/null
+++ b/RtspFace/PL_Gainer.cpp
@@ -0,0 +1,153 @@
+#include "PL_Gainer.h"
+#include "MaterialBuffer.h"
+#include "logger.h"
+
+#include <string.h> // for memcpy
+
+struct PL_Gainer_Internal
+{
+ PL_Gainer_Config config;
+ PipeMaterial lastPm;
+ MB_Frame lastFrame;
+
+ PL_Gainer_Internal() :
+ config(), lastPm(), lastFrame()
+ {
+ }
+
+ ~PL_Gainer_Internal()
+ {
+ }
+
+ void reset()
+ {
+ PL_Gainer_Config _config;
+ config = _config;
+
+ PipeMaterial _lastPm;
+ lastPm = _lastPm;
+
+ MB_Frame _lastFrame;
+ lastFrame = _lastFrame;
+ }
+};
+
+PipeLineElem* create_PL_Gainer()
+{
+ return new PL_Gainer;
+}
+
+PL_Gainer::PL_Gainer() : internal(new PL_Gainer_Internal)
+{
+}
+
+PL_Gainer::~PL_Gainer()
+{
+ delete (PL_Gainer_Internal*)internal;
+ internal= nullptr;
+}
+
+bool PL_Gainer::init(void* args)
+{
+ PL_Gainer_Internal* in = (PL_Gainer_Internal*)internal;
+ in->reset();
+
+ if (args != nullptr)
+ {
+ PL_Gainer_Config* config = (PL_Gainer_Config*)args;
+ in->config = *config;
+ }
+
+ return true;
+}
+
+void PL_Gainer::finit()
+{
+ PL_Gainer_Internal* in = (PL_Gainer_Internal*)internal;
+
+}
+
+void pl_gainer_deleter_func(PipeMaterial* pm)
+{
+ PL_Gainer_Internal* in = (PL_Gainer_Internal*)(pm->args);
+
+ if (in->config.copyData)
+ {
+ switch(pm->type)
+ {
+ case PipeMaterial::PMT_BYTES:
+ {
+ delete[] (uint8_t*)pm->buffer;
+ }
+ break;
+ case PipeMaterial::PMT_FRAME:
+ {
+ MB_Frame* pmFrame = (MB_Frame*)(pm->buffer);
+ delete[] (uint8_t*)pmFrame->buffer;
+ }
+ break;
+ default:
+ //#todo support list or pm::copier operator
+ LOG_ERROR << "Only support PMT_BYTES / PMT_FRAME";
+ return;
+ }
+ }
+
+ PipeMaterial _pm;
+ *pm = _pm;
+}
+
+bool PL_Gainer::pay(const PipeMaterial& pm)
+{
+ return true;
+}
+
+bool PL_Gainer::gain(PipeMaterial& pm)
+{
+ PL_Gainer_Internal* in = (PL_Gainer_Internal*)internal;
+
+ if (in->config.copyData)
+ {
+ PipeMaterial newPm = pm;
+
+ switch(pm.type)
+ {
+ case PipeMaterial::PMT_BYTES:
+ {
+ newPm.buffer = new uint8_t[pm.buffSize];
+ memcpy(newPm.buffer, pm.buffer, pm.buffSize);
+ }
+ break;
+ case PipeMaterial::PMT_FRAME:
+ {
+ MB_Frame* pmFrame = (MB_Frame*)(pm.buffer);
+ in->lastFrame = *pmFrame;
+ in->lastFrame.buffer = new uint8_t[pmFrame->buffSize];
+ memcpy(in->lastFrame.buffer, pmFrame->buffer, pmFrame->buffSize);
+
+ newPm.buffer = &(in->lastFrame);
+ }
+ break;
+ default:
+ //#todo support list or pm::copier operator
+ LOG_ERROR << "Only support PMT_BYTES / PMT_FRAME";
+ return false;
+ }
+
+ newPm.args = in;
+ newPm.deleter = pl_gainer_deleter_func;
+
+ newPm.former = this;
+
+ if (pm.deleter != nullptr)
+ (pm.deleter)(&pm);
+
+ pm = newPm;
+ return true;
+ }
+ else
+ {
+ pm.former = this;
+ return true;
+ }
+}
diff --git a/RtspFace/PL_Gainer.h b/RtspFace/PL_Gainer.h
new file mode 100644
index 0000000..1fc0df3
--- /dev/null
+++ b/RtspFace/PL_Gainer.h
@@ -0,0 +1,33 @@
+#ifndef _PL_Gainer_H_
+#define _PL_Gainer_H_
+
+#include "PipeLine.h"
+
+struct PL_Gainer_Config
+{
+ bool copyData;
+
+ PL_Gainer_Config() :
+ copyData(false)
+ { }
+};
+
+class PL_Gainer : public PipeLineElem
+{
+public:
+ PL_Gainer();
+ virtual ~PL_Gainer();
+
+ 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_Gainer();
+
+#endif
diff --git a/RtspFace/PL_Payer.cpp b/RtspFace/PL_Payer.cpp
new file mode 100644
index 0000000..8ec8239
--- /dev/null
+++ b/RtspFace/PL_Payer.cpp
@@ -0,0 +1,119 @@
+#include "PL_Payer.h"
+#include "MaterialBuffer.h"
+#include "logger.h"
+
+#include <string.h> // for memcpy
+
+struct PL_Payer_Internal
+{
+ PL_Payer_Config config;
+ PipeMaterial lastPm;
+ MB_Frame lastFrame;
+
+ PL_Payer_Internal() :
+ config(), lastPm(), lastFrame()
+ {
+ }
+
+ ~PL_Payer_Internal()
+ {
+ }
+
+ void reset()
+ {
+ PL_Payer_Config _config;
+ config = _config;
+
+ PipeMaterial _lastPm;
+ lastPm = _lastPm;
+
+ MB_Frame _lastFrame;
+ lastFrame = _lastFrame;
+ }
+};
+
+PipeLineElem* create_PL_Payer()
+{
+ return new PL_Payer;
+}
+
+PL_Payer::PL_Payer() : internal(new PL_Payer_Internal)
+{
+}
+
+PL_Payer::~PL_Payer()
+{
+}
+
+bool PL_Payer::init(void* args)
+{
+ PL_Payer_Internal* in = (PL_Payer_Internal*)internal;
+ in->reset();
+
+ if (args != nullptr)
+ {
+ PL_Payer_Config* config = (PL_Payer_Config*)args;
+ in->config = *config;
+ }
+
+ return true;
+}
+
+void PL_Payer::finit()
+{
+ PL_Payer_Internal* in = (PL_Payer_Internal*)internal;
+
+}
+
+void pl_payer_deleter_func(PipeMaterial* pm)
+{//#todo
+}
+
+bool PL_Payer::pay(const PipeMaterial& pm)
+{
+ PL_Payer_Internal* in = (PL_Payer_Internal*)internal;
+
+ in->lastPm = pm;
+
+ if (in->config.copyData)
+ {
+ switch(pm.type)
+ {
+ case PipeMaterial::PMT_BYTES:
+ {
+ in->lastPm.buffer = new uint8_t[pm.buffSize];
+ memcpy(in->lastPm.buffer, pm.buffer, pm.buffSize);
+ in->lastPm.args = in;
+ in->lastPm.deleter = pl_payer_deleter_func;
+ }
+ break;
+ case PipeMaterial::PMT_FRAME:
+ {
+ MB_Frame* pmFrame = (MB_Frame*)(pm.buffer);
+ in->lastFrame = *pmFrame;
+ in->lastFrame.buffer = new uint8_t[pmFrame->buffSize];
+ memcpy(in->lastFrame.buffer, pmFrame->buffer, pmFrame->buffSize);
+
+ in->lastPm.buffer = &(in->lastFrame);
+ in->lastPm.args = in;
+ in->lastPm.deleter = pl_payer_deleter_func;
+ }
+ break;
+ default:
+ //#todo support list or pm::copier operator
+ LOG_ERROR << "Only support PMT_BYTES / PMT_FRAME";
+ }
+ }
+
+ in->lastPm.former = this;
+ return true;
+}
+
+bool PL_Payer::gain(PipeMaterial& pm)
+{
+ PL_Payer_Internal* in = (PL_Payer_Internal*)internal;
+
+ pm = in->lastPm;
+
+ return true;
+}
diff --git a/RtspFace/PL_Payer.h b/RtspFace/PL_Payer.h
new file mode 100644
index 0000000..43ef44d
--- /dev/null
+++ b/RtspFace/PL_Payer.h
@@ -0,0 +1,33 @@
+#ifndef _PL_Payer_H_
+#define _PL_Payer_H_
+
+#include "PipeLine.h"
+
+struct PL_Payer_Config
+{
+ bool copyData;
+
+ PL_Payer_Config() :
+ copyData(false)
+ { }
+};
+
+class PL_Payer : public PipeLineElem
+{
+public:
+ PL_Payer();
+ virtual ~PL_Payer();
+
+ 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_Payer();
+
+#endif
diff --git a/RtspFace/PL_SensetimeFaceDetect.cpp b/RtspFace/PL_SensetimeFaceDetect.cpp
index cc04c79..c79a5f7 100644
--- a/RtspFace/PL_SensetimeFaceDetect.cpp
+++ b/RtspFace/PL_SensetimeFaceDetect.cpp
@@ -1 +1,288 @@
#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;
+ PipeMaterial pmList[2];
+ PL_SensetimeFaceDetectConfig config;
+ st_ff_vect_t faceFeatures;
+
+ bool payError;
+
+ cv_handle_t handle_track;
+
+ PL_SensetimeFaceDetect_Internal() :
+ //buffSize(0), buffSizeMax(sizeof(buffer)),
+ lastFrame(), pmList(), config(), faceFeatures(), payError(true),
+ handle_track(nullptr)
+ {
+ }
+
+ ~PL_SensetimeFaceDetect_Internal()
+ {
+ }
+
+ void reset()
+ {
+ //buffSize = 0;
+ payError = true;
+
+ MB_Frame _lastFrame;
+ lastFrame = _lastFrame;
+
+ PipeMaterial _pm;
+ pmList[0] = _pm;
+ pmList[1] = _pm;
+
+ PL_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();
+
+ PL_SensetimeFaceDetectConfig* config = (PL_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 doFaceTrack(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(width,height), CV_8UC3, buffer);
+ cv::Mat yMat(cv::Size(width,height), CV_8UC1, buffer);
+ for (int i = 0; i < face_count; i++)
+ {
+ SensetimeFaceFeature faceFeature;
+ faceFeature.rect.leftTop.x = p_face[i].rect.left;
+ faceFeature.rect.leftTop.y = p_face[i].rect.top;
+ faceFeature.rect.rightBottom.x = p_face[i].rect.right;
+ faceFeature.rect.rightBottom.y = p_face[i].rect.bottom;
+ faceFeature.id = p_face[i].ID;
+ faceFeature.yaw = p_face[i].yaw;
+ faceFeature.pitch = p_face[i].pitch;
+ faceFeature.roll = p_face[i].roll;
+ 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);
+
+ 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++)
+ {
+ FacePoint featurePoint;
+ featurePoint.x = p_face[i].points_array[j].x;
+ featurePoint.y = p_face[i].points_array[j].y;
+ faceFeature.featurePoints.push_back(featurePoint);
+
+ 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 (in->config.generate_face_feature)
+ in->faceFeatures.push_back(faceFeature);
+ }
+
+ //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 << "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 << "Only support MBFT_YUV420";
+ return false;
+ }
+
+ in->faceFeatures.clear();
+ 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_SensetimeFaceDetect::gain(PipeMaterial& pm)
+{
+ PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
+
+ if (in->payError)
+ {
+ pm.former = this;
+ return false;
+ }
+
+ if (!in->config.generate_face_feature)
+ {
+ pm.type = PipeMaterial::PMT_FRAME;
+ pm.buffer = &(in->lastFrame);
+ pm.buffSize = 0;
+ }
+ else
+ {
+ in->pmList[0].type = PipeMaterial::PMT_FRAME;
+ in->pmList[0].buffer = &(in->lastFrame);
+ in->pmList[0].buffSize = 0;
+ in->pmList[0].former = this;
+
+ in->pmList[1].type = PipeMaterial::PMT_BYTES;
+ 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;
+}
diff --git a/RtspFace/PL_SensetimeFaceDetect.h b/RtspFace/PL_SensetimeFaceDetect.h
index 19d48c4..b8c8117 100644
--- a/RtspFace/PL_SensetimeFaceDetect.h
+++ b/RtspFace/PL_SensetimeFaceDetect.h
@@ -1,4 +1,40 @@
-#ifndef _PL_PL_SENSETIMEFACEDETECT_H_
-#define _PL_PL_SENSETIMEFACEDETECT_H_
+#ifndef _PL_SENSETIMEFACEDETECT_H_
+#define _PL_SENSETIMEFACEDETECT_H_
+
+#include "PipeLine.h"
+#include <vector>
+
+struct PL_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
+ bool draw_face_rect;
+ bool draw_face_feature_point;
+ bool generate_face_feature; // for PL_SensetimeFaceFeatureEmit
+
+ PL_SensetimeFaceDetectConfig() :
+ 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_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/ev_proto.h b/RtspFace/ev_proto.h
index ab71518..6dc27be 100644
--- a/RtspFace/ev_proto.h
+++ b/RtspFace/ev_proto.h
@@ -11,8 +11,22 @@
enum EVPC
{
EVPC__FIRST,
- EVPC_SENSETIMEFACEDETECT,
- EVPC__LAST,
+ EVPC_STATUS = 1,
+ EVPC_USER_DEFINE = 128,
+ EVPC__LAST
+ };
+};
+
+struct EVPStatus
+{
+ enum EVPS
+ {
+ EVPS__FIRST,
+ EVPS_OK = 1,
+ EVPS_ERROR = 128,
+ EVPS_INTERNAL_ERROR,
+ EVPS_PARAMETER_ERROR,
+ EVPS__LAST
};
};
@@ -22,12 +36,21 @@
uint32_t size; // sizeof(EVPHeader)+sizeof(subcmd)
};
+struct EVP_Status
+{
+ int16_t status;
+};
+
struct EVP_VariableBuffer
{
- int16_t mb_type; // MB_Frame::MBFType
+ int16_t type;
uint8_t buff[0];
};
+//#todo
+template<typename TPacket>
+void endian_convert(TPacket& packet);
+
#pragma pack()
#endif
diff --git a/RtspFace/ev_server.cpp b/RtspFace/ev_server.cpp
index 4baa6b2..a6367c1 100644
--- a/RtspFace/ev_server.cpp
+++ b/RtspFace/ev_server.cpp
@@ -157,16 +157,15 @@
bool closeClient = true;
if (client->proc != nullptr)
{
- EVClientStub cs;
+ EVClientStub cs(client->recvbuff, client->recvbuff_end);
cs.id = client->fd;
- cs.recvBuff = client->recvbuff;
- cs.recvBuffSize = client->recvbuff_end;
closeClient = !(client->proc(cs));
if (cs.sendBuff != nullptr && cs.sendBuffSize > 0)
{
-
- //#todo bufferevent_write
+ size_t writeSize = bufferevent_write(bufev, cs.sendBuff, cs.sendBuffSize);
+ if (writeSize != cs.sendBuffSize)
+ LOG_WARN << "server send truncate " << (cs.sendBuffSize - writeSize) << " bytes";
if (cs.deleteSendBuff)
delete[] cs.sendBuff;
@@ -283,3 +282,17 @@
return EXIT_SUCCESS;
}
+
+void ev_send_status_packet(EVClientStub& client, EVPStatus::EVPS status)
+{
+ client.sendBuffSize = sizeof(EVPHeader)+sizeof(EVP_Status);
+ client.sendBuff = new uint8_t[client.sendBuffSize];
+ client.deleteSendBuff = true;
+
+ EVPHeader* evpHeader = new (client.sendBuff) EVPHeader;
+ evpHeader->cmd = EVPCommand::EVPC_STATUS;
+ evpHeader->size = client.sendBuffSize;
+
+ EVP_Status* evpStatus = new (client.sendBuff + sizeof(EVPHeader)) EVP_Status;
+ evpStatus->status = status;
+}
diff --git a/RtspFace/ev_server.h b/RtspFace/ev_server.h
index 3960933..aab56d0 100644
--- a/RtspFace/ev_server.h
+++ b/RtspFace/ev_server.h
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "ev_proto.h"
#define SERVER_PORT 5432
#define REUSEADDR_ON 1
@@ -25,6 +26,13 @@
sendBuff(nullptr), sendBuffSize(0), deleteSendBuff(false)
{
}
+
+ EVClientStub(const uint8_t* _recvBuff, size_t _recvBuffSize) :
+ id(-1),
+ recvBuff(_recvBuff), recvBuffSize(_recvBuffSize),
+ sendBuff(nullptr), sendBuffSize(0), deleteSendBuff(false)
+ {
+ }
};
typedef bool (*evclient_proc_t)(EVClientStub& client);
@@ -32,4 +40,7 @@
int server_main(int argc, char **argv);
+void ev_send_packet(EVClientStub& client);
+void ev_send_status_packet(EVClientStub& client, EVPStatus::EVPS status);
+
#endif
diff --git a/RtspFace/face_daemon_proto.h b/RtspFace/face_daemon_proto.h
new file mode 100644
index 0000000..cf3d4a4
--- /dev/null
+++ b/RtspFace/face_daemon_proto.h
@@ -0,0 +1,37 @@
+#ifndef _FACE_DAEMON_PROTO_H_
+#define _FACE_DAEMON_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include "ev_proto.h"
+
+#pragma pack(1)
+
+struct FaceDaemonCommand
+{
+ enum FDC
+ {
+ FDC__FIRST,
+ FDC_SENSETIMEFACEDETECT = EVPCommand::EVPC_USER_DEFINE + 1,
+ FDC_SENSETIMEFACEDETECT_RESULT
+ FDC__LAST,
+ };
+};
+
+struct FDP_Image
+{
+ int32_t school_id;
+ int16_t mb_type; // MB_Frame::MBFType
+ int16_t width;
+ int16_t height;
+ uint8_t buff[0];
+};
+
+struct FDP_FaceDetectResult
+{
+ int32_t stid; // sensetime id
+};
+
+#pragma pack()
+
+#endif
diff --git a/RtspFace/main_face_daemon.cpp b/RtspFace/main_face_daemon.cpp
index 84901f4..9ee5d4a 100644
--- a/RtspFace/main_face_daemon.cpp
+++ b/RtspFace/main_face_daemon.cpp
@@ -1,4 +1,5 @@
#include "PipeLine.h"
+#include "MaterialBuffer.h"
#include "PL_RTSPClient.h"
#include "PL_RTSPServer.h"
#include "PL_H264Decoder.h"
@@ -8,6 +9,8 @@
#include "PL_Queue.h"
#include "PL_Scale.h"
#include "PL_Fork.h"
+#include "PL_Payer.h"
+#include "PL_Gainer.h"
#include "PL_SensetimeFaceTrack.h"
#include "PL_DlibFaceTrack.h"
@@ -15,6 +18,7 @@
#include "ev_server.h"
#include "ev_proto.h"
+#include "face_daemon_proto.h"
#include "logger.h"
@@ -22,18 +26,24 @@
evclient_proc_t evclient_proc;
-bool ev_proc_SensetimeFaceDetect(EVClientStub& client)
+void send_SensetimeFaceDetectResult(PipeMaterial& lastPm)
{
+ if (lastPm.type == PipeMaterial::PMT_PM_LIST)
+ {
+ PipeMaterial& facePM = ((PipeMaterial*)(lastPm.buffer))[1];
+ st_ff_vect_t& faceFeatures = *((st_ff_vect_t*)facePM.buffer);
+ LOG_NOTICE << "faceFeatures " << faceFeatures.size();
+ //#todo send result packet
+ }
}
-bool ev_proc(EVClientStub& client)
+bool ev_proc_SensetimeFaceDetect(EVClientStub& client)
{
- EVPHeader* evpHeader = (EVPHeader*)client.recvBuff;
- //#todo check cmd and size
-
//#test send 01000B0000004142434445
//LOG_DEBUG << "cmd=" << evpHeader->cmd << ", size=" << evpHeader->size << ", \t" << (char*)(evpHeader + sizeof(EVPHeader));
//return true;
+
+ FDP_Image* fdpImage = (FDP_Image*)(client.recvBuff + sizeof(EVPHeader));
PipeLine* pipeLine = nullptr;
if (g_PipeLinePool.wait_free())
@@ -41,37 +51,69 @@
if (pipeLine == nullptr)
{
- LOG_WARN << "can't get free pipeline";//#todo send err packet
+ LOG_WARN << "can't get free pipeline";
+ ev_send_status_packet(client, EVPStatus::EVPS_INTERNAL_ERROR);
return false;
}
- PipeMaterial pm;
// fill
+ MB_Frame frame;
+ frame.type = (MB_Frame::MBFType)(fdpImage->mb_type);
+ frame.buffer = fdpImage->buff;
+ frame.buffSize = client.recvBuffSize - sizeof(EVPHeader) - sizeof(FDP_Image);
+ frame.width = fdpImage->width;
+ frame.height = fdpImage->height;
- PipeLineElem* plElem = pipeLine.pipe(&pm);
- if (! pipeLine.check_pipe_complete(plElem))
+ PipeMaterial pm;
+ pm.type = PipeMaterial::PMT_FRAME;
+ pm.buffer = &frame;
+ pm.buffSize = 0;
+
+ PipeLineElem* plElem = pipeLine->pipe(&pm);
+ if (! pipeLine->check_pipe_complete(plElem))
{
LOG_WARN << "pipeline not complete";
- g_PipeLinePool.release(pipeLine);//#todo send err packet
+ g_PipeLinePool.release(pipeLine);
+ ev_send_status_packet(client, EVPStatus::EVPS_INTERNAL_ERROR);
return false;
}
if (!plElem->gain(pm))
{
LOG_WARN << "pipeline gain error";
- g_PipeLinePool.release(pipeLine);//#todo send err packet
+ g_PipeLinePool.release(pipeLine);
+ ev_send_status_packet(client, EVPStatus::EVPS_INTERNAL_ERROR);
+ return false;
+ }
+
+ send_SensetimeFaceDetectResult(pm);
+
+ g_PipeLinePool.release(pipeLine);
+ return false;
+}
+
+bool ev_proc(EVClientStub& client)
+{
+ EVPHeader* evpHeader = (EVPHeader*)client.recvBuff;
+ if (evpHeader->size != client.recvBuffSize)
+ {
+ LOG_WARN << "Truncated buffer " << (evpHeader->size - client.recvBuffSize) << " bytes";
return false;
}
- if (pm.type == PipeMaterial::PMT_PM_LIST)
+ switch(evpHeader->cmd)
{
- PipeMaterial& facePM = ((PipeMaterial*)(pm.buffer))[1];
- st_ff_vect_t& faceFeatures = *((st_ff_vect_t*)facePM.buffer);
- LOG_NOTICE << "faceFeatures " << faceFeatures.size();
- //#todo send result packet
+ case EVPCommand::EVPC_USER_DEFINE + 1:
+ return ev_proc_SensetimeFaceDetect(client);
+ break;
+ default:
+ LOG_WARN << "Unknown command";
+ ev_send_status_packet(client, EVPStatus::EVPS_PARAMETER_ERROR);
+ return false;
+ break;
}
- g_PipeLinePool.release(pipeLine);
+ // return false to disconnect
return false;
}
@@ -80,6 +122,7 @@
initLogger(LV_DEBUG);
PipeLine::register_global_elem_creator("PL_SensetimeFaceTrack", create_PL_SensetimeFaceTrack);
+ PipeLine::register_global_elem_creator("PL_Gainer", create_PL_Gainer);
g_PipeLinePool = new PipeLinePool(true);
@@ -87,17 +130,28 @@
{
PipeLine* pipeLine = new PipeLine;
- {//payer//#todo
+ {
+ PL_Payer_Config config;
+ config.copyData = true;
+ PL_Gainer* ple = (PL_Gainer*)pipeLine->push_elem("PL_Gainer");
+ bool ret = ple->init(&config);
+ if (!ret)
+ {
+ LOG_ERROR << "ple init error";
+ exit(EXIT_FAILURE);
+ }
}
{
SensetimeFaceTrackConfig config;
+ config.draw_face_rect = false;
+ config.draw_face_feature_point = false;
config.generate_face_feature = true;
- PL_SensetimeFaceTrack* sensetimeFaceTrack = (PL_SensetimeFaceTrack*)pipeLine->push_elem("PL_SensetimeFaceTrack");
- bool ret = sensetimeFaceTrack->init(&config);
+ PL_SensetimeFaceTrack* ple = (PL_SensetimeFaceTrack*)pipeLine->push_elem("PL_SensetimeFaceTrack");
+ bool ret = ple->init(&config);
if (!ret)
{
- LOG_ERROR << "sensetimeFaceTrack init error";
+ LOG_ERROR << "ple init error";
exit(EXIT_FAILURE);
}
}
@@ -107,22 +161,4 @@
evclient_proc = ev_proc;
return server_main(argc, argv);
-
- while(true)
- {
- //LOG_ERROR << "begin pipe";
-
- PipeMaterial pm;
- if (pipeLine.pipe(&pm) == sensetimeFaceTrack);
- sensetimeFaceTrack->gain(pm);
-
- if (pm.type == PipeMaterial::PMT_PM_LIST)
- {
- PipeMaterial& facePM = ((PipeMaterial*)(pm.buffer))[1];
- st_ff_vect_t& faceFeatures = *((st_ff_vect_t*)facePM.buffer);
- LOG_NOTICE << "faceFeatures " << faceFeatures.size();
- }
-
- //LOG_ERROR << "end pipe";
- }
}
diff --git a/RtspFace/make.sh b/RtspFace/make.sh
index 863dd11..eed3ccf 100644
--- a/RtspFace/make.sh
+++ b/RtspFace/make.sh
@@ -49,7 +49,7 @@
#g++ main.cpp $CFLAGS $CPPFLAGS -o main.o
#g++ main_dump_st_face.cpp $CFLAGS $CPPFLAGS -o main.o
g++ main_face_daemon.cpp $CFLAGS $CPPFLAGS -o main.o
-g++ face_daemon_server.cpp $CFLAGS $CPPFLAGS
+g++ ev_server.cpp $CFLAGS $CPPFLAGS
g++ PipeLine.cpp $CFLAGS $CPPFLAGS
g++ PipeLinePool.cpp $CFLAGS $CPPFLAGS
@@ -62,6 +62,8 @@
g++ PL_Queue.cpp $CFLAGS $CPPFLAGS
g++ PL_Scale.cpp $CFLAGS $CPPFLAGS
g++ PL_Fork.cpp $CFLAGS $CPPFLAGS
+g++ PL_Payer.cpp $CFLAGS $CPPFLAGS
+g++ PL_Gainer.cpp $CFLAGS $CPPFLAGS
g++ PL_SensetimeFaceTrack.cpp $CFLAGS $CPPFLAGS
@@ -73,8 +75,8 @@
g++ -g -std=c++11 \
main.o PipeLine.o PipeLinePool.o \
- face_daemon_server.o \
- PL_RTSPClient.o PL_H264Decoder.o PL_H264Encoder.o PL_AVFrameYUV420.o PL_AVFrameBGRA.o PL_Queue.o PL_Scale.o PL_Fork.o \
+ ev_server.o \
+ PL_RTSPClient.o PL_H264Decoder.o PL_H264Encoder.o PL_AVFrameYUV420.o PL_AVFrameBGRA.o PL_Queue.o PL_Scale.o PL_Fork.o PL_Payer.o PL_Gainer.o \
PL_SensetimeFaceTrack.o \
PL_DlibFaceTrack.o \
$FFMPEGRTSPSERVER_OBJ PL_RTSPServer.o \
--
Gitblit v1.8.0