video analysis2.0拆分,ffmpeg封装go接口库
zhangmeng
2019-09-20 be9c1d1f659b0ff31f656424c478e83a4f7c53b5
update ffmpeg
18个文件已修改
393 ■■■■■ 已修改文件
cffmpeg.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/recorder.cpp 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/recorder.hpp 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/cffmpeg.cpp 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatIn.cpp 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatIn.hpp 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatOut.cpp 144 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatOut.hpp 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/decoder.cpp 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/rec.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/rec.hpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/stream.cpp 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/stream.hpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.cpp 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.hpp 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
goffmpeg.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libcffmpeg.c 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libcffmpeg.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cffmpeg.h
@@ -17,7 +17,7 @@
void c_ffmpeg_run_gb28181(const cffmpeg h);
void c_ffmepg_use_cpu(const cffmpeg h);
/////////passive api
void c_ffmpeg_build_recorder(const cffmpeg h, const char*id, const char *dir, int mind, int maxd);
void c_ffmpeg_build_recorder(const cffmpeg h, const char*id, const char *dir, int mind, int maxd, int audio);
void c_ffmpeg_fire_recorder(const cffmpeg h, const char*sid, const int64_t id);
void c_ffmpeg_get_info_recorder(const cffmpeg h, int *index, char** recid, int *recidLen, char **fpath, int *pathLen);
csrc/buz/recorder.cpp
@@ -34,6 +34,7 @@
        ,func_rec_info_(nullptr)
        ,thrd_(nullptr)
        ,error_occured_(false)
        ,audio_(false)
        {
            // logIt("RECODER ID: %s", id_.c_str());
        }
