video analysis2.0拆分,ffmpeg封装go接口库
zhangmeng
2019-09-28 5dc20e14010d1cf87db73ddd0de2de452049e542
add rec h265
6个文件已修改
234 ■■■■ 已修改文件
csrc/buz/recorder.cpp 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/recorder.hpp 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatIn.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatOut.cpp 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/rec.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/recorder.cpp
@@ -36,8 +36,12 @@
        ,error_occured_(false)
        ,audio_(false)
        ,cur_frame_a(0)
        ,fp_(NULL)
        {
            // logIt("RECODER ID: %s", id_.c_str());
            if (in){
                maxduration = 30 * in->getFPS();
                minduration = 10 * in->getFPS();
            }
        }
        Recorder::~Recorder(){
@@ -58,17 +62,17 @@
            {
                logIt("RECODER DESTRUCTOR EXCEPTION: ", e.what());
            }
            if (fp_) {
                fclose(fp_);
                fp_ = NULL;
            }
            
        }
        int Recorder::init_writer(const bool audio){
        int Recorder::init_write_h264(const bool audio){
            if (out_) {
                delete out_;
            }
            if(!in_){
                logIt("init_writer FormatIn not init");
                return -1;
            }
            out_ = new FormatOut(in_->getFPS(), "mp4");
@@ -95,7 +99,40 @@
            return -1;
        }
        int Recorder::write_correctly(const CPacket &pkt){
        int Recorder::init_write_hevc(const bool audio){
            if (fp_){
                fclose(fp_);
            }
            int pid = getpid();
            file_path_ = dir_ + "/" + sole::uuid4().base62() + "-" + std::to_string(pid) + ".hevc";
            fp_ = fopen(file_path_.c_str(), "wb");
            if (!fp_){
                logIt("write hevc open file error: %s", file_path_.c_str());
                return -1;
            }
            logIt("start record file: %s", file_path_.c_str());
            return 0;
        }
        int Recorder::init_writer(const bool audio){
            if(!in_){
                logIt("init_writer FormatIn not init");
                return -1;
            }
            if (in_->IsHEVC()){
                return init_write_hevc(audio);
            }else{
                return init_write_h264(audio);
            }
            return -2;
        }
////////////////////////
        int Recorder::write_h264(const CPacket &pkt){
            //reader failed, break stream
            if(pkt.id == -1 && !pkt.data){
                return -1;
@@ -127,15 +164,146 @@
            
            // logIt("WRITE FRAME ID: %d, RECORD ID: %d", pkt.id, id_frame_);
            return 0;
        }
        void Recorder::end_writer(){
        int Recorder::write_hevc(const CPacket &pkt){
            if (!fp_){
                logIt("write hevc packet error, file not open");
                return -1;
            }
            if (cur_frame == end_frame){
                return 1;
            }
            AVPacket &op = pkt.data->getAVPacket();
            int64_t cur = cur_frame;
            if (in_->isVideoPkt(&op)){
                if(pkt.id == id_frame_){
                    id_frame_in_file_ = cur_frame;
                }
                cur_frame++;
            }
            fwrite(op.data, op.size, 1, fp_);
            return 0;
        }
        int Recorder::write_correctly(const CPacket &pkt){
            if (in_->IsHEVC()){
                return write_hevc(pkt);
            }
            return write_h264(pkt);
        }
        int Recorder::end_write_h264(){
            if (!out_) return -1;
            out_->endWriter();
            if (out_){
                delete out_;
                out_ = NULL;
            }
            return 0;
        }
        int Recorder::end_write_hevc(){
            if (fp_){
                fclose(fp_);
                fp_ = NULL;
            }
            std::string hevc_file(file_path_);
            auto pos = file_path_.rfind(".hevc");
            if (pos != std::string::npos){
                file_path_ = file_path_.substr(0, pos) + ".mp4";
                logIt("mux hevc real file : %s", file_path_.c_str());
            }
            FILE *fp = fopen(hevc_file.c_str(), "rb");
            if (!fp) return 0;
            int ret = mux_hevc(fp, file_path_.c_str());
            fclose(fp);
            if (remove(hevc_file.c_str()) != 0){
                logIt("mux hevc remove file %s failed", hevc_file.c_str());
            }
            return ret;
        }
        static int read_buffer(void *opaque, uint8_t *buf, int buf_size){
            FILE *fp_open = (FILE*)opaque;
            if(!feof(fp_open)){
                int true_size=fread(buf,1,buf_size,fp_open);
                return true_size;
            }else{
                return -1;
            }
        }
        int Recorder::mux_hevc(FILE *fp, const char *outfile){
            std::unique_ptr<FormatIn> in(new FormatIn(false));
            if (!fp) {
                logIt("mux hevc file handle is null");
                return -1;
            }
            if (in->openWithCustomIO(fp, read_buffer) < 0) {
                logIt("mux hevc open custom io error");
                return -2;
            }
            if (in->open(NULL, NULL) < 0){
                logIt("mux hevc open stream error");
                return -3;
            }
            if (!in->findStreamInfo(NULL)) {
                logIt("mux hevc can't find streams");
                return -4;
            }
            std::unique_ptr<FormatOut> out(new FormatOut(in_->getFPS(), "mp4"));
            auto v = in->getStream(AVMEDIA_TYPE_VIDEO);
            if (!v){
                logIt("mux hevc file can't find video stream");
                return -5;
            }
            if (out->JustWriter(v, NULL, outfile)){
                logIt("mux hevc  start record file: %s", outfile);
            }
            int64_t id = 0;
            while(true){
                AVPacket pkt;
                if (in->readPacket(&pkt) != 0){
                    logIt("mux hevc read packet error, id: %lld", id);
                    break;
                }
                out->writeFrame(&pkt, id);
                logIt("read frame: %d", id);
                av_packet_unref(&pkt);
                id++;
            }
            out->endWriter();
            return 0;
        }
        void Recorder::end_writer(){
            int ret = -1;
            if (in_->IsHEVC()){
                ret = end_write_hevc();
            }else{
                ret = end_write_h264();
            }
            if (ret < 0){
                logIt("end write file : %s, h265: %d, failed", file_path_.c_str(), in_->IsHEVC());
            }
            logIt("finished record : %s frames: %d", file_path_.c_str(), cur_frame);
            {
                std::lock_guard<std::mutex> l(mutex_pkt_);
                list_pkt_.clear();
@@ -143,11 +311,9 @@
            // logIt("INDEX %d, REAL-FRAME-ID %d, FILE %s, CURFrame %d, ENDFrame %d\n",
            //      id_frame_in_file_, id_frame_, file_path_.c_str(), cur_frame, end_frame);
            //callback to frame index and path
            if(func_rec_info_){
                func_rec_info_(id_,id_frame_in_file_, file_path_);
            }
        }
        void Recorder::run_thread(){
@@ -187,23 +353,26 @@
        int Recorder::Run(const char* output, const int mind, const int maxd, const bool audio){
            bool a = audio;
            if (in_->IsHEVC()) a = false;
            dir_ = output;
            int ret = init_writer(audio);
            int ret = init_writer(a);
            if(ret != 0){
                logIt("recorder init writer error");
                return -1;
            }
            double fps = out_->getFPS();
            double fps = in_->getFPS();
            if(fps > 1.0){
                maxduration = fps * maxd;
                minduration = fps * mind;
                end_frame = minduration;
            }
            audio_ = audio;
            audio_ = a;
            // logIt("minduration %d maxduration %d curduration %d", minduration, maxduration, end_frame);
            logIt("minduration %d maxduration %d curduration %d", minduration, maxduration, end_frame);
            thrd_.reset(new std::thread([&]{
                run_thread();
csrc/buz/recorder.hpp
@@ -50,6 +50,15 @@
                void end_writer();
                void maybe_dump_gop();
                int init_write_h264(const bool audio);
                int write_h264(const CPacket &pkt);
                int end_write_h264();
                int init_write_hevc(const bool audio);
                int write_hevc(const CPacket &pkt);
                int end_write_hevc();
                int mux_hevc(FILE *fp, const char *outfile);
            private: 
                ffwrapper::FormatIn     *in_;
                ffwrapper::FormatOut    *out_;
@@ -59,7 +68,7 @@
                int     end_frame;
                int     cur_frame;
                int     cur_frame_a;
                std::list<CPacket>     list_pkt_;
                std::atomic_bool        stop_recorder_;
@@ -79,6 +88,8 @@
                bool                    error_occured_;
                bool                    audio_;
                FILE                    *fp_;
        };
    }
}
csrc/ffmpeg/format/FormatIn.cpp
@@ -155,11 +155,11 @@
                vs_idx_ = i;
                auto in = ctx_->streams[i];
                if(in->avg_frame_rate.num >=1 && in->avg_frame_rate.den >= 1){
                    fps_ = av_q2d(in->avg_frame_rate);
                }else if(in->r_frame_rate.num >=1 && in->r_frame_rate.den >= 1){
                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("in stream video fps %f, time_base: %d : %d", fps_, in->time_base.num, in->time_base.den);
            }
            if (type == AVMEDIA_TYPE_AUDIO){
csrc/ffmpeg/format/FormatOut.cpp
@@ -434,6 +434,12 @@
            pkt->pts = pkt->dts = pkt->duration * time_stamp; 
        }
        // logIt("BEFORE in stream timebase %d:%d, out timebase %d:%d,
        //         pts: %lld, dts: %lld, duration: %lld",
        //     in_stream->time_base.num, in_stream->time_base.den,
        //     out_stream->time_base.num, out_stream->time_base.den,
        //     pkt->pts, pkt->dts, pkt->duration);
    }
    bool FormatOut::writeFrame(AVPacket *pkt, const int64_t &frame_cnt,
csrc/worker/rec.cpp
@@ -141,8 +141,8 @@
        std::string rid(id);
        std::string dir(output);
        
        minduration_ = mindur * 25;
        maxduration_ = maxdur * 25;
        minduration_ = mindur * recRef_->getFPS();
        maxduration_ = maxdur * recRef_->getFPS();
        {
            std::lock_guard<std::mutex> l(mtx_rec_);
csrc/wrapper.cpp
@@ -151,7 +151,7 @@
    void Wrapper::init_worker(ffwrapper::FormatIn *in){
        if (rec_->Loaded() && stream_ && decoder_) return;
        stream_ = new stream(in, 3 * 25);
        stream_ = new stream(in, 3 * in->getFPS());
        // stream_->AudioSwitch(audio_);
        decoder_ = new decoder(in, scale_w_, scale_h_, scale_f_);
@@ -192,7 +192,7 @@
            
            int wTime = 1000000.0 / in->getFPS() ;
            wTime >>= 1;
            logIt("INPUT FPS: %d", wTime);
            logIt("WAIT TIME PER FRAME: %d", wTime);
            init_worker(in.get());