houxiao
2016-12-20 cf8dd1b37d9b5e0735868c276d2398b80dc26000
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_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;//这里填入一个指向完整H264数据帧的指针
   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;//这里填入一个指向完整H264数据帧的指针
   //packet.size = dwBufsize;//这个填入H264数据帧的大小
   if (av_packet_from_data(&packet, newBuff, dwBufsize + 4) != 0){
      printf("exchange data failed!\n");
   }
   //下面开始真正的解码
   avcodec_decode_video2(g_pAVCodecContext, g_pAVFrame, &frameFinished, &packet);
   if(frameFinished)//成功解码
@@ -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