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