From fa8b072f4c5359703ae664ef8a5d79139742e2e8 Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期五, 29 十一月 2019 11:20:08 +0800 Subject: [PATCH] optimize ffmpeg decode cpu and memory --- csrc/worker/decoder.cpp | 115 ++++++++++++++++++++++++++++++++------------------------- 1 files changed, 64 insertions(+), 51 deletions(-) diff --git a/csrc/worker/decoder.cpp b/csrc/worker/decoder.cpp index 67af0a1..4d432c1 100644 --- a/csrc/worker/decoder.cpp +++ b/csrc/worker/decoder.cpp @@ -4,6 +4,7 @@ #include "../ffmpeg/format/FormatIn.hpp" #include "../ffmpeg/data/CodedData.hpp" #include "../ffmpeg/log/log.hpp" +#include "../common.hpp" extern "C"{ #include <libavformat/avformat.h> @@ -22,10 +23,11 @@ {} decoder::~decoder(){ - + std::lock_guard<std::mutex> l(mutex_frm_); for(auto i : list_frm_){ - av_frame_free(&i.frm); + if (i.avframe) + av_frame_free(&i.avframe); } list_frm_.clear(); } @@ -46,25 +48,14 @@ return 0; } - int decoder::saveFrame(AVFrame *frame, int64_t &id){ - while(list_frm_.size() > 50){ - for(int i = 0; i < 12; i++){ - auto t = list_frm_.front(); - av_frame_free(&t.frm); - list_frm_.pop_front(); - } - } - list_frm_.push_back({frame,id}); - return list_frm_.size(); - } + int decoder::SetFrame(const CPacket &pkt){ + auto data = pkt.data; - int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ - - if (!data) return -1; - if (!decRef_->isVideoPkt(&data->getAVPacket())) return -2; + if (!data) return -10; + if (!decRef_->isVideoPkt(&data->getAVPacket())) return -20; if (decRef_->getCodecContext() == NULL){ - if (initDecoder() != 0) return -3; + if (initDecoder() != 0) return -30; } AVFrame *frame = av_frame_alloc(); @@ -72,54 +63,76 @@ av_copy_packet(&np, &data->getAVPacket()); auto ret = decRef_->decode(frame, &np); av_packet_unref(&np); - + if (ret == 0){ - saveFrame(frame, id); + return saveFrame(frame, pkt.v_id); } + + return ret; } void decoder::GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id){ - - AVFrame *frm = NULL; + FRM frm; { std::lock_guard<std::mutex> l(mutex_frm_); if(list_frm_.empty()){ - *data = NULL; - *w = *h = 0; - *id = -1; return; } - auto p = list_frm_.front(); + frm = list_frm_.front(); list_frm_.pop_front(); - frm = p.frm; - *id = p.id; - *w = frm->width; - *h = frm->height; - *format = frm->format; } - - *length = avpicture_get_size((enum AVPixelFormat)frm->format, frm->width, frm->height); - if (*length <= 0){ - logIt("get raw frame data error"); - *data = NULL; - *w = *h = 0; - *id = -1; - return; - } - - unsigned char *picData = (unsigned char*)malloc(*length); - auto ret = avpicture_layout((const AVPicture*)frm, (enum AVPixelFormat)frm->format, frm->width, frm->height, picData, *length); - av_frame_free(&frm); - if (ret < 0){ - *data = NULL; - *w = *h = 0; - *id = -1; - free(picData); - return; + AVFrame *frame = frm.avframe; + int pix_fmt = frame->format; + uint8_t *origin = cvbridge::extractFrame(frame, &frm.length); + av_frame_free(&frame); + if (!origin) return; + + uint8_t *finale = NULL; + if (pix_fmt != AV_PIX_FMT_NV12){ + finale = (uint8_t*)malloc(frm.length); + + unsigned char* SrcU = origin + frm.width * frm.height; + unsigned char* SrcV = SrcU + frm.width * frm.height / 4 ; + unsigned char* DstU = finale + frm.width * frm.height; + memcpy(finale, origin, frm.width * frm.height); + int i = 0; + for( i = 0 ; i < frm.width * frm.height / 4 ; i++ ){ + *(DstU++) = *(SrcU++); + *(DstU++) = *(SrcV++); + } + free(origin); + }else{ + finale = origin; } - *data = picData; + *data = finale; + *id = frm.id; + *w = frm.width; + *h = frm.height; + *format = pix_fmt; + *length = frm.length; + } +//////////////////////////////////////////////////////////////////////// +static const int maxSize = 5; + int decoder::saveFrame(AVFrame *frame, const int64_t &id){ + FRM frm; + frm.avframe = frame; + frm.width = frame->width; + frm.height = frame->height; + frm.id = id; + + std::lock_guard<std::mutex> l(mutex_frm_); + while(list_frm_.size() > maxSize){ + for(int i = 0; i < (maxSize>1); i++){ + auto t = list_frm_.front(); + av_frame_free(&t.avframe); + list_frm_.pop_front(); + } + } + + list_frm_.push_back(frm); + return list_frm_.size(); } } // namespace cffmpeg_wrap -- Gitblit v1.8.0