From 4ef430e946e717d72e923c4708a9120f94d55dbd Mon Sep 17 00:00:00 2001
From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期三, 28 十二月 2016 09:35:14 +0800
Subject: [PATCH] test h264 encoder

---
 RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp |  114 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp b/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp
index 0b38140..9ea1bba 100644
--- a/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp
+++ b/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp
@@ -16,6 +16,13 @@
 		pthread_mutex_init(&outqueue_mutex,NULL);
 
 	}
+	
+	FFmpegH264Encoder::~FFmpegH264Encoder()
+	{
+		pthread_mutex_init(&inqueue_mutex,NULL);
+		pthread_mutex_init(&outqueue_mutex,NULL);
+
+	}
 
 	void FFmpegH264Encoder::setCallbackFunctionFrameIsReady(std::function<void()> func)
 	{
@@ -45,13 +52,13 @@
 				pthread_mutex_unlock(&inqueue_mutex);
 				if(frame != NULL)
 				{
-					WriteFrame(frame);
+					WriteFrameRGB(frame);
 				}
 			}
         }
 	}
 
-	void FFmpegH264Encoder::SetupCodec(const char *filename, int codec_id)
+	bool FFmpegH264Encoder::SetupCodec(const char *filename, int codec_id)
 	{
 		int ret;
 		m_sws_flags = SWS_BICUBIC;
@@ -60,14 +67,17 @@
 		avcodec_register_all();
 		av_register_all();
 		
-		avformat_alloc_output_context2(&m_oc, NULL, NULL, filename);
+		if (strlen(filename) == 0)
+			avformat_alloc_output_context2(&m_oc, NULL, "h264", filename);
+		else 
+			avformat_alloc_output_context2(&m_oc, NULL, NULL, filename);
 		
 		if (!m_oc) {
 			avformat_alloc_output_context2(&m_oc, NULL, "avi", filename);
 		}
 
 		if (!m_oc) {
-			return;
+			return false;
 		}
 
 		m_fmt = m_oc->oformat;
@@ -79,13 +89,13 @@
 
 		m_video_codec = avcodec_find_encoder(m_fmt->video_codec);
 		if (!(m_video_codec)) {
-				return;
+				return false;
 		}
 
 		st = avformat_new_stream(m_oc, m_video_codec);
 
 		if (!st) {
-				return;
+				return false;
 		}
 
 		st->id = m_oc->nb_streams-1;
@@ -112,7 +122,7 @@
 
 		ret = avcodec_open2(c, m_video_codec, NULL);
 		if (ret < 0) {
-			return;
+			return false;
 		}
 
 		//ret = avpicture_alloc(&m_dst_picture, c->pix_fmt, c->width, c->height);
@@ -126,7 +136,7 @@
 
 		ret = av_image_alloc(m_dst_picture->data, m_dst_picture->linesize, c->width, c->height, (AVPixelFormat)m_dst_picture->format, 32);
 		if (ret < 0) {
-			return;
+			return false;
 		}
 
 		//ret = avpicture_alloc(&m_src_picture, AV_PIX_FMT_BGR24, c->width, c->height);
@@ -135,7 +145,7 @@
 		ret = av_image_alloc(m_src_picture->data, m_src_picture->linesize, c->width, c->height, AV_PIX_FMT_BGR24, 24);
 
 		if (ret < 0) {
-			return;
+			return false;
 		}
 
 		bufferSize = ret;
@@ -145,27 +155,28 @@
 		if (!(m_fmt->flags & AVFMT_NOFILE)) {
 			ret = avio_open(&m_oc->pb, filename, AVIO_FLAG_WRITE);
 			if (ret < 0) {
-				return;
+				return false;
 			}
 		}
 		
 		ret = avformat_write_header(m_oc, NULL);
 		
 		if (ret < 0) {
-			return;
+			return false;
 		}
 
 		sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR24,
 								 c->width, c->height, AV_PIX_FMT_YUV420P,
 								 SWS_BICUBIC, NULL, NULL, NULL);
 		if (!sws_ctx) {
-			return;
+			return false;
 		}
