From 5dc20e14010d1cf87db73ddd0de2de452049e542 Mon Sep 17 00:00:00 2001
From: zhangmeng <775834166@qq.com>
Date: 星期六, 28 九月 2019 16:33:18 +0800
Subject: [PATCH] add rec h265
---
csrc/ffmpeg/format/FormatIn.cpp | 8 +-
csrc/wrapper.cpp | 4
csrc/worker/rec.cpp | 4
csrc/ffmpeg/format/FormatOut.cpp | 6 +
csrc/buz/recorder.hpp | 13 +++
csrc/buz/recorder.cpp | 199 ++++++++++++++++++++++++++++++++++++++++++++++---
6 files changed, 210 insertions(+), 24 deletions(-)
diff --git a/csrc/buz/recorder.cpp b/csrc/buz/recorder.cpp
index c3b4d84..970a68e 100644
--- a/csrc/buz/recorder.cpp
+++ b/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();
diff --git a/csrc/buz/recorder.hpp b/csrc/buz/recorder.hpp
index d05ebb8..9c88bbb 100644
--- a/csrc/buz/recorder.hpp
+++ b/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_;
};
}
}
diff --git a/csrc/ffmpeg/format/FormatIn.cpp b/csrc/ffmpeg/format/FormatIn.cpp
index 4399822..25d9e3a 100644
--- a/csrc/ffmpeg/format/FormatIn.cpp
+++ b/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){
diff --git a/csrc/ffmpeg/format/FormatOut.cpp b/csrc/ffmpeg/format/FormatOut.cpp
index 2994153..6bc43df 100644
--- a/csrc/ffmpeg/format/FormatOut.cpp
+++ b/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,
diff --git a/csrc/worker/rec.cpp b/csrc/worker/rec.cpp
index d7ce012..01896b0 100644
--- a/csrc/worker/rec.cpp
+++ b/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_);
diff --git a/csrc/wrapper.cpp b/csrc/wrapper.cpp
index 26aee19..c03b54f 100644
--- a/csrc/wrapper.cpp
+++ b/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());
--
Gitblit v1.8.0