houxiao
2016-12-20 cf8dd1b37d9b5e0735868c276d2398b80dc26000
rtsp to yuv420

git-svn-id: http://192.168.1.226/svn/proxy@26 454eff88-639b-444f-9e54-f578c98de674
1个文件已添加
1个文件已修改
158 ■■■■ 已修改文件
RtspFace/RTSPClient.cpp 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/make.sh 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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
RtspFace/make.sh
New file
@@ -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