| | |
| | | #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': |
| | |
| | | } |
| | | } |
| | | |
| | | 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": |
| | | |
| | |
| | | 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() { |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | |
| | | *********/ |
| | | |
| | | 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; |
| | |
| | | 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)//成功解码 |
| | |
| | | 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; |
| | |
| | | |
| | | //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 |