+		
+		return true;
 	}
 
-	void FFmpegH264Encoder::WriteFrame(uint8_t * RGBFrame )
-	{	
-
+	bool FFmpegH264Encoder::WriteFrameRGB(uint8_t * RGBFrame )
+	{
 		memcpy(m_src_picture->data[0], RGBFrame, bufferSize);
 
 		sws_scale(sws_ctx,
@@ -182,7 +193,7 @@
 		ret = avcodec_encode_video2(m_c, &pkt, m_dst_picture, &got_packet);
 		
 		if (ret < 0) {
-			return;
+			return false;
 		}
 
 		if (!ret && got_packet && pkt.size) 
@@ -215,10 +226,75 @@
 		m_frame_count++;
 		m_dst_picture->pts += av_rescale_q(1, m_video_st->codec->time_base, m_video_st->time_base);
 		
-		onFrame();
+		if (onFrame != nullptr)
+			onFrame();
+		
+		return true;
+	}
+	
+	void copyAVFrame(AVFrame* dest, AVFrame* src)
+	{
+		int height = dest->height;
+		int width = dest->width;
+
+		memcpy(dest->data[0], src->data[0], height * width); // Y
+		memcpy(dest->data[1], src->data[1], height * width / 4); // U
+		memcpy(dest->data[2], src->data[2], height * width / 4); // V
+	}
+	
+	bool FFmpegH264Encoder::WriteFrameYUV420(AVFrame * YUVFrame)
+	{
+		copyAVFrame(m_dst_picture, YUVFrame);
+
+        AVPacket pkt = { 0 };
+		int got_packet;
+		av_init_packet(&pkt);
+
+		int ret = 0;
+
+		ret = avcodec_encode_video2(m_c, &pkt, m_dst_picture, &got_packet);
+		
+		if (ret < 0) {
+			return false;
+		}
+
+		if (!ret && got_packet && pkt.size) 
+		{
+			pkt.stream_index = m_video_st->index;
+			FrameStructure * frame = new FrameStructure();
+			frame->dataPointer = new uint8_t[pkt.size];
+			frame->dataSize = pkt.size-4;
+			frame->frameID = m_frame_count;
+
+			memcpy(frame->dataPointer,pkt.data+4,pkt.size-4);
+
+			pthread_mutex_lock(&outqueue_mutex);
+
+			if(outqueue.size()<30)
+			{
+				outqueue.push(frame);
+			}
+			else
+			{
+				delete frame;
+			}
+
+			pthread_mutex_unlock(&outqueue_mutex);
+
+		}
+
+		av_free_packet(&pkt);
+
+		m_frame_count++;
+		m_dst_picture->pts += av_rescale_q(1, m_video_st->codec->time_base, m_video_st->time_base);
+		
+		if (onFrame != nullptr)
+			onFrame();
+		
+		return true;
 	}
 
-	void FFmpegH264Encoder::SetupVideo(std::string filename, int Width, int Height, int FPS, int GOB, int BitPerSecond)
+	bool FFmpegH264Encoder::SetupVideo(std::string filename, int Width, int Height, int FPS, int GOB, int BitPerSecond)
 	{
 		m_filename = filename;
 		m_AVIMOV_WIDTH=Width;	//Movie width
@@ -227,7 +303,7 @@
 		m_AVIMOV_GOB=GOB;		//I frames per no of P frames, see note below!
 		m_AVIMOV_BPS=BitPerSecond; //Bits per second, if this is too low then movie will become garbled
 		
-		SetupCodec(m_filename.c_str(),AV_CODEC_ID_H264);	
+		return SetupCodec(m_filename.c_str(),AV_CODEC_ID_H264);	
 	}
 
 	void FFmpegH264Encoder::CloseCodec()

--
Gitblit v1.8.0