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