| | |
| | | |
| | | typedef void* cffmpeg; |
| | | |
| | | cffmpeg c_ffmpeg_create(); |
| | | cffmpeg c_ffmpeg_create(const int, const char *logfile); |
| | | void c_ffmpeg_destroy(const cffmpeg h); |
| | | void c_ffmpeg_run(const cffmpeg h, const char *input); |
| | | |
| | |
| | | |
| | | using namespace cffmpeg_wrap; |
| | | |
| | | cffmpeg c_ffmpeg_create(){ |
| | | return new Wrapper; |
| | | cffmpeg c_ffmpeg_create(const int log, const char *logfile){ |
| | | bool logit = false; |
| | | if (log) logit = true; |
| | | return new Wrapper(logit, logfile); |
| | | } |
| | | |
| | | void c_ffmpeg_destroy(const cffmpeg h){ |
| | |
| | | logIt("adjustPTS pkt stream index too much"); |
| | | return; |
| | | } |
| | | |
| | | if (pkt->pts == AV_NOPTS_VALUE && pkt->pts == AV_NOPTS_VALUE){ |
| | | int64_t time_stamp = frame_cnt; |
| | | |
| | | pkt->pos = -1; |
| | | pkt->stream_index = 0; |
| | | //Write PTS |
| | | AVRational time_base = getStream()->time_base; |
| | | |
| | | AVRational time_base_q = { 1, AV_TIME_BASE }; |
| | | //Duration between 2 frames (us) |
| | | // int64_t calc_duration = (double)(AV_TIME_BASE)*(1 / fps_); //内部时间戳 |
| | | int64_t calc_duration = (int64_t)(AV_TIME_BASE / fps_); //内部时间戳 |
| | | //Parameters |
| | | pkt->pts = av_rescale_q(time_stamp*calc_duration, time_base_q, time_base); |
| | | pkt->dts = pkt->pts; |
| | | pkt->duration = av_rescale_q(calc_duration, time_base_q, time_base); |
| | | return; |
| | | } |
| | | |
| | | AVStream *in_stream,*out_stream; |
| | | |
| | | in_stream = in_ctx_->streams[pkt->stream_index]; |
| | | out_stream = ctx_->streams[pkt->stream_index]; |
| | | |
| | | // logIt("BEFORE stream %d, pts: %lld, dts: %lld, duration: %lld", |
| | | // pkt->stream_index, pkt->pts, pkt->dts, pkt->duration); |
| | | // 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); |
| | | |
| | | //转换 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)); |
| | |
| | | file_name + "-" + |
| | | makeTimeStamp() + |
| | | ".tlog"); |
| | | rotateLog(logfile.c_str(), kRotateLogFileSize, kRotateLogFileCount, show_stdout); |
| | | |
| | | CreateLogger(logfile.c_str(), show_stdout); |
| | | } |
| | | |
| | | void CreateLogger(const char *name, const bool show_stdout){ |
| | | |
| | | rotateLog(name, kRotateLogFileSize, kRotateLogFileCount, show_stdout); |
| | | |
| | | log_run = true; |
| | | } |
| | | |
| | | void DestroyLogger(){ |
| | | spdlog::drop_all(); |
| | | if (log_run) |
| | | spdlog::drop_all(); |
| | | } |
| | | |
| | | void logIt(const char *fmt, ...){ |
| | |
| | | va_end(args); //结束可变参数的获取 |
| | | |
| | | if(log_run){ |
| | | spdlog::get(log_name)->error(temp); |
| | | std::string lc(temp); |
| | | lc = "LIB-libcffmpeg.so-> " + lc; |
| | | spdlog::get(log_name)->error(lc); |
| | | }else{ |
| | | printf("%s\n", temp); |
| | | } |
| | |
| | | |
| | | namespace logif{ |
| | | void CreateLogger(const char *dir, const char *name, const bool show_stdout); |
| | | void CreateLogger(const char *name, const bool show_stdout); |
| | | void DestroyLogger(); |
| | | |
| | | void logIt(const char *fmt, ...); |
| | |
| | | namespace cffmpeg_wrap{ |
| | | using namespace buz; |
| | | |
| | | Wrapper::Wrapper() |
| | | Wrapper::Wrapper(const bool logit, const char *logfile) |
| | | :input_url_("") |
| | | ,scale_w_(0) |
| | | ,scale_h_(0) |
| | |
| | | ,rec_(new rec) |
| | | { |
| | | makeTheWorld(); |
| | | if (logit){ |
| | | logif::CreateLogger(logfile, true); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | logIt("WRAPPER EXCEPTION: ", e.what()); |
| | | } |
| | | logif::DestroyLogger(); |
| | | } |
| | | |
| | | std::unique_ptr<ffwrapper::FormatIn> Wrapper::init_reader(const char* input){ |
| | |
| | | |
| | | void Wrapper::AudioSwitch(const bool a){ |
| | | audio_ = a; |
| | | if (stream_){ |
| | | stream_->AudioSwitch(a); |
| | | } |
| | | // if (stream_){ |
| | | // stream_->AudioSwitch(a); |
| | | // } |
| | | } |
| | | |
| | | void Wrapper::init_worker(ffwrapper::FormatIn *in){ |
| | | if (rec_->Loaded() && stream_ && decoder_) return; |
| | | |
| | | stream_ = new stream(in, 3 * 25); |
| | | stream_->AudioSwitch(audio_); |
| | | // stream_->AudioSwitch(audio_); |
| | | |
| | | decoder_ = new decoder(in, scale_w_, scale_h_, scale_f_); |
| | | |
| | |
| | | } |
| | | |
| | | void 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; |
| | | } |
| | | if (stream_) stream_->SetPacket(data, id); |
| | | if (decoder_ && run_dec_) decoder_->SetFrame(data, id); |
| | | if (rec_->Loaded()) rec_->SetPacket(data, id); |
| | |
| | | |
| | | void Wrapper::run_stream_thread(){ |
| | | |
| | | int tryTime = 0; |
| | | while(!stop_stream_.load()){ |
| | | auto in = init_reader(input_url_.c_str()); |
| | | |
| | | if (!in) { |
| | | logIt("ERROR: init_reader! url: %s\n", input_url_.c_str()); |
| | | usleep(200000); |
| | | tryTime++; |
| | | if (tryTime == 50){ |
| | | break; |
| | | } |
| | | continue; |
| | | } |
| | | |
| | |
| | | |
| | | init_worker(in.get()); |
| | | |
| | | int64_t id = -1; |
| | | int64_t id = gb_ ? 0 : -1; |
| | | |
| | | while(!stop_stream_.load()){ |
| | | auto data(std::make_shared<CodedData>()); |
| | | if (in->readPacket(&data->getAVPacket()) != 0){ |
| | | logIt("read packet error, id: %lld", id); |
| | | break; |
| | | } |
| | | if (id < 0){ |
| | | |
| | | if (!gb_ && id < 0){ |
| | | id++; |
| | | continue; |
| | | } |
| | | |
| | | |
| | | run_worker(in.get(), data, id); |
| | | usleep(wTime); |
| | | |
| | |
| | | } |
| | | |
| | | void Wrapper::BuildRecorder(const char* id, const char *output, const int mindur, const int maxdur, const bool audio){ |
| | | |
| | | bool a = audio; |
| | | if (gb_) a = false; |
| | | |
| | | if (rec_->Loaded()){ |
| | | rec_->NewRec(id, output, mindur, maxdur, audio); |
| | | rec_->NewRec(id, output, mindur, maxdur, a); |
| | | }else{ |
| | | std::string rid(id), dir(output); |
| | | fn_rec_lazy_ = |
| | | [=]{rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur, audio);}; |
| | | [=]{rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur, a);}; |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | class Wrapper{ |
| | | public: |
| | | Wrapper(); |
| | | explicit Wrapper(const bool logit, const char *logfile); |
| | | ~Wrapper (); |
| | | private: |
| | | std::unique_ptr<ffwrapper::FormatIn> init_reader(const char* input); |
| | |
| | | |
| | | // New 2nd new |
| | | func New(conf Config) *GoFFMPEG { |
| | | f := C.wrap_fn_create() |
| | | |
| | | var l *C.char |
| | | f := C.wrap_fn_create(0, l) |
| | | |
| | | if f == nil { |
| | | return nil |
| | | } |
| | | if conf.Scale != 0 && conf.Width != 0 && conf.Height != 0 { |
| | | C.wrap_fn_scale(f, C.int(conf.Width), C.int(conf.Height), C.int(conf.Scale)) |
| | | } |
| | | if conf.GB { |
| | | C.wrap_fn_run_gb28181(f) |
| | | } |
| | | if conf.CPU { |
| | | C.wrap_fn_use_cpu(f) |
| | | } |
| | | |
| | | return &GoFFMPEG{ |
| | | ffmpeg: f, |
| | | } |
| | | } |
| | | |
| | | // NewWithLog log |
| | | func NewWithLog(conf Config, logfile string) *GoFFMPEG { |
| | | lf := C.CString(logfile) |
| | | defer C.free(unsafe.Pointer(lf)) |
| | | |
| | | f := C.wrap_fn_create(1, lf) |
| | | if f == nil { |
| | | return nil |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | cffmpeg wrap_fn_create(){ |
| | | return fn_create(); |
| | | cffmpeg wrap_fn_create(const int log, const char *logfile){ |
| | | return fn_create(log, logfile); |
| | | } |
| | | |
| | | void wrap_fn_destroy(const cffmpeg h){ |
| | |
| | | |
| | | typedef void* cffmpeg; |
| | | |
| | | typedef cffmpeg(*lib_cffmpeg_create)(); |
| | | typedef cffmpeg(*lib_cffmpeg_create)(const int, const char*); |
| | | typedef void (*lib_cffmpeg_destroy)(const cffmpeg); |
| | | typedef void (*lib_cffmpeg_run)(const cffmpeg, const char*); |
| | | typedef void (*lib_cffmpeg_scale)(const cffmpeg, const int, const int, const int); |
| | |
| | | libcffmpeg init_libcffmpeg(const char *so_file); |
| | | void release_libcffmpeg(libcffmpeg lib); |
| | | |
| | | cffmpeg wrap_fn_create(); |
| | | cffmpeg wrap_fn_create(const int log, const char *logfile); |
| | | void wrap_fn_destroy(const cffmpeg h); |
| | | void wrap_fn_run(const cffmpeg h, const char* input); |
| | | void wrap_fn_scale(const cffmpeg h, const int wid, const int hei, const int flags); |