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 +++++++++++++++++++++++++++++++++++++++------
RtspFace/make.sh | 23 +++++++
2 files changed, 140 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
diff --git a/RtspFace/make.sh b/RtspFace/make.sh
new file mode 100644
index 0000000..fbe9d62
--- /dev/null
+++ b/RtspFace/make.sh
@@ -0,0 +1,23 @@
+LIVEMEDIA_BASE=/opt/live
+LIVEMEDIA_INC="-I$LIVEMEDIA_BASE/liveMedia/include -I$LIVEMEDIA_BASE/groupsock/include -I$LIVEMEDIA_BASE/UsageEnvironment/include -I$LIVEMEDIA_BASE/BasicUsageEnvironment/include"
+LIVEMEDIA_LIB="-L$LIVEMEDIA_BASE/liveMedia -L$LIVEMEDIA_BASE/groupsock -L$LIVEMEDIA_BASE/UsageEnvironment -L$LIVEMEDIA_BASE/BasicUsageEnvironment -lliveMedia -lgroupsock -lBasicUsageEnvironment -lUsageEnvironment"
+
+FFMPEG_BASE=/opt/ffmpeg-3.2.2/inst
+FFMPEG_INC="-I$FFMPEG_BASE/include"
+FFMPEG_LIB="-L$FFMPEG_BASE/lib -lavutil -lavformat -lswresample -lavcodec"
+
+LIBBASE64_BASE=/opt/base64
+LIBBASE64_INC="-I$LIBBASE64_BASE/include"
+LIBBASE64_LIB="$LIBBASE64_BASE/lib/libbase64.o"
+
+CPPFLAGS+="$LIVEMEDIA_INC $FFMPEG_INC $LIBBASE64_INC"
+LDFLAGS+="$LIVEMEDIA_LIB $FFMPEG_LIB $LIBBASE64_LIB"
+
+CFLAGS+="-D__STDC_CONSTANT_MACROS"
+
+rm rtsp_face
+
+g++ -g RTSPClient.cpp $CFLAGS $CPPFLAGS $LDFLAGS -o rtsp_face
+
+#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$FFMPEG_BASE/lib
+#./rtsp_face rtsp://admin:admin12345@192.168.1.63:554/h264/ch1/main/av_stream
--
Gitblit v1.8.0