From 109ffe9a777658936a38d0c146579a67c60a0d17 Mon Sep 17 00:00:00 2001 From: xuxiuxi <xuxiuxi@454eff88-639b-444f-9e54-f578c98de674> Date: 星期四, 11 五月 2017 17:48:48 +0800 Subject: [PATCH] --- RtspFace/PL_H264Decoder.cpp | 172 +++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 107 insertions(+), 65 deletions(-) diff --git a/RtspFace/PL_H264Decoder.cpp b/RtspFace/PL_H264Decoder.cpp index b27918c..87d8735 100644 --- a/RtspFace/PL_H264Decoder.cpp +++ b/RtspFace/PL_H264Decoder.cpp @@ -1,4 +1,6 @@ #include "PL_H264Decoder.h" +#include "MaterialBuffer.h" +#include "logger.h" #include <H264VideoRTPSource.hh> // for SPropRecord #include <libbase64.h> @@ -12,19 +14,24 @@ struct H264Decoder_Internal { - uint8_t buffer[1920*1080*3]; - size_t buffSize; - size_t buffSizeMax; + //uint8_t buffer[1920*1080*3]; + //size_t buffSize; + //size_t buffSizeMax; bool fmtp_set_to_context; bool payError; AVCodecContext* pAVCodecContext; - AVFrame* pAVFrame; + AVFrame* pAVFrame;//#todo delete + + MB_Frame lastFrame; + PL_H264Decoder_Config config; H264Decoder_Internal() : - buffSize(0), buffSizeMax(sizeof(buffer)), fmtp_set_to_context(false), - payError(false), - pAVCodecContext(nullptr), pAVFrame(nullptr) + //buffSize(0), buffSizeMax(sizeof(buffer)), + fmtp_set_to_context(false), + payError(true), + pAVCodecContext(nullptr), pAVFrame(nullptr), + lastFrame(), config() { } @@ -34,9 +41,18 @@ void reset() { - buffSize = 0; + //buffSize = 0; fmtp_set_to_context = false; - payError = false; + payError = true; + + pAVCodecContext = nullptr; + pAVFrame = nullptr; + + MB_Frame _lastFrame; + lastFrame = _lastFrame; + + PL_H264Decoder_Config _config; + config = _config; } }; @@ -59,6 +75,12 @@ { H264Decoder_Internal* in = (H264Decoder_Internal*)internal; in->reset(); + + if (args) + { + PL_H264Decoder_Config* config = (PL_H264Decoder_Config*)args; + in->config = *config; + } return true; } @@ -114,19 +136,20 @@ if (!avCodec) { - printf("codec not found!\n"); + LOG_WARN << "codec not found!" << std::endl; return false; } in->pAVCodecContext = avcodec_alloc_context3(avCodec); - - in->pAVCodecContext->time_base.num = 1; - in->pAVCodecContext->frame_number = 1; + in->pAVCodecContext->codec_type = AVMEDIA_TYPE_VIDEO; - in->pAVCodecContext->bit_rate = 0; - in->pAVCodecContext->time_base.den = 25; - in->pAVCodecContext->width = 1920; - in->pAVCodecContext->height = 1080; + // this is only reference for codec + //in->pAVCodecContext->frame_number = 1; + //in->pAVCodecContext->bit_rate = 0; + //in->pAVCodecContext->time_base.num = 1; + //in->pAVCodecContext->time_base.den = 25; + //in->pAVCodecContext->width = 1920; + //in->pAVCodecContext->height = 1080; if (in->pAVCodecContext->extradata == NULL) { @@ -155,90 +178,108 @@ return true; } -bool decodeH264(H264Decoder_Internal* in, uint8_t* buffer, size_t buffSize) +bool decodeH264(H264Decoder_Internal* in, uint8_t* buffer, size_t buffSize, timeval pts) { AVPacket packet = {0}; - int frameFinished = buffSize; + int gotPicture = buffSize; // frameFinished if (av_packet_from_data(&packet, buffer, buffSize) != 0) { - printf("av_packet_from_data error\n"); + LOG_WARN << "av_packet_from_data error" << std::endl; return false; - } + } + + packet.pts = packet.dts = (pts.tv_sec * 1000 * 1000 + pts.tv_usec) / 90000; // decode - avcodec_decode_video2(in->pAVCodecContext, in->pAVFrame, &frameFinished, &packet); - if(frameFinished) + avcodec_decode_video2(in->pAVCodecContext, in->pAVFrame, &gotPicture, &packet); + if(gotPicture) { // decode ok - - int picSize = in->pAVCodecContext->height * in->pAVCodecContext->width; - in->buffSize = picSize * 1.5; - - int height = in->pAVFrame->height; - int width = in->pAVFrame->width; - - // write yuv420 - int a=0; - for (int i = 0; i < height; i++) - { - memcpy(in->buffer + a, in->pAVFrame->data[0] + i * in->pAVFrame->linesize[0], width); - a += width; - } - for (int i=0; i<height/2; i++) - { - memcpy(in->buffer + a, in->pAVFrame->data[1] + i * in->pAVFrame->linesize[1], width / 2); - a += width / 2; - } - for (int i=0; i<height/2; i++) - { - memcpy(in->buffer + a, in->pAVFrame->data[2] + i * in->pAVFrame->linesize[2], width / 2); - a += width / 2; - } - - //in->buffer readly - - //static size_t f=0; - //char fname[50]; - //sprintf(fname, "%u.yuv420", ++f); - //FILE * pFile = fopen (fname,"wb"); - //fwrite (in->buffer , sizeof(char), in->buffSize, pFile); - //fclose(pFile); + return true; } else - printf("incomplete frame\n"); + { + //#todo sps sps changing + LOG_WARN << "incomplete frame" << std::endl; + return false; + } } bool PL_H264Decoder::pay(const PipeMaterial& pm) { H264Decoder_Internal* in = (H264Decoder_Internal*)internal; + in->payError = true; + if (!in->fmtp_set_to_context) { if (manager == NULL) return false; - std::string fmtp(manager->get_global_param(PLGP_RTSP_FMTP)); + std::string fmtp(manager->get_param(PLGP_RTSP_FMTP)); if (fmtp.empty()) return false; size_t numSPropRecords = 0; SPropRecord *p_record = parseSPropParameterSets(fmtp.c_str(), numSPropRecords); if (numSPropRecords < 2) - return false;//#todo log + { + LOG_WARN << "numSPropRecords < 2" << std::endl; + return false; + } SPropRecord &sps = p_record[0]; SPropRecord &pps = p_record[1]; bool ret = initH264DecoderEnv(in, sps.sPropBytes, sps.sPropLength, pps.sPropBytes, pps.sPropLength); if (!ret) - return false; // #todo log + { + LOG_ERROR << "initH264DecoderEnv error" << std::endl; + return false; + } else in->fmtp_set_to_context = true; } - in->payError = decodeH264(in, pm.buffer, pm.buffSize); - return in->payError; + if (pm.buffer == nullptr) + return false; + + bool ret = false; + if (pm.type == PipeMaterial::PMT_BYTES) + { + if (pm.buffSize <= 0) + return false; + + timeval pts = {0}; + ret = decodeH264(in, (uint8_t*)pm.buffer, pm.buffSize, pts); + } + else if (pm.type == PipeMaterial::PMT_FRAME) + { + MB_Frame* frame = (MB_Frame*)pm.buffer; + + if (frame->buffSize <= 0) + return false; + + ret = decodeH264(in, (uint8_t*)frame->buffer, frame->buffSize, frame->pts); + if (ret) + { + in->lastFrame.type = MB_Frame::MBFT_PTR_AVFRAME; + in->lastFrame.buffer = (uint8_t*)(in->pAVFrame); + in->lastFrame.buffSize = sizeof(in->pAVFrame); + in->lastFrame.width = in->pAVFrame->width; + in->lastFrame.height = in->pAVFrame->height; + + if (in->config.resetPTS) + gettimeofday(&(in->lastFrame.pts),NULL); + else + in->lastFrame.pts = frame->pts; + + } + } + + in->payError = !ret; + return ret; } bool PL_H264Decoder::gain(PipeMaterial& pm) @@ -247,9 +288,10 @@ if (!in->payError) { - pm.buffer = in->buffer; - pm.buffSize = in->buffSize; + pm.type = PipeMaterial::PMT_FRAME; + pm.buffer = &(in->lastFrame); + pm.buffSize = 0; } pm.former = this; - return in->payError; + return !in->payError; } -- Gitblit v1.8.0