From be9c1d1f659b0ff31f656424c478e83a4f7c53b5 Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期五, 20 九月 2019 11:44:19 +0800 Subject: [PATCH] update ffmpeg --- csrc/buz/recorder.cpp | 254 +++++++++++++++++++++++++++++++------------------- 1 files changed, 157 insertions(+), 97 deletions(-) diff --git a/csrc/buz/recorder.cpp b/csrc/buz/recorder.cpp index 4bfd370..86afe89 100644 --- a/csrc/buz/recorder.cpp +++ b/csrc/buz/recorder.cpp @@ -1,7 +1,9 @@ #include "recorder.hpp" +#include "sole.hpp" #include <thread> #include <unistd.h> +#include <chrono> extern "C"{ #include <libavcodec/avcodec.h> @@ -17,32 +19,48 @@ namespace cffmpeg_wrap{ namespace buz{ - Recorder::Recorder(FormatIn *in) + Recorder::Recorder(FormatIn *in, const std::string &id) :in_(in) ,out_(NULL) ,maxduration(30 * 25) ,minduration(10 * 25) ,end_frame(minduration) - ,cur_frame(-1) - ,thread_(nullptr) + ,cur_frame(0) ,stop_recorder_(false) - ,id_frame_(0) - ,file_frame_index_(-1) + ,id_(id) + ,id_frame_(-1) + ,id_frame_in_file_(-1) ,file_path_("") ,func_rec_info_(nullptr) - {} - - Recorder::~Recorder(){ - if(thread_){ - stop_recorder_.store(true); - cv_.notify_one(); - thread_->join(); - } - if(out_) - delete out_; + ,thrd_(nullptr) + ,error_occured_(false) + ,audio_(false) + { + // logIt("RECODER ID: %s", id_.c_str()); } - int Recorder::init_writer(){ + Recorder::~Recorder(){ + + try + { + if (thrd_){ + if (!stop_recorder_.load()){ + stop_recorder_.store(true); + cv_.notify_one(); + } + + thrd_->join(); + // logIt("REC THREAD JOINED, QUIT!!!, %s", id_.c_str()); + } + } + catch(const std::exception& e) + { + logIt("RECODER DESTRUCTOR EXCEPTION: ", e.what()); + } + + } + + int Recorder::init_writer(const bool audio){ if (out_) { delete out_; } @@ -52,111 +70,111 @@ 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); - return 0; - } - - void Recorder::start_writer(){ - if (cur_frame == 0) { - file_path_ = dir_ + "/" + std::to_string(random()) + ".mp4"; - out_->JustWriter(in_->getStream(), file_path_.c_str()); - logIt("start record %s", file_path_.c_str()); + file_path_ = dir_ + "/" + sole::uuid4().base62() + ".mp4"; + auto ret = out_->JustWriter(in, file_path_.c_str()); + if (ret){ + return 0; } + + return -1; } - int Recorder::write_correctly(const avpacket &pkt){ + int Recorder::write_correctly(const CPacket &pkt){ //reader failed, break stream if(pkt.id == -1 && !pkt.data){ - end_writer(); - return 1; - } - // writer error, reinit writer - int64_t cur = cur_frame++; - if(!out_->writeFrame(pkt.data->getAVPacket(), cur)){ - end_writer(); return -1; } - if(pkt.id == id_frame_){ - file_frame_index_ = cur_frame; + + if (cur_frame == end_frame){ + return 1; } + + int64_t cur = cur_frame++; + AVPacket &op = pkt.data->getAVPacket(); + AVPacket np(op); + av_copy_packet(&np, &op); + auto ret = out_->writeFrame(np, cur); + av_packet_unref(&np); + if (!ret) return -1; + + if(pkt.id == id_frame_){ + id_frame_in_file_ = cur_frame-1; + } + + // logIt("WRITE FRAME ID: %d, RECORD ID: %d", pkt.id, id_frame_); return 0; } void Recorder::end_writer(){ - if(cur_frame == -1) return; + out_->endWriter(); - //reinit cur_frame clear list pkt + if (out_){ + delete out_; + out_ = NULL; + } { - std::lock_guard<std::mutex> locker(mutex_pkt_); - cur_frame = -1; - end_frame = minduration; + std::lock_guard<std::mutex> l(mutex_pkt_); list_pkt_.clear(); } + // 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_(file_frame_index_, file_path_); - // logIt("recoder index %d, file name %s\n", file_frame_index_, file_path_.c_str()); - }else{ - // logIt("recorder has no func_rec_info"); + func_rec_info_(id_,id_frame_in_file_, file_path_); } + } void Recorder::run_thread(){ - bool reinit_writer = false; - while(!stop_recorder_.load()){ - if (reinit_writer) { - while(!stop_recorder_.load()){ - if(init_writer() == 0) - break; - usleep(300000); - } - if(stop_recorder_.load()) break; - } - std::list<avpacket> pkts; + while(!stop_recorder_.load()){ + + std::list<CPacket> pkts; { std::unique_lock<std::mutex> locker(mutex_pkt_); - cv_.wait(locker,[&]{ + auto status = cv_.wait_for(locker, std::chrono::seconds(3), [&]{ return !list_pkt_.empty() || stop_recorder_.load(); }); - if(stop_recorder_.load()){ - end_writer(); + + if (!status || stop_recorder_.load()){ + error_occured_ = !status; break; - } - if(cur_frame == -1){ - continue; } list_pkt_.swap(pkts); } - - if (cur_frame == 0) { - start_writer(); - } - + + int ret = 0; for(auto &i : pkts){ - if (cur_frame < end_frame){ - const int ret = write_correctly(i); - if(ret != 0){ - if(ret == -1) reinit_writer = true; - break; - } - }else{ - end_writer(); + ret = write_correctly(i); + if (ret != 0){ break; } } + + if (ret != 0){ + break; + } } + + stop_recorder_.store(true); + end_writer(); } - int Recorder::Run(const char* output, const int mind, const int maxd){ - if(thread_){ - logIt("recorder already run"); - return 0; - } + 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; @@ -169,42 +187,55 @@ end_frame = minduration; } - logIt("min %d max %d endcount %d", minduration, maxduration, end_frame); + audio_ = audio; - thread_.reset(new std::thread([&]{ + // logIt("minduration %d maxduration %d curduration %d", minduration, maxduration, end_frame); + + thrd_.reset(new std::thread([&]{ run_thread(); })); + //.detach(); return 0; } int Recorder::FireRecorder(const int64_t &id){ - if(cur_frame == -1){ + if (stop_recorder_.load()) return -1; + + if(id_frame_ == -1){ id_frame_ = id; - { - std::lock_guard<std::mutex> locker(mutex_pkt_); - cur_frame = 0; + + std::lock_guard<std::mutex> locker(mutex_pkt_); + if (list_pkt_.size() > end_frame){ + end_frame = list_pkt_.size() + minduration/2; + if (end_frame > maxduration) + end_frame = maxduration; } - }else if(end_frame - cur_frame > minduration/2 && end_frame < maxduration){ + + // logIt("FIRST FIRE RECORD ID: %lld, cur_frame: %d, end_frame: %d", id, cur_frame, end_frame); + + }else if(cur_frame > minduration/2 && end_frame < maxduration){ end_frame = end_frame + minduration / 2; if(end_frame > maxduration){ end_frame = maxduration; } + // logIt("PROLONG REC, cur_frame: %d, end_frame: %d", cur_frame, end_frame); } + // logIt("FIRE REC FRAME ID: %lld", id); return 0; } - int Recorder::CachePacket(const avpacket &pkt){ + int Recorder::PushPacket(const CPacket &pkt){ + if (stop_recorder_.load()) return 0; std::lock_guard<std::mutex> locker(mutex_pkt_); - if(cur_frame == -1){ - //error occur, stream break - if(pkt.id == -1 && pkt.data == nullptr){ - list_pkt_.clear(); - return -1; - } + 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)){ @@ -215,17 +246,46 @@ maybe_dump_gop(); list_pkt_.push_back(pkt); + // cv_.notify_one(); + }else{ list_pkt_.push_back(pkt); cv_.notify_one(); } - return 0; + return list_pkt_.size(); + } + + int Recorder::PushPackets(std::list<CPacket> &lst){ + + if (stop_recorder_.load()) return 0; + + std::lock_guard<std::mutex> locker(mutex_pkt_); + 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; + } + i = true; + } + + list_pkt_.push_back(p); + } + maybe_dump_gop(); + cv_.notify_one(); + + // logIt("CACHE PACKET : %d", list_pkt_.size()); + return list_pkt_.size(); } void Recorder::maybe_dump_gop(){ //瓒呰繃min/2,涓㈠純gop - while (list_pkt_.size() > maxduration) { + while (list_pkt_.size() > minduration) { list_pkt_.pop_front(); while(!list_pkt_.empty()){ auto &cache = list_pkt_.front(); @@ -239,4 +299,4 @@ } } } -} \ No newline at end of file +} -- Gitblit v1.8.0