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