From 1e777cf1467b4e02c3f1ff03434ec46cf8bb9838 Mon Sep 17 00:00:00 2001
From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期四, 03 八月 2017 09:46:49 +0800
Subject: [PATCH] split client server

---
 RtspFace/PL_RTSPServer.cpp                 |    1 
 RtspFace/PL_SensetimeFaceTrackMultiTrd.cpp |    4 
 RtspFace/PL_AndroidMediaCodecEncoder.h     |   63 ++++++++++
 RtspFace/PL_AndroidMediaCodecEncoder.cpp   |  266 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 332 insertions(+), 2 deletions(-)

diff --git a/RtspFace/PL_AndroidMediaCodecEncoder.cpp b/RtspFace/PL_AndroidMediaCodecEncoder.cpp
new file mode 100644
index 0000000..ca2b98b
--- /dev/null
+++ b/RtspFace/PL_AndroidMediaCodecEncoder.cpp
@@ -0,0 +1,266 @@
+#include "PL_AndroidMediaCodecEncoder.h"
+#include "MaterialBuffer.h"
+#include "logger.h"
+#include "MediaHelper.h"
+
+#include <media/NdkMediaCodec.h>
+#include <media/NdkMediaFormat.h>
+
+#include <android/bitmap.h>
+
+#include <stdlib.h>
+#include <liveMedia/liveMedia.hh>
+
+struct PL_AMCE_Internal
+{
+	uint8_t buffer[1920*1080*3];//#todo new from config
+	size_t buffSize;
+	const size_t buffSizeMax;
+	
+	size_t inputFrameCount;
+
+	PL_AndroidMediaCodecEncoder_Config config;
+
+	AMediaCodec* codec;
+
+	bool payOK;
+
+	MB_Frame tempFrame; // frame for gain
+
+	PL_AMCE_Internal() : 
+		buffSize(0), buffSizeMax(sizeof(buffer)), 
+		inputFrameCount(0),
+		config(), 
+		codec(nullptr),
+		payOK(false),
+		tempFrame()
+	{
+	}
+	
+	~PL_AMCE_Internal()
+	{
+	}
+	
+	void reset()
+	{
+		buffSize = 0;
+		
+		inputFrameCount = 0;
+
+		PL_AndroidMediaCodecEncoder_Config _config;
+		config = _config;
+		
+		codec = nullptr;//#todo destory
+
+		payOK = false;
+
+		MB_Frame _tempFrame;
+		tempFrame = _tempFrame;
+	}
+};
+
+PipeLineElem* create_PL_AndroidMediaCodecEncoder()
+{
+	return new PL_AndroidMediaCodecEncoder;
+}
+
+PL_AndroidMediaCodecEncoder::PL_AndroidMediaCodecEncoder() : internal(new PL_AMCE_Internal)
+{
+}
+
+PL_AndroidMediaCodecEncoder::~PL_AndroidMediaCodecEncoder()
+{
+	delete (PL_AMCE_Internal*)internal;
+	internal= nullptr;
+}
+
+bool PL_AndroidMediaCodecEncoder::init(void* args)
+{
+	PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
+	in->reset();
+
+	PL_AndroidMediaCodecEncoder_Config* config = (PL_AndroidMediaCodecEncoder_Config*)args;
+	in->config = *config;
+
+    AMediaFormat* format = AMediaFormat_new();
+
+    AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, config->ak_mime.c_str());
+    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, config->ak_height);
+    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, config->ak_width);
+
+	AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, config->ak_bit_rate);
+	AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, config->ak_frame_rate);
+	AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, config->ak_i_frame_interval);
+
+// see: https://developer.android.com/reference/android/media/MediaCodecInfo.CodecCapabilities.html#COLOR_FormatYUV420Flexible
+#define AMEDIA_COLOR_FormatYUV420Flexible 0x7f420888
+    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, config->ak_color_format);
+    //AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_STRIDE, config->ak_width * 2);
+
+	//uint8_t sps[] = {0x0,0x0,0x0,0x1, 0x67, 0x42, 0x00, 0x2A, 0x95, 0xA8, 0x1E, 0x00, 0x89, 0xF9, 0x61, 0x00, 0x00, 0x07, 0x08, 0x00, 0x01, 0x5F, 0x90, 0x04};
+	//uint8_t pps[] = {0x0,0x0,0x0,0x1, 0x68, 0xCE, 0x3C, 0x80};
+	//AMediaFormat_setBuffer(format, "csd-0", sps, sizeof(sps)); // sps
+	//AMediaFormat_setBuffer(format, "csd-1", pps, sizeof(pps)); // pps
+
+    // should like:
+    // mime: string(video/avc), durationUs: int64(10000000), width: int32(480), height: int32(360), max-input-size: int32(55067), csd-0: data, csd-1: data}
+    LOG_INFO << "AMediaFormat_toString: " << AMediaFormat_toString(format) << LOG_ENDL;
+
+    in->codec = AMediaCodec_createEncoderByType(config->ak_mime.c_str());
+
+    if (AMediaCodec_configure(in->codec, format, nullptr, nullptr, AMEDIACODEC_CONFIGURE_FLAG_ENCODE) != AMEDIA_OK)
+	{
+		AMediaFormat_delete(format);
+        LOG_ERROR << "AMediaCodec_configure error" << LOG_ENDL;
+		return false;
+	}
+
+    if (AMediaCodec_start(in->codec) != AMEDIA_OK)
+	{
+		AMediaFormat_delete(format);
+        LOG_ERROR << "AMediaCodec_start error" << LOG_ENDL;
+		return false;
+	}
+
+    AMediaFormat_delete(format);
+	return true;
+}
+
+void PL_AndroidMediaCodecEncoder::finit()
+{
+	PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
+	//todo release codec
+	// call AMediaCodec_stop
+}
+
+bool amce_pay_frame_breaker(const PipeMaterial* pm, void* args)
+{
+	PL_AMCE_Internal* in = (PL_AMCE_Internal*)args;
+	MB_Frame* frame = (MB_Frame*)pm->buffer;
+
+	ssize_t bufidx = AMediaCodec_dequeueInputBuffer(in->codec, 2000);
+	LOGP(DEBUG, "input buffer bufidx=%zd, inputFrameCount=%d", bufidx, in->inputFrameCount++);
+
+	if (bufidx >= 0)
+	{
+		size_t bufsize;
+		uint8_t* inputBuff = AMediaCodec_getInputBuffer(in->codec, bufidx, &bufsize);
+		size_t sampleSize = std::min(bufsize, frame->buffSize);
+		memcpy(inputBuff, frame->buffer, sampleSize); // fill buffer
+
+		uint64_t presentationTimeUs = timeval_to_microseconds(frame->pts); //microseconds
+
+		media_status_t ms = AMediaCodec_queueInputBuffer(in->codec, bufidx, 0, sampleSize, presentationTimeUs, 0);
+
+		in->payOK = true;
+		LOGP(DEBUG, "media_status_t=%d", ms);
+	}
+	else
+	{
+		LOG_WARN << "bufidx=" << bufidx << LOG_ENDL;
+		in->payOK = false;
+		return false;
+	}
+
+	return false;
+}
+
+bool PL_AndroidMediaCodecEncoder::pay(const PipeMaterial& pm)
+{
+	PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
+
+	in->payOK = false;
+	if (!in->payOK)
+		pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_NV12, amce_pay_frame_breaker, in);
+
+	return in->payOK;
+}
+
+bool PL_AndroidMediaCodecEncoder::gain(PipeMaterial& pm)
+{
+	PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
+
+	if (!in->payOK)
+	{
+		LOG_WARN << "not in->payOK" << LOG_ENDL;
+		return false;
+	}
+
+	pm.deleter = nullptr;
+	pm.former = this;
+
+	AMediaCodecBufferInfo info;
+	ssize_t outputBuffIdx = AMediaCodec_dequeueOutputBuffer(in->codec, &info, 0);
+	if (outputBuffIdx >= 0)
+	{
+		if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM)
+		{
+			LOGP(WARNING, "output EOS");
+		}
+
+       //AMediaFormat* format = AMediaCodec_getOutputFormat(in->codec);
+       //if (format != NULL)
+       //{
+       //    int32_t width, height, color;
+       //    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
+       //    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
+       //    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, &color);
+       //    AMediaFormat_delete(format);
+       //    format = nullptr;
+       //    LOGP(DEBUG, "output media format, w=%d, h=%d, c=%d", width, height, color);
+       //}
+
+		in->tempFrame.reset();
+
+		size_t outSize = in->buffSizeMax;
+		uint8_t* outputBuff = AMediaCodec_getOutputBuffer(in->codec, outputBuffIdx, &outSize);
+		if (outputBuff != nullptr)
+		{
+			in->buffSize = std::min((size_t) info.size, in->buffSizeMax);
+			memcpy(in->buffer, outputBuff + info.offset, in->buffSize);
+
+			in->tempFrame.type = MB_Frame::MBFT_H264_NALU_AUX;
+			in->tempFrame.buffer = in->buffer;
+			in->tempFrame.buffSize = in->buffSize;
+			in->tempFrame.width = in->config.ak_width;
+			in->tempFrame.height = in->config.ak_height;
+			microseconds_to_timeval(info.presentationTimeUs, in->tempFrame.pts);
+
+			pm.type = PipeMaterial::PMT_FRAME;
+			pm.buffer = &(in->tempFrame);
+			pm.buffSize = 0;
+
+			//static size_t f = 0;
+			//static FILE *pFile = fopen("/sdcard/aa.264", "wb");
+			//fwrite(in->buffer, sizeof(char), in->buffSize, pFile);
+			//if (++f > 400){
+			//	fclose(pFile);
+			//	exit(0);
+			//}
+		}
+
+		AMediaCodec_releaseOutputBuffer(in->codec, outputBuffIdx, false);
+
+		return true;
+	}
+	else if (outputBuffIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)
+	{
+		LOGP(DEBUG, "output buffers changed");
+	}
+	else if (outputBuffIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
+	{
+		auto format = AMediaCodec_getOutputFormat(in->codec);
+		LOGP(INFO, "format changed to: %s", AMediaFormat_toString(format));
+		AMediaFormat_delete(format);
+	}
+	else if (outputBuffIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
+	{
+		LOGP(DEBUG, "no output buffer right now");
+	}
+	else
+	{
+		LOGP(WARNING, "unexpected info code: %zd", outputBuffIdx);
+	}
+	
+	return false;
+}
diff --git a/RtspFace/PL_AndroidMediaCodecEncoder.h b/RtspFace/PL_AndroidMediaCodecEncoder.h
new file mode 100644
index 0000000..90ec190
--- /dev/null
+++ b/RtspFace/PL_AndroidMediaCodecEncoder.h
@@ -0,0 +1,63 @@
+#ifndef _PL_ANDROIDMEDIACODECENCODER_H_
+#define _PL_ANDROIDMEDIACODECENCODER_H_
+
+#include "PipeLine.h"
+
+struct PL_AndroidMediaCodecEncoder_Config
+{
+	// D:\adk\ndk-bundle\platforms\android-21\arch-arm64\usr\include\media\NdkMediaFormat.h
+	// AMEDIAFORMAT_KEY_AAC_PROFILE;
+	int32_t ak_bit_rate; // AMEDIAFORMAT_KEY_BIT_RATE;
+	// AMEDIAFORMAT_KEY_CHANNEL_COUNT;
+	// AMEDIAFORMAT_KEY_CHANNEL_MASK;
+	int32_t ak_color_format; // AMEDIAFORMAT_KEY_COLOR_FORMAT;
+	// AMEDIAFORMAT_KEY_DURATION;
+	// AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL;
+	int32_t ak_frame_rate; // AMEDIAFORMAT_KEY_FRAME_RATE;
+	int32_t ak_height; // AMEDIAFORMAT_KEY_HEIGHT;
+	// AMEDIAFORMAT_KEY_IS_ADTS;
+	// AMEDIAFORMAT_KEY_IS_AUTOSELECT;
+	// AMEDIAFORMAT_KEY_IS_DEFAULT;
+	// AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE;
+	int32_t ak_i_frame_interval; // AMEDIAFORMAT_KEY_I_FRAME_INTERVAL;
+	// AMEDIAFORMAT_KEY_LANGUAGE;
+	// AMEDIAFORMAT_KEY_MAX_HEIGHT;
+	// AMEDIAFORMAT_KEY_MAX_INPUT_SIZE;
+	// AMEDIAFORMAT_KEY_MAX_WIDTH;
+	std::string ak_mime; // AMEDIAFORMAT_KEY_MIME; // video/avc
+	// AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP;
+	// AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER;
+	// AMEDIAFORMAT_KEY_SAMPLE_RATE;
+	int32_t ak_width; // AMEDIAFORMAT_KEY_WIDTH;
+	// AMEDIAFORMAT_KEY_STRIDE;
+
+	PL_AndroidMediaCodecEncoder_Config() : 
+		ak_bit_rate(0), 
+		ak_color_format(0), 
+		ak_frame_rate(0), 
+		ak_height(0), 
+		ak_i_frame_interval(0), 
+		ak_mime(),
+		ak_width(0)
+	{}
+};
+
+class PL_AndroidMediaCodecEncoder : public PipeLineElem
+{
+public:
+	PL_AndroidMediaCodecEncoder();
+	virtual ~PL_AndroidMediaCodecEncoder();
+
+	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_AndroidMediaCodecEncoder();
+
+#endif
diff --git a/RtspFace/PL_RTSPServer.cpp b/RtspFace/PL_RTSPServer.cpp
index d705a8b..d3da325 100644
--- a/RtspFace/PL_RTSPServer.cpp
+++ b/RtspFace/PL_RTSPServer.cpp
@@ -114,6 +114,7 @@
 		*FrameSize = newBufferSize;
 
 		LOG_DEBUG << "send frame size=" << in.buffSize << std::endl;
+		return 1;
 	}
 	
 	virtual char ReleaseFrame()
diff --git a/RtspFace/PL_SensetimeFaceTrackMultiTrd.cpp b/RtspFace/PL_SensetimeFaceTrackMultiTrd.cpp
index f5c7643..cd9c91f 100644
--- a/RtspFace/PL_SensetimeFaceTrackMultiTrd.cpp
+++ b/RtspFace/PL_SensetimeFaceTrackMultiTrd.cpp
@@ -89,7 +89,7 @@
 			return ret;
 		}
 
-		ret = cv_face_create_tracker(&tracker_handle, nullptr, config.point_size_config);
+		ret = cv_face_create_tracker(&tracker_handle, nullptr, config.point_size_config | CV_FACE_TRACKING_TWO_THREAD);
 		if (ret != 0)
 		{
 			LOGP(ERROR, "cv_face_create_tracker: %s/n", strerror(ret));
@@ -425,7 +425,7 @@
 				uint8_t *buffer, size_t width, size_t height, size_t stride,
 				cv_pixel_format cvPixFmt)
 {
-	PipeLineElemTimingDebugger td(nullptr);
+	//PipeLineElemTimingDebugger td(nullptr);
 	in->trackThread.do_face_track(buffer, cvPixFmt, width, height, stride);
 	return 0;
 }

--
Gitblit v1.8.0