From 9e5babf9db52e64bdae60137be7696e56241fca6 Mon Sep 17 00:00:00 2001 From: xingzilong <xingzilong@454eff88-639b-444f-9e54-f578c98de674> Date: 星期五, 18 八月 2017 18:12:17 +0800 Subject: [PATCH] H264 NALU解析 并在RTSPServer判断 --- RtspFace/PL_RTSPServer2.cpp | 237 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 190 insertions(+), 47 deletions(-) diff --git a/RtspFace/PL_RTSPServer2.cpp b/RtspFace/PL_RTSPServer2.cpp index bda31d5..7974fb5 100644 --- a/RtspFace/PL_RTSPServer2.cpp +++ b/RtspFace/PL_RTSPServer2.cpp @@ -1,4 +1,4 @@ -#include "PL_RTSPServer.h" +#include "PL_RTSPServer2.h" #include "MaterialBuffer.h" #include "logger.h" @@ -12,9 +12,35 @@ #include "PreAllocBufferQueue.h" #include "MediaHelper.h" -struct RTSPServer_Internal +typedef enum { + NALU_TYPE_SLICE = 1, + NALU_TYPE_DPA = 2, + NALU_TYPE_DPB = 3, + NALU_TYPE_DPC = 4, + NALU_TYPE_IDR = 5, + NALU_TYPE_SEI = 6, + NALU_TYPE_SPS = 7, + NALU_TYPE_PPS = 8, + NALU_TYPE_AUD = 9, + NALU_TYPE_EOSEQ = 10, + NALU_TYPE_EOSTREAM = 11, + NALU_TYPE_FILL = 12, +} NaluType; + +typedef struct { - RTSPServerConfig config; + int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested) + unsigned len; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU) + unsigned max_size; //! Nal Unit Buffer size + int forbidden_bit; //! should be always FALSE + int nal_reference_idc; //! NALU_PRIORITY_xxxx + int nal_unit_type; //! NALU_TYPE_xxxx + char *buf; //! contains the first byte followed by the EBSP +} NALU_t; + +struct RTSPServer2_Internal +{ + RTSPServer2Config config; pthread_t live_daemon_thid; bool live_daemon_running; @@ -24,27 +50,35 @@ PreAllocBufferQueue* frameQueue; pthread_mutex_t* queue_mutex; pthread_mutex_t* queue_empty_mutex; + pthread_mutex_t* queue_full_mutex; bool auxLineSet; - RTSPServer_Internal() : + uint8_t lastSps[50]; + uint8_t lastPps[50]; + uint8_t lastSpsPps[100]; + + size_t lastSpsSize; + size_t lastPpsSize; + + RTSPServer2_Internal() : config(), live_daemon_thid(0), live_daemon_running(false), server(nullptr), - frameQueue(nullptr), queue_mutex(new pthread_mutex_t), queue_empty_mutex(new pthread_mutex_t), //#todo from config - auxLineSet(false) + frameQueue(nullptr), queue_mutex(nullptr), queue_empty_mutex(nullptr), queue_full_mutex(nullptr), //#todo from config + auxLineSet(false), + lastSps(), lastPps(),lastSpsPps(),lastSpsSize(0),lastPpsSize(0) { - pthread_mutex_init(queue_mutex, NULL); } - ~RTSPServer_Internal() + ~RTSPServer2_Internal() { reset(); } void reset() { - RTSPServerConfig _config; + RTSPServer2Config _config; config =_config; if (frameQueue != nullptr) @@ -59,7 +93,6 @@ delete queue_mutex; queue_mutex = nullptr; } - queue_mutex = new pthread_mutex_t; pthread_mutex_init(queue_mutex, NULL); @@ -69,9 +102,17 @@ delete queue_empty_mutex; queue_empty_mutex = nullptr; } - queue_empty_mutex = new pthread_mutex_t; pthread_mutex_init(queue_empty_mutex, NULL); + + if (queue_full_mutex != nullptr) + { + pthread_mutex_destroy(queue_full_mutex); + delete queue_full_mutex; + queue_full_mutex = nullptr; + } + queue_full_mutex = new pthread_mutex_t; + pthread_mutex_init(queue_full_mutex, NULL); live_daemon_thid = 0; live_daemon_running = false; @@ -79,30 +120,32 @@ server = nullptr; //#todo delete auxLineSet = false; + lastSpsSize = 0; + lastPpsSize = 0; } }; -PipeLineElem* create_PL_RTSPServer() +PipeLineElem* create_PL_RTSPServer2() { - return new PL_RTSPServer; + return new PL_RTSPServer2; } -PL_RTSPServer::PL_RTSPServer() : internal(new RTSPServer_Internal) +PL_RTSPServer2::PL_RTSPServer2() : internal(new RTSPServer2_Internal) { } -PL_RTSPServer::~PL_RTSPServer() +PL_RTSPServer2::~PL_RTSPServer2() { - delete (RTSPServer_Internal*)internal; + delete (RTSPServer2_Internal*)internal; internal = nullptr; } struct DeliverFrameCallback { - RTSPServer_Internal* in; + RTSPServer2_Internal* in; PreAllocBufferQueue::Buffer* lastBuffer; - DeliverFrameCallback(RTSPServer_Internal* _in) + DeliverFrameCallback(RTSPServer2_Internal* _in) : in(_in) , lastBuffer(nullptr) { } @@ -116,17 +159,44 @@ } } + static int get_nalu_info(NALU_t* _p_nalu_info,const uint8_t* _pbuffer,const size_t _len) + { + if((nullptr==_pbuffer)||(_len<=4)) + { + return -1; + } + _p_nalu_info->forbidden_bit = _pbuffer[4] & 0x80; //1 bit + _p_nalu_info->nal_reference_idc = _pbuffer[4] & 0x60; // 2 bit + _p_nalu_info->nal_unit_type = _pbuffer[4] & 0x1f;// 5 bit + return 0; + } + static bool deliverFrame(void* args, uint8_t*& buffer, size_t& buffSize, timeval& pts) { DeliverFrameCallback* _this = (DeliverFrameCallback*)args; + + if (_this->in->config.payBlockFullQueue && !_this->in->frameQueue->Full()) + { + int ret = pthread_mutex_unlock(_this->in->queue_full_mutex); + if (ret != 0) + { + LOG_WARN << "pthread_mutex_unlock queue_full_mutex, ret=" << ret << LOG_ENDL; + } + } if (_this->in->frameQueue->Empty()) { int ret = pthread_mutex_lock(_this->in->queue_empty_mutex); if (ret != 0) { - LOG_WARN << "pthread_mutex_lock queue_empty_mutex, ret=" << ret << std::endl; + LOG_WARN << "pthread_mutex_lock queue_empty_mutex, ret=" << ret << LOG_ENDL; } + } + + int ret = pthread_mutex_lock(_this->in->queue_empty_mutex); + if (ret != 0) + { + LOG_WARN << "pthread_mutex_lock queue_empty_mutex, ret=" << ret << LOG_ENDL; } ScopeLocker<pthread_mutex_t>(_this->in->queue_mutex); @@ -138,17 +208,39 @@ _this->lastBuffer = nullptr; } + //#todo +#if 0 + //find frameQueue->Seek is pps/sps + PreAllocBufferQueue::Buffer* _p_Buffer = _this->in->frameQueue->Seek(); + // if not: send bufferred pps , return; + + NALU_t _obj_NALU_t; + get_nalu_info(&_obj_NALU_t,_p_Buffer->buffer,_p_Buffer->buffSize); + if(NALU_TYPE_PPS!=_obj_NALU_t.nal_unit_type) + { + memcpy(_this->in->lastSpsPps,_this->in->lastSps,_this->in->lastSpsSize); + memcpy(_this->in->lastSpsPps+_this->in->lastSpsSize,_this->in->lastPps,_this->in->lastPpsSize); + buffer = _this->in->lastSpsPps; + buffSize = _this->in->lastSpsSize+_this->in->lastPpsSize; + gettimeofday(&pts, NULL); + return true; + } +#endif + + _this->lastBuffer = _this->in->frameQueue->Dequeue(); if (_this->lastBuffer == nullptr) return false; - buffer = _this->lastBuffer->buffer; - buffSize = _this->lastBuffer->buffSize; + buffer = _this->lastBuffer->buffer + 4; // #todo send nalu + buffSize = _this->lastBuffer->buffSize - 4; + //LOG_WARN << "sizeS=" << buffSize << LOG_ENDL; - LOG_INFO << "DeliverFrameCallback buffSize=" << buffSize << LOG_ENDL; + //LOG_INFO << "DeliverFrameCallback buffSize=" << buffSize << LOG_ENDL; //static size_t f = 0; //static FILE *pFile = fopen("/data/bb.264", "wb"); //fwrite(buffer, sizeof(char), buffSize, pFile); + //fflush(pFile); //if (++f > 30){ // fclose(pFile); // exit(0); @@ -173,7 +265,7 @@ static void* live_daemon_thd(void* arg) { - RTSPServer_Internal* in = (RTSPServer_Internal*)arg; + RTSPServer2_Internal* in = (RTSPServer2_Internal*)arg; in->server = new MESAI::LiveRTSPServer(nullptr, 8554, 8080); @@ -191,13 +283,14 @@ in->live_daemon_running = false; } -bool PL_RTSPServer::init(void* args) +bool PL_RTSPServer2::init(void* args) { - RTSPServer_Internal* in = (RTSPServer_Internal*)internal; + RTSPServer2_Internal* in = (RTSPServer2_Internal*)internal; + in->reset(); if (args) { - RTSPServerConfig* config = (RTSPServerConfig*)args; + RTSPServer2Config* config = (RTSPServer2Config*)args; in->config = *config; } @@ -205,37 +298,37 @@ qcfg.multithreadSafe = false; qcfg.fullQueueDropFront = true; qcfg.fullQueueSync = false; - qcfg.count = 32; - qcfg.maxBuffSize = 100000; + qcfg.count = 20; + qcfg.maxBuffSize = 524288; // 512KB in->frameQueue = new PreAllocBufferQueue(qcfg); int ret = pthread_create(&(in->live_daemon_thid), NULL, live_daemon_thd, in); if(ret != 0) { - LOG_ERROR << "pthread_create: " << strerror(ret) << std::endl; + LOG_ERROR << "pthread_create: " << strerror(ret) << LOG_ENDL; return false; } return true; } -void PL_RTSPServer::finit() +void PL_RTSPServer2::finit() { - RTSPServer_Internal* in = (RTSPServer_Internal*)internal; + RTSPServer2_Internal* in = (RTSPServer2_Internal*)internal; pthread_join(in->live_daemon_thid, NULL); } -bool PL_RTSPServer::pay(const PipeMaterial& pm) +bool PL_RTSPServer2::pay(const PipeMaterial& pm) { - RTSPServer_Internal* in = (RTSPServer_Internal*)internal; + RTSPServer2_Internal* in = (RTSPServer2_Internal*)internal; if (pm.buffer == nullptr) return false; if (pm.type != PipeMaterial::PMT_FRAME) { - LOG_ERROR << "PL_RTSPServer::pay only support PMT_FRAME" << std::endl; + LOG_ERROR << "PL_RTSPServer2::pay only support PMT_FRAME" << LOG_ENDL; return false; } @@ -251,35 +344,79 @@ framedSource->ppsBase64 = ppsStr; in->auxLineSet = true; + + LOG_INFO <<"sps:" << spsStr.size() << ", pps:" << ppsStr.size() << LOG_ENDL; } } - MB_Frame* frame = (MB_Frame*)pm.buffer; - if (frame->buffer == nullptr || frame->buffSize == 0) - return false; + MB_Frame* frame = (MB_Frame*)pm.buffer; + if (frame->buffer == nullptr || frame->buffSize == 0) + return false; + //LOG_WARN << "sizeR=" << frame->buffSize << LOG_ENDL; + + + +//#todo +#if 0 + // find if is pps/ + // buffer the frame into spsRTSPServer2_Internal + + if(frame->type==MB_Frame::MBFT_H264_NALU) + { + NALU_t objNALU_t; + DeliverFrameCallback::get_nalu_info(&objNALU_t,(const uint8_t*)(frame->buffer),frame->buffSize); + if(NALU_TYPE_PPS!=objNALU_t.nal_unit_type) + { + memcpy(in->lastPps,frame->buffer,frame->buffSize); + } + else if(NALU_TYPE_SPS!=objNALU_t.nal_unit_type) + { + memcpy(in->lastSps,frame->buffer,frame->buffSize); + } + } +#endif + + while (in->config.payBlockFullQueue && in->frameQueue->Full()) + { + int ret = pthread_mutex_lock(in->queue_full_mutex); + if (ret != 0) + { + LOG_WARN << "pthread_mutex_lock queue_full_mutex, ret=" << ret << LOG_ENDL; + } + + //if (in->frameQueue->Full()) + //{ + // LOG_WARN << "frameQueue wakeup while full" << LOG_ENDL; + // return false; + //} + } ScopeLocker<pthread_mutex_t>(in->queue_mutex); //if (in->frameQueue->Full()) - // LOG_WARN << "PL_RTSPServer::pay may lost data" << std::endl; + // LOG_WARN << "PL_RTSPServer2::pay may lost data" << LOG_ENDL; PreAllocBufferQueue::Buffer* qbuff = in->frameQueue->Enqueue(); if (qbuff == nullptr) { - LOG_WARN << "PL_RTSPServer::pay may lost data size=" << frame->buffSize << std::endl; + LOG_WARN << "PL_RTSPServer2::pay may lost data size=" << frame->buffSize << LOG_ENDL; int ret = pthread_mutex_unlock(in->queue_empty_mutex); if (ret != 0) { - LOG_WARN << "pthread_mutex_unlock queue_empty_mutex, ret=" << ret << std::endl; + LOG_WARN << "pthread_mutex_unlock queue_empty_mutex, ret=" << ret << LOG_ENDL; } return false; } - memcpy(qbuff->buffer, frame->buffer, frame->buffSize); - qbuff->buffSize = frame->buffSize; + const PreAllocBufferQueue::Config& qcfg(in->frameQueue->GetConfig()); + size_t copySize = std::min(qcfg.maxBuffSize, frame->buffSize); + + memcpy(qbuff->buffer, frame->buffer, copySize);//#todo size min + qbuff->buffSize = copySize; //static size_t f = 0; //static FILE *pFile = fopen("/data/aa.264", "wb"); - //fwrite(qbuff->buffer, sizeof(char), frame->buffSize, pFile); + //fwrite(qbuff->buffer, sizeof(char), qbuff->buffSize, pFile); + //fflush(pFile); //if (++f > 400){ // fclose(pFile); // exit(0); @@ -288,18 +425,24 @@ int ret = pthread_mutex_unlock(in->queue_empty_mutex); if (ret != 0) { - LOG_WARN << "pthread_mutex_unlock queue_empty_mutex, ret=" << ret << std::endl; + LOG_WARN << "pthread_mutex_unlock queue_empty_mutex, ret=" << ret << LOG_ENDL; } + + if (copySize < frame->buffSize) + { + LOG_WARN << "copy frame truncated" << LOG_ENDL; + } + return true; } -bool PL_RTSPServer::gain(PipeMaterial& pm) +bool PL_RTSPServer2::gain(PipeMaterial& pm) { - RTSPServer_Internal* in = (RTSPServer_Internal*)internal; + RTSPServer2_Internal* in = (RTSPServer2_Internal*)internal; pm.type = PipeMaterial::PMT_NONE; pm.buffer = nullptr; pm.buffSize = 0; pm.former = this; - return true; + return false; } -- Gitblit v1.8.0