@@ -59,7 +60,7 @@
            
        }
        int Recorder::init_writer(){
        int Recorder::init_writer(const bool audio){
            if (out_) {
                delete out_;
            }
@@ -69,10 +70,18 @@
                return -1;
            }
            out_ = new FormatOut(in_->getStream(), "mp4");
            out_ = new FormatOut(in_->getFPS(), "mp4");
            AVStream *vs = in_->getStream(0);
            AVStream *as = in_->getStream(1);
            if (!vs) return -1;
            if (audio && !as) logIt("there is no audio");
            std::vector<AVStream*> in;
            in.push_back(vs);
            if (audio && as) in.push_back(as);
            file_path_ = dir_ + "/" + sole::uuid4().base62() + ".mp4";
            auto ret = out_->JustWriter(in_->getStream(), file_path_.c_str());
            auto ret = out_->JustWriter(in, file_path_.c_str());
            if (ret){
                return 0;
            }
@@ -162,10 +171,10 @@
            end_writer();
        }
        int Recorder::Run(const char* output, const int mind, const int maxd){
        int Recorder::Run(const char* output, const int mind, const int maxd, const bool audio){
            dir_ = output;
            int ret = init_writer();
            int ret = init_writer(audio);
            if(ret != 0){
                logIt("recorder init writer error");
                return -1;
@@ -177,6 +186,8 @@
                minduration = fps * mind;
                end_frame = minduration;
            }
            audio_ = audio;
            // logIt("minduration %d maxduration %d curduration %d", minduration, maxduration, end_frame);    
@@ -221,6 +232,10 @@
            if(id_frame_ == -1){
                //wait I 
                if (!audio_ && in_->isAudioPkt(pkt.data->getAVPacket())){
                        return 0;
                }
                if (list_pkt_.empty()) {
                    AVPacket &avpkt = pkt.data->getAVPacket();
                    if (!(avpkt.flags & AV_PKT_FLAG_KEY)){
@@ -249,6 +264,9 @@
            bool i = false;
            for (auto &p : lst){
                if (!i){
                    if (!audio_ && in_->isAudioPkt(p.data->getAVPacket())){
                        continue;
                    }
                    AVPacket &avpkt = p.data->getAVPacket();
                    if (!(avpkt.flags & AV_PKT_FLAG_KEY)){
                        continue;
csrc/buz/recorder.hpp
@@ -35,7 +35,7 @@
                ~Recorder();
            public: 
                int Run(const char* output, const int mind, const int maxd);
                int Run(const char* output, const int mind, const int maxd, const bool audio);
                int PushPacket(const CPacket &pkt);
                int PushPackets(std::list<CPacket> &lst);
                int FireRecorder(const int64_t &id);
@@ -49,7 +49,7 @@
            private:
                void run_thread();
                int init_writer();
                int init_writer(const bool audio);
                int write_correctly(const CPacket &pkt);
                void end_writer();
@@ -80,6 +80,8 @@
                FUNC_REC_INFO           func_rec_info_;
                bool                    error_occured_;
                bool                    audio_;
        };
    }
}
csrc/cffmpeg.cpp
@@ -48,9 +48,11 @@
//////passive api
void c_ffmpeg_build_recorder(const cffmpeg h, const char* id, const char *dir, int mind, int maxd){
void c_ffmpeg_build_recorder(const cffmpeg h, const char* id, const char *dir, int mind, int maxd, int audio){
    Wrapper *s = (Wrapper*)h;
    s->BuildRecorder(id, dir, mind, maxd);
    bool a = audio == 0 ? false : true;
    s->BuildRecorder(id, dir, mind, maxd, a);
}
void c_ffmpeg_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){
csrc/ffmpeg/format/FormatIn.cpp
@@ -29,11 +29,13 @@
    :ctx_(NULL)
    ,dec_ctx_(NULL)
    ,vs_idx_(-1)
    ,as_idx_(-1)
    ,hw_accl_(hw)
    ,io_ctx_(NULL)
    ,read_io_buff_(NULL)
    ,read_io_buff_size_(32768)
    ,handle_gb28181(NULL)
    ,fps_(25.0)
    {}
    FormatIn::~FormatIn()
@@ -100,7 +102,7 @@
        handle_gb28181 = new GB28181API;
        handle_gb28181->addCamera(fn);
        int ret = openWithCustomIO((void *)&handle_gb28181, handle_gb28181->readData, options);
        int ret = openWithCustomIO(handle_gb28181, handle_gb28181->readData, options);
        if(ret < 0){
            logIt("do openWithCustomIO failed:%d",ret);
        }
@@ -136,15 +138,25 @@
            return false;
        }
        logIt("there are %d stream", ctx_->nb_streams);
        for (int i = 0; i < ctx_->nb_streams; ++i)
        {
            switch(ctx_->streams[i]->codecpar->codec_type){
                case AVMEDIA_TYPE_VIDEO:
                    vs_idx_ = i;
                    break;
            auto type = ctx_->streams[i]->codecpar->codec_type;
            if (type == AVMEDIA_TYPE_VIDEO){
                vs_idx_ = i;
                default:
                    break;
                auto in = ctx_->streams[i];
                if(in->r_frame_rate.num >=1 && in->r_frame_rate.den >= 1){
                    fps_ = av_q2d(in->r_frame_rate);
                }else if(in->avg_frame_rate.num >=1 && in->avg_frame_rate.den >= 1){
                    fps_ = av_q2d(in->avg_frame_rate);
                }
                logIt("video stream time base %d : %d", in->time_base.num, in->time_base.den);
            }
            if (type == AVMEDIA_TYPE_AUDIO){
                as_idx_ = i;
                logIt("audio stream time base %d : %d", ctx_->streams[i]->time_base.num, ctx_->streams[i]->time_base.den);
            }
        }
        return true;
@@ -250,43 +262,52 @@
        return true;
    }
    AVStream *FormatIn::getStream(int type){
        return ctx_->streams[vs_idx_];
    AVStream *FormatIn::getStream(int type/*=-1*/){
        if (type == -1){
            return ctx_->streams[vs_idx_];
        }
        if (type == ctx_->streams[vs_idx_]->codecpar->codec_type)
            return ctx_->streams[vs_idx_];
        if (type == ctx_->streams[as_idx_]->codecpar->codec_type)
            return ctx_->streams[as_idx_];
        return NULL;
    }
    AVCodecContext *FormatIn::getCodecContext(int type){
        return dec_ctx_;
    }
    
    bool FormatIn::readPacket(AVPacket &pkt_out, int stream_index){
        bool founded = false;
        while (!founded){
            const int ret = av_read_frame(ctx_, &pkt_out);
            if(ret < 0){
                // logIt("read frame from %s failed:%s",
                //         ctx_->filename,getAVErrorDesc(ret).c_str());
                return false;
            }
            if(pkt_out.stream_index == stream_index){
                founded = true;
            }else{
                av_free_packet(&pkt_out);
                av_init_packet(&pkt_out);
                pkt_out.data = NULL;
                pkt_out.size = 0;
            }
    bool FormatIn::isVideoPkt(AVPacket &pkt){
        if (pkt.stream_index == vs_idx_){
            return true;
        }
        pkt_out.stream_index = 0;
        return false;
    }
    bool FormatIn::isAudioPkt(AVPacket &pkt){
        if (pkt.stream_index == as_idx_){
            return true;
        }
        return false;
    }
    bool FormatIn::readPacket(AVPacket &pkt_out){
        const int ret = av_read_frame(ctx_, &pkt_out);
        if(ret < 0){
            return false;
        }
        return true;
    }
    bool FormatIn::readPacket(std::shared_ptr<CodedData> &data, int stream_index){
    bool FormatIn::readPacket(std::shared_ptr<CodedData> &data){
        AVPacket &pkt(data->getAVPacket());
        return readPacket(pkt, getStream()->index);
        return readPacket(pkt);
    }
    int FormatIn::decode(AVFrame* &frame, AVPacket &pkt){
csrc/ffmpeg/format/FormatIn.hpp
@@ -37,8 +37,8 @@
        bool openCodec(const int type, AVDictionary **options);
        
        bool readPacket(AVPacket &pkt_out, int stream_index = 0);
        bool readPacket(std::shared_ptr<CodedData> &data, int stream_index = 0);
        bool readPacket(AVPacket &pkt_out);
        bool readPacket(std::shared_ptr<CodedData> &data);
        int decode(AVFrame* &frame, AVPacket &pkt);
        int decode(std::shared_ptr<FrameData> &frame_data,
@@ -47,18 +47,22 @@
        int readFrame(AVFrame* &frame);
        int readFrame(std::shared_ptr<FrameData> &frame_data);
        bool isVideoPkt(AVPacket &pkt);
        bool isAudioPkt(AVPacket &pkt);
    private:
        bool allocCodec(AVCodec *dec, AVStream *s, AVDictionary **options);
    public:
        AVStream *getStream(int type = 0);
        AVStream *getStream(int type = -1);
        AVCodecContext *getCodecContext(int type = 0);
        const double getFPS()const{return fps_;}
    private:
         AVFormatContext     *ctx_;
         AVCodecContext         *dec_ctx_;
         int                 vs_idx_;
        int                 as_idx_;
         bool                 hw_accl_;
        double                 fps_;
    private:
        AVIOContext            *io_ctx_;
        uint8_t             *read_io_buff_;
csrc/ffmpeg/format/FormatOut.cpp
@@ -32,6 +32,7 @@
    ,record_(false)
    ,fps_(0.0f)
    ,format_name_("mp4")
    ,streams_(NULL)
    {}
    FormatOut::~FormatOut()
@@ -265,42 +266,16 @@
    }
//////////////////////////////////////////////////////////////////////////
    FormatOut::FormatOut(AVStream *in, const char *format_name)
    FormatOut::FormatOut(const double fps, const char *format_name)
    :FormatOut(){
        format_name_ = format_name;
        if(in->r_frame_rate.num >=1 && in->r_frame_rate.den >= 1){
            fps_ = av_q2d(in->r_frame_rate);
        }else if(in->avg_frame_rate.num >=1 && in->avg_frame_rate.den >= 1){
            fps_ = av_q2d(in->avg_frame_rate);
        }
    }
    bool FormatOut::copyCodecFromIn(AVStream *in){
        v_s_ = avformat_new_stream(ctx_, in->codec->codec);
        if(!v_s_){
            return false;
        }
        int ret = avcodec_copy_context(v_s_->codec, in->codec);
        if (ret < 0){
            logIt("can't copy codec from in error:%s", getAVErrorDesc(ret).c_str());
            return false;
        }
        if (ctx_->oformat->flags & AVFMT_GLOBALHEADER)
        {
            v_s_->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }
        return true;
        fps_ = fps;
    }
    bool FormatOut::openResource(const char *filename, const int flags){
        if((ctx_->flags & AVFMT_NOFILE) != AVFMT_NOFILE){
        if((ctx_->oformat->flags & AVFMT_NOFILE) != AVFMT_NOFILE){
            
            const int err = avio_open2(&ctx_->pb, filename, flags, NULL, NULL);
            if(err < 0)
@@ -320,7 +295,43 @@
        }
        return true;
    }
    bool FormatOut::JustWriter(AVStream *in, const char *filename){
    bool FormatOut::copyCodecFromIn(std::vector<AVStream*> in){
        auto count = in.size();
        for(int i = 0; i < count; i++)
        {    //根据输入流创建输出流
            AVStream *in_stream = in[i];
            AVStream *out_stream = avformat_new_stream(ctx_, in_stream->codec->codec);
            if(!out_stream)
            {
                logIt("Failed allocating output stream.\n");
                return false;
            }
            if (in_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
                v_s_ = out_stream;
            }
            //将输出流的编码信息复制到输入流
            auto ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
            if(ret<0)
            {
                logIt("Failed to copy context from input to output stream codec context\n");
                return false;
            }
            out_stream->codec->codec_tag = 0;
            if(ctx_->oformat->flags & AVFMT_GLOBALHEADER)
                out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }
        streams_ = in;
        return true;
    }
    bool FormatOut::JustWriter(std::vector<AVStream*> in, const char *filename){
        if(ctx_){
            clear();
        }
@@ -386,7 +397,7 @@
        return true;
    }
    void FormatOut::adjustPTS(AVPacket &pkt, const int64_t &frame_cnt){
    void FormatOut::adjustVideoPTS(AVPacket &pkt, const int64_t &frame_cnt){
        int64_t time_stamp = frame_cnt;
        
        pkt.pos = -1;  
@@ -404,7 +415,70 @@
        pkt.dts = pkt.pts;
        pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base); //(double)(calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base));
        
        // logIt("FRAME ID: %lld, PTS : %lld, DTS : %lld", frame_cnt, pkt.pts, pkt.dts);
        // logIt("FRAME ID: %lld, PTS : %lld, DTS : %lld", frame_cnt, pkt.pts, pkt.dts);
    }
    void FormatOut::adjustPTS(AVPacket &pkt, const int64_t &frame_cnt){
        if (streams_.size() == 1){
            return adjustVideoPTS(pkt, frame_cnt);
        }
        if (pkt.stream_index >= streams_.size()){
            logIt("adjustPTS pkt stream index too much");
            return;
        }
        AVStream *in_stream,*out_stream;
        in_stream = streams_[pkt.stream_index];
        out_stream = ctx_->streams[pkt.stream_index];
        // logIt("stream %d time_base %d : %d", pkt.stream_index, in_stream->time_base.num, in_stream->time_base.den);
        // logIt("out time_base %d : %d", out_stream->time_base.num, out_stream->time_base.den);
        std::string type("video");
        if (in_stream->codecpar->codec_type == 1){
            type = "audio";
        }
        // logIt("BEFORE stream %d type: %s, pts: %lld, dts: %lld, duration: %lld",
        // pkt.stream_index, type.c_str(), pkt.pts, pkt.pts, pkt.duration);
        //copy packet
        //转换 PTS/DTS 时序
        pkt.pts = av_rescale_q_rnd(pkt.pts,in_stream->time_base,out_stream->time_base,(enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
        pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
        //printf("pts %d dts %d base %d\n",pkt.pts,pkt.dts, in_stream->time_base);
        pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
        pkt.pos = -1;
        // logIt("AFTER stream %d type: %s, pts: %lld, dts: %lld, duration: %lld",
        // pkt.stream_index, type.c_str(), pkt.pts, pkt.pts, pkt.duration);
        // //此while循环中并非所有packet都是视频帧,当收到视频帧时记录一下,仅此而已
        // if(pkt.stream_index==video_index)
        // {
        //     printf("Receive %8d video frames from input URL\n",frame_index);
        //     frame_index++;
        // }
        // //将包数据写入到文件。
        // ret = av_interleaved_write_frame(ofmt_ctx,&pkt);
        // if(ret < 0)
        // {
        //     /**
        //     当网络有问题时,容易出现到达包的先后不一致,pts时序混乱会导致
        //     av_interleaved_write_frame函数报 -22 错误。暂时先丢弃这些迟来的帧吧
        //     若所大部分包都没有pts时序,那就要看情况自己补上时序(比如较前一帧时序+1)再写入。
        //     */
        //     if(ret==-22){
        //         continue;
        //     }else{
        //         printf("Error muxing packet.error code %d\n" , ret);
        //         break;
        //     }
        // }
    }
    bool FormatOut::writeFrame(AVPacket &pkt, const int64_t &frame_cnt,
@@ -429,11 +503,11 @@
            ret = av_write_frame(ctx_, &pkt);
        }
    
        if(ret < 0){
            return false;
        if(ret < -22 || ret == 0){
            return true;
        }
        return true;
        return false;
    }
    bool FormatOut::writeTrailer(){
csrc/ffmpeg/format/FormatOut.hpp
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <memory>
#include <string>
#include <vector>
struct AVFormatContext;
struct AVStream;
@@ -26,7 +27,7 @@
        FormatOut(VideoProp &prop,
                const char *filename, char *format_name = NULL);
        FormatOut(AVStream *in, const char *format_name);
        FormatOut(const double fps, const char *format_name);
        void clear();
    public:
@@ -39,14 +40,15 @@
        int encode(std::shared_ptr<CodedData> &data,AVFrame *frame);
    public:
        bool copyCodecFromIn(AVStream *in);
        bool copyCodecFromIn(std::vector<AVStream*> in);
        bool openResource(const char *filename, const int flags);
        bool closeResource();
        bool JustWriter(AVStream *in, const char *filename);
        bool JustWriter(std::vector<AVStream*> in, const char *filename);
        bool EncodeWriter(const char *filename);
        bool writeFrame(AVPacket &pkt, const int64_t &frame_cnt, bool interleaved = true);
        void adjustPTS(AVPacket &pkt, const int64_t &frame_cnt);
        void adjustVideoPTS(AVPacket &pkt, const int64_t &frame_cnt);
        bool endWriter();
        bool writeHeader(AVDictionary **options = NULL);
@@ -75,6 +77,8 @@
        double                     fps_;
        std::string             format_name_;
        // rec
        std::vector<AVStream*>    streams_;
    };
}
#endif
csrc/worker/decoder.cpp
@@ -66,6 +66,7 @@
    int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
        if (!data) return -1;
        if (decRef_->isAudioPkt(data->getAVPacket())) return -2;
        
        if (!conv_){
            initDecoder();
csrc/worker/rec.cpp
@@ -40,7 +40,7 @@
        list_recInfo_.emplace_back(info);
    }
    std::unique_ptr<buz::Recorder> rec::startRec(std::string id, std::string dir, const int mind, const int maxd){
    std::unique_ptr<buz::Recorder> rec::startRec(std::string id, std::string dir, const int mind, const int maxd, const bool audio){
        if(!recRef_){
            logIt("Init wrapper first");
            return nullptr;
@@ -54,7 +54,7 @@
        int trycnt = 0;
        while(trycnt < 100){
            auto ret = rec->Run(dir.c_str(), mind, maxd);
            auto ret = rec->Run(dir.c_str(), mind, maxd, audio);
            if(ret == 0) break;
            usleep(200000);
        }
@@ -133,7 +133,7 @@
        return recRef_ != NULL;
    }
    
    void rec::NewRec(const char* id, const char *output, const int mindur, const int maxdur){
    void rec::NewRec(const char* id, const char *output, const int mindur, const int maxdur, const bool audio){
        std::string rid(id);
        std::string dir(output);
        
@@ -145,7 +145,7 @@
            if (map_rec_.find(rid) != map_rec_.end()){
                map_rec_.erase(rid);
            }
            map_rec_[rid] = startRec(rid, dir, mindur, maxdur);
            map_rec_[rid] = startRec(rid, dir, mindur, maxdur, audio);
        }
        
    }
csrc/worker/rec.hpp
@@ -53,11 +53,11 @@
        // 丢弃缓存
        int shrinkCache();
        // 创建录像实例开始录像
        std::unique_ptr<buz::Recorder> startRec(std::string id, std::string dir, const int mind, const int maxd);
        std::unique_ptr<buz::Recorder> startRec(std::string id, std::string dir, const int mind, const int maxd, const bool audio);
        // 清除缓存,断线重连时需要
        void clear();
    public:
        void NewRec(const char* id, const char *output, const int mindur, const int maxdur);
        void NewRec(const char* id, const char *output, const int mindur, const int maxdur, const bool audio);
        // 准备好录像
        void Load(ffwrapper::FormatIn *in);
csrc/worker/stream.cpp
@@ -1,10 +1,13 @@
#include "stream.hpp"
#include "../ffmpeg/data/CodedData.hpp"
#include "../ffmpeg/format/FormatIn.hpp"
namespace cffmpeg_wrap{
    stream::stream(const int maxSize)
    :max_size_(maxSize)
    stream::stream(ffwrapper::FormatIn *in, const int maxSize)
    :streamRef_(in)
    ,max_size_(maxSize)
    ,audio_(false)
    {}
    stream::~stream(){
@@ -14,6 +17,13 @@
    int stream::SetPacket(std::shared_ptr<ffwrapper::CodedData> data){
        if (data){
            auto audio = streamRef_->isAudioPkt(data->getAVPacket());
            // 如果包是音频包,但是不使用音频,直接返回
            if (!audio_ && audio){
                return 0;
            }
            std::lock_guard<std::mutex> locker(mutex_avpkt_);
            list_avpkt_.push_back(data);
            
csrc/worker/stream.hpp
@@ -6,6 +6,7 @@
#include <memory>
namespace ffwrapper{
    class FormatIn;
    class CodedData;
}
@@ -15,13 +16,16 @@
    private:
        std::list<std::shared_ptr<ffwrapper::CodedData> > list_avpkt_;
        std::mutex mutex_avpkt_;
        ffwrapper::FormatIn *streamRef_;
        const int max_size_;
        bool audio_;
    public:
        explicit stream(const int maxSize);
        stream(ffwrapper::FormatIn *in, const int maxSize);
        ~stream();
        int SetPacket(std::shared_ptr<ffwrapper::CodedData> data);
        void GetPacket(unsigned char **pktData, int *size, int *key);
        void AudioSwitch(const bool a){audio_ = a;}
    };
    
}
csrc/wrapper.cpp
@@ -44,6 +44,7 @@
    ,scale_w_(0)
    ,scale_h_(0)
    ,scale_f_(SWS_POINT)
    ,audio_(false)
    ,gb_(0)
    ,cpu_(0)
    ,thread_(nullptr)
@@ -72,20 +73,6 @@
        }
    }
    void Wrapper::ScalePicture(const int w, const int h, const int flags){
        scale_w_ = w;
        scale_f_ = flags;
        scale_h_ = h;
    }
    void Wrapper::GB28181(){
        gb_ = 1;
    }
    void Wrapper::CPUDec(){
        cpu_ = 1;
    }
    std::unique_ptr<ffwrapper::FormatIn> Wrapper::init_reader(const char* input){
        VideoProp prop;
@@ -106,7 +93,7 @@
        }
        if(flag == 0){
            if(!in->findStreamInfo(NULL)){
                logIt("yolo can't find video stream\n");
                logIt("can't find video stream\n");
                return nullptr;
            }
            
@@ -131,15 +118,26 @@
        return 0;
    }
    void Wrapper::AudioSwitch(const bool a){
        audio_ = a;
        if (stream_){
            stream_->AudioSwitch(a);
        }
    }
    void Wrapper::init_worker(ffwrapper::FormatIn *in){
        if (rec_->Loaded() && stream_ && decoder_) return;
        stream_ = new stream(3 * 25);
        stream_ = new stream(in, 3 * 25);
        stream_->AudioSwitch(audio_);
        decoder_ = new decoder(in, scale_w_, scale_h_, scale_f_);
        rec_->Load(in);
        if(fn_rec_lazy_) fn_rec_lazy_(in);
    }
    
    void Wrapper::run_worker(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
    void Wrapper::run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
        if (stream_) stream_->SetPacket(data);
        if (decoder_) decoder_->SetFrame(data, id);
        if (rec_->Loaded()) rec_->SetPacket(data, id);
@@ -172,7 +170,7 @@
                    break;
                }
                
                run_worker(data, id);
                run_worker(in.get(), data, id);
                id++;
            }
@@ -180,14 +178,14 @@
        }
    }
    void Wrapper::BuildRecorder(const char* id, const char *output, const int mindur, const int maxdur){
    void Wrapper::BuildRecorder(const char* id, const char *output, const int mindur, const int maxdur, const bool audio){
        
        if (rec_->Loaded()){
            rec_->NewRec(id, output, mindur, maxdur);
            rec_->NewRec(id, output, mindur, maxdur, audio);
        }else{
            std::string rid(id), dir(output);
            fn_rec_lazy_ = 
            [=](ffwrapper::FormatIn *in){rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur);};
            [=](ffwrapper::FormatIn *in){rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur, audio);};
        }
    }
csrc/wrapper.hpp
@@ -37,19 +37,24 @@
        std::unique_ptr<ffwrapper::FormatIn> init_reader(const char* input);
        void init_worker(ffwrapper::FormatIn *in);
        void run_worker(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id);
        void run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id);
        void deinit_worker();
    public: 
        int RunStream(const char* input);
    private: 
        void run_stream_thread();
    public: //recorder
        void BuildRecorder(const char* id,const char *dir, const int mind, const int maxd);
        void BuildRecorder(const char* id,const char *dir, const int mind, const int maxd, const bool audio);
        int FireRecorder(const char* sid,const int64_t &id);
        void GetInfoRecorder(std::string &recID, int &index, std::string &path);
        void ScalePicture(const int w, const int h, const int flags);
        void GB28181();
        void CPUDec();
        void ScalePicture(const int w, const int h, const int flags){
            scale_w_ = w;
            scale_h_ = h;
            scale_f_ = flags;
        }
        void GB28181(){gb_ = 1;}
        void CPUDec(){cpu_ = 1;}
        void AudioSwitch(const bool a);
    public: //decoder
        void BuildDecoder();
        void GetPicDecoder(unsigned char **data, int *w, int *h, int64_t *id);
@@ -59,7 +64,7 @@
        // stream 参数
        std::string input_url_;
        int scale_w_, scale_h_, scale_f_;
        bool audio_;
        int gb_, cpu_;
        // decoder 参数
        std::unique_ptr<std::thread> thread_;
goffmpeg.go
@@ -134,13 +134,13 @@
}
// BuildRecorder build recorder
func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd int) {
func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd, audio int) {
    out := C.CString(output)
    defer C.free(unsafe.Pointer(out))
    csid := C.CString(sid)
    defer C.free(unsafe.Pointer(csid))
    C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd))
    C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd), C.int(audio))
}
// GetInfoRecorder info
libcffmpeg.c
@@ -87,8 +87,8 @@
    fn_cpu(h);
}
void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd){
    fn_recorder(h, id, dir, mind, maxd);
void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd, int audio){
    fn_recorder(h, id, dir, mind, maxd, audio);
}
void wrap_fn_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){
libcffmpeg.h
@@ -16,7 +16,7 @@
typedef void (*lib_cffmpeg_scale)(const cffmpeg, const int, const int, const int);
typedef void (*lib_cffmpeg_gb28181)(const cffmpeg);
typedef void (*lib_cffmpeg_cpu)(const cffmpeg);
typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, int, int);
typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, int, int, int);
typedef void (*lib_cffmpeg_fire_recorder)(const cffmpeg, const char*, const int64_t);
typedef void (*lib_cffmpeg_info_recorder)(const cffmpeg, int*, char**, int*, char**, int*);
typedef void (*lib_cffmpeg_decoder)(const cffmpeg);
@@ -48,7 +48,7 @@
void wrap_fn_scale(const cffmpeg h, const int wid, const int hei, const int flags);
void wrap_fn_run_gb28181(const cffmpeg h);
void wrap_fn_use_cpu(const cffmpeg h);
void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd);
void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd, int audio);
void wrap_fn_fire_recorder(const cffmpeg h, const char *sid, const int64_t id);
void wrap_fn_info_recorder(const cffmpeg, int* index, char** recid, int* recidLen, char** fpath, int* pathLen);
void wrap_fn_decoder(const cffmpeg h);