From cf8dd1b37d9b5e0735868c276d2398b80dc26000 Mon Sep 17 00:00:00 2001
From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期二, 20 十二月 2016 17:32:19 +0800
Subject: [PATCH] rtsp to yuv420

---
 RtspFace/RTSPClient.cpp |  135 +++++++++++++++++++++++++++++++++++++++------
 1 files changed, 117 insertions(+), 18 deletions(-)

diff --git a/RtspFace/RTSPClient.cpp b/RtspFace/RTSPClient.cpp
index 831075c..a306d89 100644
--- a/RtspFace/RTSPClient.cpp
+++ b/RtspFace/RTSPClient.cpp
@@ -23,6 +23,12 @@
 #include "liveMedia.hh"
 #include "BasicUsageEnvironment.hh"
 
+#include <iostream>
+#include <libbase64.h>
+
+bool initH264DecoderEnv(uint8_t* sps, size_t spsSize, uint8_t* pps, size_t ppsSize);
+int decodeH264(uint8_t* pBuffer, int dwBufsize, const char *outfile)  ;
+
 // Forward function definitions:
 
 // RTSP 'response handlers':
@@ -465,6 +471,42 @@
   }
 }
 
+SPropRecord* parseSPropParameterSets(char const* sPropParameterSetsStr,  
+                                     // result parameter:  
+                                     size_t& numSPropRecords) {  
+  // Make a copy of the input string, so we can replace the commas with '\0's:  
+  char* inStr = strDup(sPropParameterSetsStr);  
+  if (inStr == NULL) {  
+    numSPropRecords = 0;  
+    return NULL;  
+  }  
+  
+  // Count the number of commas (and thus the number of parameter sets):  
+  numSPropRecords = 1;  
+  char* s;  
+  for (s = inStr; *s != '\0'; ++s) {  
+    if (*s == ',') {  
+      ++numSPropRecords;  
+      *s = '\0';  
+    }  
+  }  
+  
+  // Allocate and fill in the result array:  
+  SPropRecord* resultArray = new SPropRecord[numSPropRecords]; //****** 鐪嬪埌 杩欓噷浜� 鎶� *******/  
+  s = inStr;  
+  for (unsigned i = 0; i < numSPropRecords; ++i) {  
+    resultArray[i].sPropBytes = new uint8_t[256];
+	
+	size_t sPropLength = 0;
+	base64_decode(s, strlen(s), (char*)resultArray[i].sPropBytes, &sPropLength, 0);
+	resultArray[i].sPropLength = sPropLength;
+	
+    s += strlen(s) + 1;  
+  }  
+  
+  delete[] inStr;  
+  return resultArray;  
+}
 
 // Implementation of "DummySink":
 
