From b35d0da3fb4ceec328286851d0e2b316872ab04a Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期四, 10 十月 2019 14:20:55 +0800 Subject: [PATCH] send frame not bgr --- csrc/wrapper.cpp | 43 +++----- csrc/worker/decoder.cpp | 68 +++++-------- csrc/wrapper.hpp | 2 csrc/ffmpeg/bridge/cvbridge.cpp | 127 ++++++++++--------------- csrc/worker/decoder.hpp | 6 + csrc/ffmpeg/bridge/cvbridge.hpp | 11 - 6 files changed, 105 insertions(+), 152 deletions(-) diff --git a/csrc/ffmpeg/bridge/cvbridge.cpp b/csrc/ffmpeg/bridge/cvbridge.cpp index 0ab95d5..21d09a1 100644 --- a/csrc/ffmpeg/bridge/cvbridge.cpp +++ b/csrc/ffmpeg/bridge/cvbridge.cpp @@ -2,6 +2,7 @@ #include <string.h> #include <stdexcept> +#include <memory> extern "C"{ #include <libavcodec/avcodec.h> @@ -22,7 +23,6 @@ double *param/*=NULL*/) :scale_(new swscale_wrapper) ,pic_(new PicData(dstW, dstH, dstFmt)) - ,buff_fill_(NULL) { bool flag = !!scale_ && !!pic_; flag = scale_->initContext(srcW, srcH, srcFmt, dstW, dstH, dstFmt, flags) && flag; @@ -39,106 +39,81 @@ if(pic_){ delete pic_; } - if(buff_fill_){ - free(buff_fill_); - } } - bool cvbridge::copyPicture(uint8_t *out, AVFrame *in){ + uint8_t* cvbridge::convert2Data(AVFrame *in){ if(!scale_ || !pic_){ - return false; + return NULL; } if(!scale_->scaleFrame(in, pic_->getAVFrame())){ - return false; + return NULL; } + uint8_t *out = (uint8_t*)malloc(pic_->getAVPictureSize()); memcpy(out, pic_->getAVPictureData(), pic_->getAVPictureSize()); - return true; + return out; } - bool cvbridge::getAVFrame(uint8_t *in, const int w, const int h, AVFrame * &output){ - int width = w; - int height = h; - AVFrame *temp_rgb_frame = av_frame_alloc(); - temp_rgb_frame->format = (AVPixelFormat)scale_->srcFmt_; - temp_rgb_frame->width = width; - temp_rgb_frame->height = height; - - //create a AVPicture frame from the opencv Mat input image - int ret = avpicture_fill((AVPicture *)temp_rgb_frame, - (uint8_t *)in, - (AVPixelFormat)scale_->srcFmt_, - width, - height); - if(ret < 0){ - av_frame_free(&temp_rgb_frame); - return false; - } - // temp_rgb_frame->linesize[0] = frame.step; - - - output->format = (AVPixelFormat)scale_->dstFmt_; - output->width = width; - output->height = height; - - ret = scale_->scaleFrame(temp_rgb_frame, output); - - av_frame_free(&temp_rgb_frame); + AVFrame* cvbridge::convert2Frame(AVFrame *in){ + if(!scale_ || !pic_){ + return NULL; + } - if(ret) - return true; + if(!scale_->scaleFrame(in, pic_->getAVFrame())){ + return NULL; + } - return false; + return av_frame_clone(pic_->getAVFrame()); } - AVFrame *cvbridge::getAVFrame(uint8_t *in, const int w, const int h){ +///////////////////////////////////////////////////////////////// + + AVFrame *cvbridge::fillFrame(uint8_t *in, const int w, const int h, const int f){ int width = w; int height = h; + int format = f; - if(!buff_fill_){ - int size = avpicture_get_size((AVPixelFormat)scale_->dstFmt_, width, height); - buff_fill_ = (uint8_t *) malloc(size); - } - AVFrame * output = av_frame_alloc(); - const int ret = avpicture_fill((AVPicture*)output, buff_fill_, - (AVPixelFormat)scale_->dstFmt_, width, height); + AVFrame *frame = av_frame_alloc(); + frame->format = format; + frame->width = width; + frame->height = height; + + // int size = avpicture_get_size((enum AVPixelFormat)frame->format, frame->width, frame->height); + // if (size <= 0){ + // return NULL; + // } + // printf("size: %d, res: %dx%d, format: %d\n", size, w, h, f); + // uint8_t *spare = (uint8_t*)malloc(size); + // memcpy(spare, in, size); + + int ret = avpicture_fill((AVPicture *)frame, + (uint8_t *)in, + (AVPixelFormat)frame->format, + frame->width, + frame->height); if(ret < 0){ - av_frame_free(&output); + av_frame_free(&frame); return NULL; } + return frame; + } - if(getAVFrame(in, w, h, output)){ - return output; + uint8_t* cvbridge::extractFrame(AVFrame *in, int *length){ + *length = avpicture_get_size((enum AVPixelFormat)in->format, in->width, in->height); + if (*length <= 0){ + return NULL; } - av_frame_free(&output); - return NULL; - } -////////////////////////////////////////////////////////////////////////////////// - AVFrame *cvbridge::getAVFrame(AVFrame *in){ - - int size = avpicture_get_size((enum AVPixelFormat)in->format, in->width, in->height); - uint8_t *buff = (uint8_t*)malloc(size); - avpicture_layout((const AVPicture *)in, (enum AVPixelFormat)in->format, - in->width, in->height, (unsigned char *)buff, size); - - AVFrame *output = getAVFrame(buff, in->width, in->height); - free(buff); - return output; - } - - bool cvbridge::getAVFrame(AVFrame *in, AVFrame * &output){ - - int size = avpicture_get_size((enum AVPixelFormat)in->format, in->width, in->height); - uint8_t *buff = (uint8_t*)malloc(size); - avpicture_layout((const AVPicture *)in, (enum AVPixelFormat)in->format, - in->width, in->height, (unsigned char *)buff, size); - - bool flag = getAVFrame(buff, in->width, in->height, output); - free(buff); - return flag; + uint8_t *buff = (uint8_t*)malloc(*length); + int ret = avpicture_layout((const AVPicture *)in, (enum AVPixelFormat)in->format, + in->width, in->height, (unsigned char *)buff, *length); + if (ret < 0){ + free(buff); + return NULL; + } + return buff; } } diff --git a/csrc/ffmpeg/bridge/cvbridge.hpp b/csrc/ffmpeg/bridge/cvbridge.hpp index 565d509..60dfd60 100644 --- a/csrc/ffmpeg/bridge/cvbridge.hpp +++ b/csrc/ffmpeg/bridge/cvbridge.hpp @@ -22,18 +22,15 @@ ~cvbridge(); public: - bool copyPicture(uint8_t *out, AVFrame *in); + uint8_t* convert2Data(AVFrame *in); + AVFrame* convert2Frame(AVFrame *in); - bool getAVFrame(uint8_t *in, const int w, const int h, AVFrame * &output); - AVFrame *getAVFrame(uint8_t *in, const int w, const int h); - - AVFrame *getAVFrame(AVFrame *in); - bool getAVFrame(AVFrame *in, AVFrame * &output); + static AVFrame *fillFrame(uint8_t *in, const int w, const int h, const int f); + static uint8_t* extractFrame(AVFrame *in, int *length); private: ffwrapper::swscale_wrapper *scale_; ffwrapper::PicData *pic_; - uint8_t *buff_fill_; }; diff --git a/csrc/worker/decoder.cpp b/csrc/worker/decoder.cpp index 67af0a1..f5e95b5 100644 --- a/csrc/worker/decoder.cpp +++ b/csrc/worker/decoder.cpp @@ -25,7 +25,7 @@ std::lock_guard<std::mutex> l(mutex_frm_); for(auto i : list_frm_){ - av_frame_free(&i.frm); + free(i.data); } list_frm_.clear(); } @@ -47,24 +47,33 @@ } int decoder::saveFrame(AVFrame *frame, int64_t &id){ + FRM frm; + frm.width = frame->width; + frm.height = frame->height; + frm.format = frame->format; + frm.id = id; + frm.data = cvbridge::extractFrame(frame, &frm.length); + + std::lock_guard<std::mutex> l(mutex_frm_); while(list_frm_.size() > 50){ for(int i = 0; i < 12; i++){ auto t = list_frm_.front(); - av_frame_free(&t.frm); + free(t.data); list_frm_.pop_front(); } } - list_frm_.push_back({frame,id}); + if (!frm.data) return 0; + list_frm_.push_back(frm); return list_frm_.size(); } 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(); @@ -76,50 +85,27 @@ if (ret == 0){ saveFrame(frame, id); } + av_frame_free(&frame); + return ret; } void decoder::GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id){ - AVFrame *frm = NULL; - { - 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(); - 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"); + std::lock_guard<std::mutex> l(mutex_frm_); + if(list_frm_.empty()){ *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; - } - - *data = picData; + auto p = list_frm_.front(); + list_frm_.pop_front(); + *data = p.data; + *id = p.id; + *w = p.width; + *h = p.height; + *format = p.format; + *length = p.length; } } // namespace cffmpeg_wrap diff --git a/csrc/worker/decoder.hpp b/csrc/worker/decoder.hpp index 94bbb03..d157d25 100644 --- a/csrc/worker/decoder.hpp +++ b/csrc/worker/decoder.hpp @@ -21,7 +21,11 @@ namespace cffmpeg_wrap { typedef struct _frm{ - AVFrame *frm; + uint8_t *data; + int length; + int width; + int height; + int format; int64_t id; }FRM; diff --git a/csrc/wrapper.cpp b/csrc/wrapper.cpp index 0e847bf..a48629a 100644 --- a/csrc/wrapper.cpp +++ b/csrc/wrapper.cpp @@ -159,14 +159,17 @@ } } - void Wrapper::run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ + int Wrapper::run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ if (gb_){ AVPacket &pkt = data->getAVPacket(); pkt.pts = pkt.dts = AV_NOPTS_VALUE; } + int flag = 0; if (stream_) stream_->SetPacket(data, id); - if (decoder_ && run_dec_) decoder_->SetFrame(data, id); + if (decoder_ && run_dec_) flag = decoder_->SetFrame(data, id); if (rec_->Loaded()) rec_->SetPacket(data, id); + + return flag } void Wrapper::deinit_worker(){ @@ -209,8 +212,10 @@ id++; continue; } - - run_worker(in.get(), data, id); + // decode error + if (run_worker(in.get(), data, id) == -1){ + break; + } usleep(wTime); id++; @@ -325,8 +330,7 @@ if(in->decode(frm, &data->getAVPacket()) == 0){ *w = frm->width; *h = frm->height; - pic = (unsigned char*)malloc(frm->width * frm->height * 3); - bridge_->copyPicture(pic, frm); + pic = bridge_->convert2Data(frm); break; } } @@ -388,14 +392,14 @@ PicEncoder *e = (PicEncoder*)hdl; auto ctx = e->enc->getCodecContext(); + AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24; if (e->bridge == NULL){ - AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24; e->bridge = new cvbridge( w, h, AV_PIX_FMT_BGR24, e->w, e->h, ctx->pix_fmt, e->flag); } - AVFrame *frame = e->bridge->getAVFrame(in, w, h); + AVFrame *frame = cvbridge::fillFrame(in, w, h, pix_fmt); AVPacket *pkt = av_packet_alloc(); auto flag = e->enc->encode(pkt, frame); @@ -458,26 +462,13 @@ auto b = c->b; - AVFrame *tmp_frm = av_frame_alloc(); - tmp_frm->format = (AVPixelFormat)c->srcF; - tmp_frm->width = c->srcW; - tmp_frm->height = c->srcH; - - //create a AVPicture frame from the opencv Mat input image - int ret = avpicture_fill((AVPicture *)tmp_frm, - (uint8_t *)src, - (AVPixelFormat)tmp_frm->format, - tmp_frm->width, - tmp_frm->height); + AVFrame *tmp_frm = cvbridge::fillFrame(src, c->srcW, c->srcH, c->srcF); + if (!tmp_frm) return NULL; - unsigned char *picData = NULL; - if (ret > 0){ - picData = (unsigned char*)malloc(c->dstW * c->dstH * 3); - b->copyPicture(picData, tmp_frm); - } - + unsigned char *picData = b->convert2Data(tmp_frm); + av_frame_free(&tmp_frm); - + return picData; } diff --git a/csrc/wrapper.hpp b/csrc/wrapper.hpp index bd9d24f..ca528f9 100644 --- a/csrc/wrapper.hpp +++ b/csrc/wrapper.hpp @@ -34,7 +34,7 @@ std::unique_ptr<ffwrapper::FormatIn> init_reader(const char* input); void init_worker(ffwrapper::FormatIn *in); - void run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); + int run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); void deinit_worker(); public: int RunStream(const char* input); -- Gitblit v1.8.0