video analysis2.0拆分,ffmpeg封装go接口库
zhangmeng
2019-10-10 b35d0da3fb4ceec328286851d0e2b316872ab04a
send frame not bgr
6个文件已修改
257 ■■■■■ 已修改文件
csrc/ffmpeg/bridge/cvbridge.cpp 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/bridge/cvbridge.hpp 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/decoder.cpp 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/decoder.hpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.cpp 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.hpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
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;
    }
}
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_;
    };
    
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
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;
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;
    }
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);