@@ -481,6 +523,18 @@
     fSubsession(subsession) {
   fStreamId = strDup(streamId);
   fReceiveBuffer = new u_int8_t[DUMMY_SINK_RECEIVE_BUFFER_SIZE];
+  
+  //parse sdp
+  //const char* strSDP = fSubsession.savedSDPLines();
+  const char* strFmtp = fSubsession.fmtp_spropparametersets();
+  //std::cout << strFmtp << std::endl;
+  
+  size_t numSPropRecords = 0;
+  SPropRecord *p_record = parseSPropParameterSets(fSubsession.fmtp_spropparametersets(), numSPropRecords);
+	SPropRecord &sps = p_record[0];  
+	SPropRecord &pps = p_record[1];
+	
+	initH264DecoderEnv(sps.sPropBytes, sps.sPropLength, pps.sPropBytes, pps.sPropLength);
 }
 
 DummySink::~DummySink() {
@@ -491,6 +545,10 @@
 void DummySink::afterGettingFrame(void* clientData, unsigned frameSize, unsigned numTruncatedBytes,
 				  struct timeval presentationTime, unsigned durationInMicroseconds) {
   DummySink* sink = (DummySink*)clientData;
+
+  if (frameSize > 0)
+	decodeH264(sink->fReceiveBuffer, frameSize, NULL);
+  
   sink->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
 }
 
@@ -535,24 +593,30 @@
 
 *********/
 
-AVFrame* g_pAVFrame = NULL;
-AVCodecContext* g_pAVCodecContext  = NULL;
-
-void initH264DecoderEnv()
+extern "C"
 {
-	avcodec_init();  
-	av_register_all();  
+	#include <libavcodec/avcodec.h>
+	#include <libavutil/frame.h>
+	#include <libavformat/avformat.h>
+}
 
-	g_pAVCodecContext = avcodec_alloc_context();
+AVCodecContext* g_pAVCodecContext  = NULL;
+AVFrame* g_pAVFrame = NULL;
+
+bool initH264DecoderEnv(uint8_t* sps, size_t spsSize, uint8_t* pps, size_t ppsSize)
+{
+	av_register_all();
 
 	// find the video encoder
-	AVCodec* avCodec = avcodec_find_decoder(CODEC_ID_H264);  
+	AVCodec* avCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
 
 	if (!avCodec)   
 	{  
 		printf("codec not found!\n");  
 		return -1;  
 	}  
+
+	g_pAVCodecContext = avcodec_alloc_context3(avCodec);
 
 	//鍒濆鍖栧弬鏁帮紝涓嬮潰鐨勫弬鏁板簲璇ョ敱鍏蜂綋鐨勪笟鍔″喅瀹�
 	g_pAVCodecContext->time_base.num = 1;
@@ -563,21 +627,49 @@
 	g_pAVCodecContext->width = 1920;
 	g_pAVCodecContext->height = 1080;
 
-	if(avcodec_open(g_pAVCodecContext, avCodec) >= 0)
-		g_pAVFrame = avcodec_alloc_frame();// Allocate video frame
+	if (g_pAVCodecContext->extradata == NULL)  
+    {  
+        int totalsize = 0;  
+        unsigned char* tmp = NULL;  
+        unsigned char nalu_header[4] = { 0, 0, 0, 1 };  
+  
+        totalsize = 8 + spsSize + ppsSize;  
+  
+        tmp = new unsigned char[totalsize];  
+        memcpy(tmp, nalu_header, 4);  
+        memcpy(tmp + 4, sps, spsSize);  
+        memcpy(tmp + 4 + spsSize, nalu_header, 4);  
+        memcpy(tmp + 4 + spsSize + 4, pps, ppsSize);  
+  
+        g_pAVCodecContext->extradata_size = totalsize; // g_pAVCodecContext 涓烘垜瑙g爜鏃跺�欎娇鐢ㄧ殑涓婁笅鏂�  
+  
+        g_pAVCodecContext->extradata = tmp;  
+    }
+	
+	if(avcodec_open2(g_pAVCodecContext, avCodec, NULL) >= 0)
+		g_pAVFrame = av_frame_alloc();// Allocate video frame
 	else
-		return -1;
+		return false;
+	
+	return true;
 }
 
-int decodeH264(char* pBuffer, int dwBufsize, const char *outfile,  
-        const char *sps,const int sps_len,const char *pps,const int pps_len)  
+int decodeH264(uint8_t* pBuffer, int dwBufsize, const char *outfile)  
 {
 	AVPacket packet = {0};
 	int frameFinished = dwBufsize;//杩欎釜鏄殢渚垮~鍏ユ暟瀛楋紝娌′粈涔堜綔鐢�
 
-	packet.data = pBuffer;//杩欓噷濉叆涓�涓寚鍚戝畬鏁碒264鏁版嵁甯х殑鎸囬拡
-	packet.size = dwBufsize;//杩欎釜濉叆H264鏁版嵁甯х殑澶у皬
+	uint8_t newBuff[dwBufsize+4];
+	newBuff[0]=0x00; newBuff[1]=0x00; newBuff[2]=0x00; newBuff[3]=0x01;
+	memcpy(newBuff + 4, pBuffer, dwBufsize);
+	
+	//packet.data = pBuffer;//杩欓噷濉叆涓�涓寚鍚戝畬鏁碒264鏁版嵁甯х殑鎸囬拡
+	//packet.size = dwBufsize;//杩欎釜濉叆H264鏁版嵁甯х殑澶у皬
 
+	if (av_packet_from_data(&packet, newBuff, dwBufsize + 4) != 0){  
+		printf("exchange data failed!\n");
+	}  
+	
 	//涓嬮潰寮�濮嬬湡姝g殑瑙g爜
 	avcodec_decode_video2(g_pAVCodecContext, g_pAVFrame, &frameFinished, &packet);
 	if(frameFinished)//鎴愬姛瑙g爜
@@ -586,10 +678,10 @@
 		int newSize = picSize * 1.5;
 
 		//鐢宠鍐呭瓨
-		unsigned char *buff = new unsigned char[newSize];
+		uint8_t *buff = new uint8_t[newSize];
 
-		int height = p->codec->height;
-		int width = p->codec->width;
+		int height = g_pAVFrame->height;
+		int width = g_pAVFrame->width;
 
 		//鍐欏叆鏁版嵁
 		int a=0;
@@ -611,6 +703,13 @@
 
 		//buff readly
 
+		//static size_t f=0;
+		//char fname[50];
+		//sprintf(fname, "%u.yuv420", ++f);
+		//FILE * pFile = fopen (fname,"wb");
+		//fwrite (buff , sizeof(char), newSize, pFile);
+		//fclose(pFile);
+		
 		delete[] buff;
 	}
 	else

--
Gitblit v1.8.0