Merge branch 'master' of ssh://192.168.5.5:29418/valib/goffmpeg
| | |
| | | void c_ffmpeg_destroy(const cffmpeg h); |
| | | void c_ffmpeg_run(const cffmpeg h, const char *input); |
| | | |
| | | int c_ffmpeg_get_fps(const cffmpeg h); |
| | | void c_ffmpeg_run_gb28181(const cffmpeg h); |
| | | void c_ffmepg_use_cpu(const cffmpeg h); |
| | | /////////passive api |
| | | void c_ffmpeg_set_record_duration(const cffmpeg h, const int min, const int max); |
| | | void c_ffmpeg_build_recorder(const cffmpeg h, const char*id, const char *dir, int mind, int maxd, int audio); |
| | | void c_ffmpeg_build_recorder(const cffmpeg h, const char*id, const char *dir, const int64_t fid, 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); |
| | | |
| | |
| | | const int dstW, const int dstH, const int dstFormat, const int flag); |
| | | void c_ffmpeg_destroy_conv(void *h); |
| | | void *c_ffmpeg_conv(void *h, uint8_t *in); |
| | | |
| | | // gpu conv |
| | | void* c_gpu_conv(uint8_t *in, const int w, const int h, const int dst_w, const int dst_h, int *length); |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | |
| | | #include <unistd.h> |
| | | #include <chrono> |
| | | |
| | | #include <sys/stat.h> |
| | | |
| | | extern "C"{ |
| | | #include <libavcodec/avcodec.h> |
| | | } |
| | |
| | | ,out_(NULL) |
| | | ,maxduration(30 * 25) |
| | | ,minduration(10 * 25) |
| | | ,end_frame(minduration) |
| | | ,cur_frame(0) |
| | | ,fp_(NULL) |
| | | ,stop_recorder_(false) |
| | | ,id_(id) |
| | | ,id_frame_(-1) |
| | | ,id_frame_in_file_(-1) |
| | | ,id_frame_(0) |
| | | ,id_frame_in_file_(0) |
| | | ,file_path_("") |
| | | ,func_rec_info_(nullptr) |
| | | ,thrd_(nullptr) |
| | | ,error_occured_(false) |
| | | ,audio_(false) |
| | | ,cur_frame_a(0) |
| | | ,fp_(NULL) |
| | | ,end_frame_(0) |
| | | ,v_cur_frame_(0) |
| | | ,a_cur_frame_(0) |
| | | ,error_occured_(false) |
| | | ,last_rec_id_(-1) |
| | | { |
| | | if (in){ |
| | | maxduration = 30 * in->getFPS(); |
| | |
| | | std::string filename(sole::uuid4().base62() + "-" + std::to_string(pid) + ".mp4"); |
| | | file_path_ = dir_ + "/" + filename; |
| | | |
| | | std::string backup_dir("./video"); |
| | | size_t pos = dir_.rfind("/"); |
| | | if (pos != std::string::npos){ |
| | | backup_dir = dir_.substr(0, pos); |
| | | } |
| | | |
| | | auto v = in_->getStream(AVMEDIA_TYPE_VIDEO); |
| | | if (!v){ |
| | | return -2; |
| | |
| | | } |
| | | bool ret = out_->JustWriter(v, a, file_path_.c_str()); |
| | | if (ret){ |
| | | logIt("start record file: %s", file_path_.c_str()); |
| | | logIt("start record h264 file: %s", file_path_.c_str()); |
| | | return 0; |
| | | }else{ |
| | | file_path_ = "./" + filename; |
| | | ret = out_->JustWriter(v, a, file_path_.c_str()); |
| | | mkdir(backup_dir.c_str(), 0777); |
| | | file_path_ = backup_dir + "/" + filename; |
| | | |
| | | logIt("failed in dir %s, try file %s to start record file", dir_.c_str(), file_path_.c_str()); |
| | | ret = out_->JustWriter(v, a, file_path_.c_str()); |
| | | if (ret){ |
| | | logIt("start record file: %s", file_path_.c_str()); |
| | | logIt("start record h264 file: %s", file_path_.c_str()); |
| | | return 0; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | int pid = getpid(); |
| | | std::string filename(sole::uuid4().base62() + "-" + std::to_string(pid) + ".mp4"); |
| | | std::string filename(sole::uuid4().base62() + "-" + std::to_string(pid) + ".hevc"); |
| | | file_path_ = dir_ + "/" + filename; |
| | | |
| | | std::string backup_dir("./video"); |
| | | size_t pos = dir_.rfind("/"); |
| | | if (pos != std::string::npos){ |
| | | backup_dir = dir_.substr(0, pos); |
| | | } |
| | | |
| | | fp_ = fopen(file_path_.c_str(), "wb"); |
| | | if (!fp_){ |
| | | file_path_ = "./" + filename; |
| | | mkdir(backup_dir.c_str(), 0777); |
| | | file_path_ = backup_dir + "/" + filename; |
| | | |
| | | logIt("failed in dir %s, try file %s to start record hevc file", dir_.c_str(), file_path_.c_str()); |
| | | fp_ = fopen(file_path_.c_str(), "wb"); |
| | | if (!fp_){ |
| | |
| | | return -1; |
| | | } |
| | | } |
| | | logIt("start record file: %s", file_path_.c_str()); |
| | | logIt("start record hevc file: %s", file_path_.c_str()); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | //////////////////////// |
| | | int Recorder::write_h264(const CPacket &pkt){ |
| | | //reader failed, break stream |
| | | if(pkt.id == -1 && !pkt.data){ |
| | | if(!pkt.data){ |
| | | return -1; |
| | | } |
| | | |
| | | if (cur_frame == end_frame){ |
| | | if (v_cur_frame_ == end_frame_){ |
| | | return 1; |
| | | } |
| | | |
| | | AVPacket &op = pkt.data->getAVPacket(); |
| | | |
| | | if (!audio_ && in_->isAudioPkt(&op)) { |
| | | return 0; |
| | | } |
| | | |
| | | AVPacket np(op); |
| | | av_copy_packet(&np, &op); |
| | | |
| | | int64_t cur = cur_frame; |
| | | int64_t cur = v_cur_frame_; |
| | | if (in_->isVideoPkt(&np)){ |
| | | |
| | | if(pkt.id == id_frame_){ |
| | | id_frame_in_file_ = cur_frame; |
| | | if(pkt.v_id == id_frame_){ |
| | | id_frame_in_file_ = v_cur_frame_; |
| | | } |
| | | cur_frame++; |
| | | v_cur_frame_++; |
| | | |
| | | }else if (in_->isAudioPkt(&np)) { |
| | | cur = cur_frame_a++; |
| | | cur = a_cur_frame_++; |
| | | } |
| | | |
| | | auto ret = out_->writeFrame(&np, cur); |
| | |
| | | logIt("write hevc packet error, file not open"); |
| | | return -1; |
| | | } |
| | | if (cur_frame == end_frame){ |
| | | if (v_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++; |
| | | |
| | | if (in_->isAudioPkt(&op)) { |
| | | return 0; |
| | | } |
| | | if (op.data == NULL){ |
| | | logIt("hevc avpacket data null"); |
| | | return 0; |
| | | } |
| | | |
| | | if (in_->isVideoPkt(&op)){ |
| | | |
| | | if(pkt.v_id == id_frame_){ |
| | | id_frame_in_file_ = v_cur_frame_; |
| | | } |
| | | v_cur_frame_++; |
| | | } |
| | | fwrite(op.data, op.size, 1, fp_); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | std::unique_ptr<FormatIn> in(nullptr); |
| | | int tryTime = 0; |
| | | while (in->openWithCustomIO(fp, read_buffer) < 0) { |
| | | usleep(10000); |
| | | if (tryTime++ < 100){ |
| | | logIt("mux hevc mux: %d failed open custom io %s, try again", tryTime, outfile); |
| | | continue; |
| | | |
| | | while(true){ |
| | | std::unique_ptr<FormatIn> tmp(new FormatIn(false)); |
| | | auto ret = tmp->openWithCustomIO(fp, read_buffer); |
| | | if (ret == 0){ |
| | | in = std::move(tmp); |
| | | break; |
| | | } |
| | | logIt("mux hevc try %d time to open custom io, failed", tryTime); |
| | | return -2; |
| | | usleep(10000); |
| | | if (tryTime++ > 100){ |
| | | logIt("mux hevc try %d time to open custom io %s, failed", tryTime, outfile); |
| | | return -2; |
| | | } |
| | | } |
| | | if (in->open(NULL, NULL) < 0){ |
| | | logIt("mux hevc open stream error"); |
| | |
| | | return -5; |
| | | } |
| | | if (out->JustWriter(v, NULL, outfile)){ |
| | | logIt("mux hevc start record file: %s", outfile); |
| | | logIt("mux hevc start record file: %s", outfile); |
| | | } |
| | | |
| | | int64_t id = 0; |
| | |
| | | end_write_h264(); |
| | | } |
| | | |
| | | logIt("finished record : %s frames: %d", file_path_.c_str(), cur_frame); |
| | | logIt("finished record : %s frames: %d, frame in file id: %d", |
| | | file_path_.c_str(), end_frame_, id_frame_in_file_); |
| | | { |
| | | 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); |
| | | |
| | | if(func_rec_info_){ |
| | | func_rec_info_(id_,id_frame_in_file_, file_path_); |
| | |
| | | std::list<CPacket> pkts; |
| | | { |
| | | std::unique_lock<std::mutex> locker(mutex_pkt_); |
| | | auto status = cv_.wait_for(locker, std::chrono::seconds(3), [&]{ |
| | | int sec = minduration/50; |
| | | if (in_) sec = minduration/in_->getFPS()/2; |
| | | auto status = cv_.wait_for(locker, std::chrono::seconds(sec), [&]{ |
| | | return !list_pkt_.empty() || stop_recorder_.load(); |
| | | }); |
| | | |
| | | |
| | | if (!status || stop_recorder_.load()){ |
| | | error_occured_ = !status; |
| | | break; |
| | | } |
| | | |
| | | list_pkt_.swap(pkts); |
| | | } |
| | | |
| | |
| | | |
| | | stop_recorder_.store(true); |
| | | end_writer(); |
| | | list_pkt_.clear(); |
| | | } |
| | | |
| | | int Recorder::Run(const char* output, const int mind, const int maxd, const bool audio){ |
| | |
| | | if(fps > 1.0){ |
| | | maxduration = fps * maxd; |
| | | minduration = fps * mind; |
| | | end_frame = minduration; |
| | | end_frame_ = minduration; |
| | | } |
| | | |
| | | audio_ = a; |
| | | |
| | | logIt("minduration %d maxduration %d curduration %d", minduration, maxduration, end_frame); |
| | | logIt("minduration %d maxduration %d", minduration, maxduration); |
| | | |
| | | thrd_.reset(new std::thread([&]{ |
| | | run_thread(); |
| | |
| | | int Recorder::FireRecorder(const int64_t &id){ |
| | | if (stop_recorder_.load()) return -1; |
| | | |
| | | if(id_frame_ == -1){ |
| | | if(id_frame_ == 0){ |
| | | id_frame_ = id; |
| | | |
| | | |
| | | 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; |
| | | if (list_pkt_.size() > end_frame_){ |
| | | end_frame_ = list_pkt_.size() + minduration/2; |
| | | if (end_frame_ > maxduration) |
| | | end_frame_ = maxduration; |
| | | } |
| | | |
| | | }else if(v_cur_frame_ > minduration/2 && end_frame_ < maxduration){ |
| | | logIt("cur frame: %d, end frame: %d, duration: [%d-%d]", |
| | | v_cur_frame_, end_frame_, minduration, 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; |
| | | 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::PushPacket(const CPacket &pkt){ |
| | | int Recorder::PushPacket(std::list<CPacket> &lst){ |
| | | if (stop_recorder_.load()) return 0; |
| | | |
| | | std::lock_guard<std::mutex> locker(mutex_pkt_); |
| | | |
| | | if(id_frame_ == -1){ |
| | | //wait I |
| | | if (!audio_ && in_->isAudioPkt(&pkt.data->getAVPacket())){ |
| | | return 0; |
| | | // 没有开始录制 |
| | | if (last_rec_id_ < 0){ |
| | | logIt("last rec id is 0 cache size: %ld", lst.size()); |
| | | for (auto &i : lst){ |
| | | // 从第一个非音频关键帧开始 |
| | | if (last_rec_id_ < 0){ |
| | | if (!in_->isVideoPkt(&i.data->getAVPacket())){ |
| | | continue; |
| | | } |
| | | if (!(i.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ |
| | | continue; |
| | | } |
| | | } |
| | | last_rec_id_ = i.id; |
| | | list_pkt_.push_back(i); |
| | | } |
| | | |
| | | maybe_dump_gop(); |
| | | |
| | | list_pkt_.push_back(pkt); |
| | | // cv_.notify_one(); |
| | | |
| | | }else{ |
| | | list_pkt_.push_back(pkt); |
| | | cv_.notify_one(); |
| | | for(auto &i : lst){ |
| | | if (i.id > last_rec_id_){ |
| | | list_pkt_.push_back(i); |
| | | last_rec_id_++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | cv_.notify_one(); |
| | | |
| | | return list_pkt_.size(); |
| | | } |
| | | |
| | | int Recorder::PushPackets(std::list<CPacket> &lst){ |
| | | |
| | | int Recorder::StartWritePacket(std::list<CPacket> &lst, const int64_t &id, const int start, const int end){ |
| | | |
| | | if (stop_recorder_.load()) return 0; |
| | | |
| | | // 第一次录像,设置触发帧id |
| | | id_frame_ = id; |
| | | |
| | | |
| | | if (start < 0) { |
| | | logIt("start write packet [%d-%d] in pkt size: %d, frame id: %lld, " |
| | | "cur frame: %d, end frame: %d, duration: [%d-%d], last rec id: %lld", |
| | | start, end, lst.size(), id_frame_, |
| | | v_cur_frame_, end_frame_, minduration, maxduration, last_rec_id_); |
| | | return -1; |
| | | } |
| | | |
| | | std::lock_guard<std::mutex> locker(mutex_pkt_); |
| | | bool i = false; |
| | | // 将传入的所有packets保存如缓存 |
| | | int index = -1; |
| | | for (auto &p : lst){ |
| | | if (!audio_ && in_->isAudioPkt(&p.data->getAVPacket())){ |
| | | continue; |
| | | } |
| | | index++; |
| | | if (index < start) continue; |
| | | |
| | | list_pkt_.push_back(p); |
| | | |
| | | if (index == end){ |
| | | last_rec_id_ = p.id; |
| | | break; |
| | | } |
| | | } |
| | | maybe_dump_gop(); |
| | | |
| | | |
| | | logIt("start write packet [%d-%d] in pkt size: %d, frame id: %lld, " |
| | | "cur frame: %d, end frame: %d, duration: [%d-%d], last rec id: %lld", |
| | | start, end, lst.size(), id_frame_, |
| | | v_cur_frame_, end_frame_, minduration, maxduration, last_rec_id_); |
| | | |
| | | |
| | | // 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() > minduration) { |
| | | |
| | | while (list_pkt_.size() > maxduration) { |
| | | list_pkt_.pop_front(); |
| | | while(!list_pkt_.empty()){ |
| | | auto &i = list_pkt_.front(); |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }// end clase |
| | | }// end namespace |
| | |
| | | |
| | | public: |
| | | 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 PushPacket(std::list<CPacket> &lst); |
| | | int StartWritePacket(std::list<CPacket> &lst, const int64_t &id, const int start, const int end); |
| | | int FireRecorder(const int64_t &id); |
| | | |
| | | void SetCallback(FUNC_REC_INFO cb){ |
| | |
| | | ffwrapper::FormatIn *in_; |
| | | ffwrapper::FormatOut *out_; |
| | | |
| | | int maxduration; |
| | | int minduration; |
| | | int end_frame; |
| | | int cur_frame; |
| | | int cur_frame_a; |
| | | |
| | | std::list<CPacket> list_pkt_; |
| | | |
| | | std::list<CPacket> list_pkt_; |
| | | std::atomic_bool stop_recorder_; |
| | | std::mutex mutex_pkt_; |
| | | std::condition_variable cv_; |
| | | |
| | | std::unique_ptr<std::thread> thrd_; |
| | | |
| | | std::string dir_; |
| | | std::string id_; |
| | | |
| | | int64_t id_frame_; |
| | | int id_frame_in_file_; |
| | | |
| | | std::string file_path_; |
| | | FUNC_REC_INFO func_rec_info_; |
| | | |
| | | bool error_occured_; |
| | | |
| | | FILE *fp_; |
| | | bool audio_; |
| | | |
| | | FILE *fp_; |
| | | std::unique_ptr<std::thread> thrd_; |
| | | |
| | | |
| | | int end_frame_; |
| | | int v_cur_frame_; |
| | | int a_cur_frame_; |
| | | |
| | | int64_t last_rec_id_; |
| | | |
| | | int maxduration; |
| | | int minduration; |
| | | |
| | | bool error_occured_; |
| | | }; |
| | | } |
| | | } |
| | |
| | | s->RunStream(input); |
| | | } |
| | | |
| | | int c_ffmpeg_get_fps(const cffmpeg h){ |
| | | Wrapper *s = (Wrapper*)h; |
| | | return s->GetFPS(); |
| | | } |
| | | |
| | | void c_ffmpeg_run_gb28181(const cffmpeg h){ |
| | | Wrapper *s = (Wrapper*)h; |
| | | s->GB28181(); |
| | |
| | | s->SetRecMinCacheTime(min); |
| | | } |
| | | |
| | | void c_ffmpeg_build_recorder(const cffmpeg h, const char* id, const char *dir, int mind, int maxd, int audio){ |
| | | void c_ffmpeg_build_recorder(const cffmpeg h, const char* id, const char *dir, const int64_t fid, int mind, int maxd, int audio){ |
| | | Wrapper *s = (Wrapper*)h; |
| | | |
| | | bool a = audio == 0 ? false : true; |
| | | s->BuildRecorder(id, dir, mind, maxd, a); |
| | | s->BuildRecorder(id, dir, fid, mind, maxd, a); |
| | | } |
| | | |
| | | void c_ffmpeg_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){ |
| | |
| | | void c_ffmpeg_destroy_conv(void *h){ |
| | | DestoryConvertor(h); |
| | | } |
| | | |
| | | void* c_gpu_conv(uint8_t *in, const int w, const int h, const int dst_w, const int dst_h, int *length){ |
| | | return ConvertYUV2BGR(in, w, h, dst_w, dst_h, length); |
| | | } |
| | |
| | | class CodedData; |
| | | } |
| | | // 缓存的视频帧 |
| | | typedef struct _cache_pkt{ |
| | | class CPacket{ |
| | | public: |
| | | std::shared_ptr<ffwrapper::CodedData> data; |
| | | int64_t v_id; |
| | | int64_t a_id; |
| | | int64_t id; |
| | | }CPacket; |
| | | }; |
| | | |
| | | #endif |
| | |
| | | av_register_all(); |
| | | avfilter_register_all(); |
| | | avformat_network_init(); |
| | | av_log_set_level(AV_LOG_VERBOSE); |
| | | av_log_set_level(AV_LOG_ERROR); |
| | | } |
| | | |
| | | std::string getAVErrorDesc(const int code){ |
| | |
| | | |
| | | FormatIn::~FormatIn() |
| | | { |
| | | if(io_ctx_){ |
| | | if(read_io_buff_){ |
| | | // av_free(read_io_buff_); |
| | | read_io_buff_ = NULL; |
| | | } |
| | | avio_context_free(&io_ctx_); |
| | | io_ctx_ = NULL; |
| | | } |
| | | if(ctx_){ |
| | | if (!ctx_->oformat){ |
| | | avformat_free_context(ctx_); |
| | | }else{ |
| | | if (!(ctx_->flags & AVFMT_FLAG_CUSTOM_IO)){ |
| | | avformat_close_input(&ctx_); |
| | | }else{ |
| | | avformat_free_context(ctx_); |
| | | } |
| | | |
| | | ctx_ = NULL; |
| | | if(dec_ctx_){ |
| | | avcodec_close(dec_ctx_); |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | if (handle_gb28181){ |
| | | delete handle_gb28181; |
| | | } |
| | | if(read_io_buff_){ |
| | | av_free(read_io_buff_); |
| | | read_io_buff_ = NULL; |
| | | } |
| | | if(io_ctx_){ |
| | | avio_context_free(&io_ctx_); |
| | | io_ctx_ = NULL; |
| | | } |
| | | |
| | | } |
| | | |
| | | //////////////////////////////////////////////////////////////////////// |
| | | int FormatIn::openWithCustomIO(void *opaque, read_packet fn, AVDictionary **options/*=NULL*/){ |
| | | ctx_ = avformat_alloc_context(); |
| | | if(!ctx_){ |
| | | logIt("open with custom io create format error\n"); |
| | | return -1; |
| | | } |
| | | read_io_buff_ = (uint8_t*)av_malloc(read_io_buff_size_); |
| | | if(!read_io_buff_){ |
| | | logIt("open with custom io alloc read io buff error\n"); |
| | |
| | | logIt("open with custom io create custom avio error\n"); |
| | | return -1; |
| | | } |
| | | |
| | | ctx_ = avformat_alloc_context(); |
| | | if(!ctx_){ |
| | | logIt("open with custom io create format error\n"); |
| | | return -1; |
| | | } |
| | | |
| | | ctx_->pb = io_ctx_; |
| | | |
| | | auto err = av_probe_input_buffer(ctx_->pb, &ctx_->iformat, NULL, NULL, 0, read_io_buff_size_); |
| | | auto err = av_probe_input_buffer(ctx_->pb, &ctx_->iformat, NULL, NULL, 0, 0); |
| | | if(err != 0){ |
| | | logIt("open with custom io prob input buffer error:%d err: %s\n", err, getAVErrorDesc(err).c_str()); |
| | | return -1; |
| | |
| | | int out_idx = -1; |
| | | std::vector<AVStream*> in_streams{in_v_stream_, in_a_stream_}; |
| | | for (auto i : in_streams){ |
| | | if (i->index == pkt->stream_index){ |
| | | if (i && (i->index == pkt->stream_index)){ |
| | | if (i->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){ |
| | | out_idx = v_idx_; |
| | | in_stream = i; |
| | |
| | | while (!q.empty()) q.pop_front(); |
| | | pthread_mutex_unlock(&mtx); |
| | | } |
| | | |
| | | void clearAll(std::function<void(T)> fn){ |
| | | pthread_mutex_lock(&mtx); |
| | | while (!q.empty()){ |
| | | T value = q.front(); |
| | | fn(value); |
| | | q.pop_front(); |
| | | } |
| | | pthread_mutex_unlock(&mtx); |
| | | } |
| | | private: |
| | | deque<T> q; |
| | | pthread_mutex_t mtx; |
| | |
| | | |
| | | ~GB28181API(){ |
| | | printf("GB28181API end!\n"); |
| | | m_rtpQueue.clearAll(); |
| | | // m_rtpQueue.clearAll(); |
| | | m_rtpQueue.clearAll([](frameBuffInfo *info){ |
| | | delete[] info->buff; |
| | | delete info; |
| | | }); |
| | | deleteCamera(); |
| | | } |
| | | |
| | |
| | | #include "../ffmpeg/format/FormatIn.hpp" |
| | | #include "../ffmpeg/data/CodedData.hpp" |
| | | #include "../ffmpeg/log/log.hpp" |
| | | #include "../common.hpp" |
| | | |
| | | extern "C"{ |
| | | #include <libavformat/avformat.h> |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int decoder::saveFrame(AVFrame *frame, int64_t &id){ |
| | | int decoder::saveFrame(AVFrame *frame, const int64_t &id){ |
| | | FRM frm; |
| | | frm.width = frame->width; |
| | | frm.height = frame->height; |
| | |
| | | return list_frm_.size(); |
| | | } |
| | | |
| | | int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | int decoder::SetFrame(const CPacket &pkt){ |
| | | auto data = pkt.data; |
| | | |
| | | if (!data) return -10; |
| | | if (!decRef_->isVideoPkt(&data->getAVPacket())) return -20; |
| | |
| | | av_packet_unref(&np); |
| | | |
| | | if (ret == 0){ |
| | | saveFrame(frame, id); |
| | | saveFrame(frame, pkt.v_id); |
| | | } |
| | | av_frame_free(&frame); |
| | | return ret; |
| | |
| | | struct AVFrame; |
| | | struct AVCodecContext; |
| | | |
| | | class CPacket; |
| | | |
| | | namespace ffwrapper |
| | | { |
| | | class FormatIn; |
| | |
| | | |
| | | private: |
| | | int initDecoder(); |
| | | int saveFrame(AVFrame *frame, int64_t &id); |
| | | int saveFrame(AVFrame *frame, const int64_t &id); |
| | | public: |
| | | void Start(); |
| | | int SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); |
| | | int SetFrame(const CPacket &pkt); |
| | | void GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id); |
| | | |
| | | public: |
| | |
| | | using namespace ffwrapper; |
| | | using namespace cffmpeg_wrap::buz; |
| | | |
| | | static const int cache_time = 6 * 60; |
| | | |
| | | namespace cffmpeg_wrap |
| | | { |
| | | rec::rec() |
| | | :recRef_(NULL) |
| | | ,min_cache_len_(125) |
| | | ,time_offset_(5) |
| | | ,min_cache_len_(cache_time * 25) // 最小缓存?分钟的视频,因为整个流程会有延迟,暂定?分钟 |
| | | {} |
| | | |
| | | rec::~rec() |
| | |
| | | list_recInfo_.emplace_back(info); |
| | | } |
| | | |
| | | std::unique_ptr<buz::Recorder> rec::startRec(std::string id, std::string dir, const int mind, const int maxd, const bool audio){ |
| | | void rec::findRecFramesIndex(const int64_t &fired_id, const int duration, int &start, int &end){ |
| | | |
| | | start = end = -1; |
| | | |
| | | if (list_pkt_.empty()){ |
| | | return; |
| | | } |
| | | |
| | | // 录像开始id在触发id之前1/2时长,保证在中间 |
| | | int64_t start_id = fired_id - duration/2; |
| | | // 寻找关键帧作为录像开始id |
| | | int offset = recRef_ ? recRef_->getFPS() : 25; |
| | | |
| | | int64_t index = -1; |
| | | |
| | | for(auto &i : list_pkt_){ |
| | | index++; |
| | | // 跳过音频 |
| | | if(!recRef_->isVideoPkt(&i.data->getAVPacket())){ |
| | | continue; |
| | | } |
| | | // 寻找关键帧作为起始 |
| | | if (start < 0){ |
| | | if (i.data->getAVPacket().flags & AV_PKT_FLAG_KEY){ |
| | | // 当前帧id > 开始id或开始id在offset内,作为起始录像帧 |
| | | if (i.v_id >= start_id || start_id - i.v_id < offset){ |
| | | start = index; |
| | | start_id = i.v_id; |
| | | } |
| | | } |
| | | }else if (recRef_->isVideoPkt(&i.data->getAVPacket())){ |
| | | // 视频帧,看是否缓存中有所有的duration数据 |
| | | if (i.v_id - start_id == duration){ |
| | | end = index; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | if (end < 0) end = index; |
| | | } |
| | | |
| | | std::unique_ptr<buz::Recorder> rec::startRec(std::string id, std::string dir, const int64_t &frameID, const int mind, const int maxd, const bool audio){ |
| | | if(!recRef_){ |
| | | logIt("Init wrapper first"); |
| | | return nullptr; |
| | |
| | | if(ret == 0) break; |
| | | usleep(200000); |
| | | } |
| | | |
| | | if (trycnt < 100){ |
| | | int duration = mind * recRef_->getFPS(); |
| | | int start=0, end=0; |
| | | |
| | | std::lock_guard<std::mutex> locker(mtx_pkt_); |
| | | rec->PushPackets(list_pkt_); |
| | | logIt("cache size: %ld", list_pkt_.size()); |
| | | // 首次获取录像信息,先存一个最短时长 |
| | | findRecFramesIndex(frameID, duration, start, end); |
| | | rec->StartWritePacket(list_pkt_, frameID, start, end); |
| | | |
| | | return rec; |
| | | } |
| | | |
| | |
| | | |
| | | void rec::Load(ffwrapper::FormatIn *in){ |
| | | recRef_ = in; |
| | | if (in){ |
| | | min_cache_len_ = in->getFPS() * cache_time; |
| | | } |
| | | } |
| | | |
| | | void rec::Unload(){ |
| | |
| | | return recRef_ != NULL; |
| | | } |
| | | |
| | | void rec::NewRec(const char* id, const char *output, const int mindur, const int maxdur, const bool audio){ |
| | | void rec::NewRec(const char* id, const char *output, const int64_t &frameID, const int mindur, const int maxdur, const bool audio){ |
| | | std::string rid(id); |
| | | std::string dir(output); |
| | | |
| | |
| | | if (map_rec_.find(rid) != map_rec_.end()){ |
| | | map_rec_.erase(rid); |
| | | } |
| | | map_rec_[rid] = startRec(rid, dir, mindur, maxdur, audio); |
| | | map_rec_[rid] = startRec(rid, dir, frameID, mindur, maxdur, audio); |
| | | } |
| | | |
| | | } |
| | |
| | | // logIt("recorders count: %d", map_rec_.size()); |
| | | } |
| | | |
| | | void rec::SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | if (!data) return; |
| | | void rec::SetPacket(const CPacket &pkt){ |
| | | if (!pkt.data) return; |
| | | cachePacket(pkt); |
| | | |
| | | std::lock_guard<std::mutex> l(mtx_rec_); |
| | | for(auto &i : map_rec_){ |
| | | if (i.second){ |
| | | i.second->PushPacket({data, id}); |
| | | std::lock_guard<std::mutex> pl(mtx_pkt_); |
| | | i.second->PushPacket(list_pkt_); |
| | | } |
| | | } |
| | | |
| | | cachePacket(data, id); |
| | | } |
| | | |
| | | void rec::cachePacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | void rec::cachePacket(const CPacket &pkt){ |
| | | |
| | | std::lock_guard<std::mutex> l(mtx_pkt_); |
| | | //wait I |
| | | if (list_pkt_.empty()) { |
| | | if (!recRef_->isVideoPkt(&pkt.data->getAVPacket())){ |
| | | return; |
| | | } |
| | | |
| | | if (!(data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ |
| | | if (!(pkt.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ |
| | | return; |
| | | } |
| | | } |
| | | |
| | | list_pkt_.push_back({data, id}); |
| | | list_pkt_.push_back(pkt); |
| | | |
| | | // 超过缓存最大长度,删除一个gop |
| | | shrinkCache(); |
| | |
| | | if (recRef_){ |
| | | fps = recRef_->getFPS(); |
| | | } |
| | | min_cache_len_ = (min + time_offset_) * fps; |
| | | min_cache_len_ += min * fps; |
| | | } |
| | | |
| | | int rec::shrinkCache(){ |
| | | //超过最大缓存,丢弃gop |
| | | //缓存最小长度的,用于记录 |
| | | int fps = 25; |
| | | if (recRef_){ |
| | | fps = recRef_->getFPS(); |
| | | } |
| | | // 最小5秒长度 |
| | | int mincache = fps * 5; |
| | | int md = min_cache_len_ < mincache ? mincache : min_cache_len_; |
| | | while (list_pkt_.size() > md) { |
| | | //超过最大缓存,丢弃gop |
| | | |
| | | while (list_pkt_.size() > min_cache_len_) { |
| | | list_pkt_.pop_front(); |
| | | while(!list_pkt_.empty()){ |
| | | auto &i = list_pkt_.front(); |
| | | if (!(i.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ |
| | | // 音频丢弃 |
| | | if (!recRef_->isVideoPkt(&i.data->getAVPacket())){ |
| | | list_pkt_.pop_front(); |
| | | }else if (!(i.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ |
| | | // 非关键帧丢弃 |
| | | list_pkt_.pop_front(); |
| | | }else{ |
| | | break; |
| | |
| | | #include "../buz/recorder.hpp" |
| | | |
| | | struct AVPacket; |
| | | class CPacket; |
| | | |
| | | namespace ffwrapper |
| | | { |
| | |
| | | private: |
| | | ffwrapper::FormatIn *recRef_; |
| | | int min_cache_len_; |
| | | // 整个流程耗时补偿录制时间,2s默认 |
| | | const int time_offset_; |
| | | // 录像的实例,对应任务 |
| | | std::unordered_map<std::string, std::unique_ptr<buz::Recorder> > map_rec_; |
| | | // 多线程添加任务实例,在读流线程使用录像,但是添加在另一个线程 |
| | |
| | | std::mutex mtx_pkt_; |
| | | |
| | | private: |
| | | // 查找缓存中的录制帧 |
| | | void findRecFramesIndex(const int64_t &fired_id, const int duration, int &start, int &end); |
| | | |
| | | // 录像实例的回调函数,录像完成后设置录像文件路径,id和帧id |
| | | void setRecInfo(std::string &id, int &index, std::string &path); |
| | | // 缓存视频包 |
| | | void cachePacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); |
| | | void cachePacket(const CPacket &pkt); |
| | | // 丢弃缓存 |
| | | int shrinkCache(); |
| | | // 创建录像实例开始录像 |
| | | std::unique_ptr<buz::Recorder> startRec(std::string id, std::string dir, const int mind, const int maxd, const bool audio); |
| | | std::unique_ptr<buz::Recorder> startRec(std::string id, std::string dir, const int64_t &frameID, 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, const bool audio); |
| | | void NewRec(const char* id, const char *output, const int64_t &frameID, const int mindur, const int maxdur, const bool audio); |
| | | |
| | | // 准备好录像 |
| | | void Load(ffwrapper::FormatIn *in); |
| | | void Unload(); |
| | | const bool Loaded() const; |
| | | // 缓存录像的视频包,等待触发录像,或直接放到录像缓存 |
| | | void SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); |
| | | void SetPacket(const CPacket &pkt); |
| | | // 触发录像 |
| | | void FireRecSignal(const char* sid,const int64_t &id); |
| | | // 获取录像文件路径和帧id |
| | |
| | | |
| | | #include "../ffmpeg/format/FormatIn.hpp" |
| | | #include "../ffmpeg/data/CodedData.hpp" |
| | | #include "../ffmpeg/log/log.hpp" |
| | | using namespace logif; |
| | | |
| | | namespace cffmpeg_wrap{ |
| | | stream::stream(ffwrapper::FormatIn *in, const int maxSize) |
| | |
| | | list_pkt_.clear(); |
| | | } |
| | | |
| | | int stream::SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | if (data){ |
| | | |
| | | int stream::SetPacket(const CPacket &pkt){ |
| | | if (pkt.data){ |
| | | // 如果包是音频包,但是不使用音频,直接返回 |
| | | if (!audio_ && streamRef_->isAudioPkt(&data->getAVPacket())){ |
| | | if (!audio_ && streamRef_->isAudioPkt(&pkt.data->getAVPacket())){ |
| | | return 0; |
| | | } |
| | | |
| | | std::lock_guard<std::mutex> locker(mutex_avpkt_); |
| | | list_pkt_.push_back({data, id}); |
| | | list_pkt_.push_back(pkt); |
| | | |
| | | while(list_pkt_.size() > max_size_/2*3){ |
| | | list_pkt_.pop_front(); |
| | |
| | | stream(ffwrapper::FormatIn *in, const int maxSize); |
| | | ~stream(); |
| | | |
| | | int SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); |
| | | int SetPacket(const CPacket &pkt); |
| | | void GetPacket(unsigned char **pktData, int *size, int *key); |
| | | void AudioSwitch(const bool a){audio_ = a;} |
| | | }; |
| | |
| | | #include "worker/stream.hpp" |
| | | #include "worker/decoder.hpp" |
| | | #include "worker/rec.hpp" |
| | | |
| | | #include "CUDALERP.h" |
| | | #include "common.hpp" |
| | | |
| | | using namespace logif; |
| | | using namespace ffwrapper; |
| | |
| | | ,decoder_(nullptr) |
| | | ,rec_(new rec) |
| | | ,logit_(false) |
| | | ,fps_(25) |
| | | { |
| | | makeTheWorld(); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | int Wrapper::run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | int Wrapper::run_worker(ffwrapper::FormatIn *in, const CPacket &pkt){ |
| | | if (gb_){ |
| | | AVPacket &pkt = data->getAVPacket(); |
| | | pkt.pts = pkt.dts = AV_NOPTS_VALUE; |
| | | AVPacket &p = pkt.data->getAVPacket(); |
| | | p.pts = p.dts = AV_NOPTS_VALUE; |
| | | } |
| | | int flag = 0; |
| | | if (stream_) stream_->SetPacket(data, id); |
| | | if (decoder_ && run_dec_) flag = decoder_->SetFrame(data, id); |
| | | if (rec_->Loaded()) rec_->SetPacket(data, id); |
| | | if (stream_) stream_->SetPacket(pkt); |
| | | if (decoder_ && run_dec_) flag = decoder_->SetFrame(pkt); |
| | | if (rec_->Loaded()) rec_->SetPacket(pkt); |
| | | |
| | | return flag; |
| | | } |
| | |
| | | continue; |
| | | } |
| | | |
| | | fps_ = in->getFPS(); |
| | | |
| | | int wTime = 1000000.0 / in->getFPS() ; |
| | | wTime >>= 1; |
| | | logIt("WAIT TIME PER FRAME: %d", wTime); |
| | |
| | | init_worker(in.get()); |
| | | |
| | | int64_t id = gb_ ? 0 : -1; |
| | | |
| | | int64_t v_id = id; |
| | | int64_t a_id = id; |
| | | |
| | | bool exist = access(input_url_.c_str(), 0) == 0 ? true : false; |
| | | |
| | | while(!stop_stream_.load()){ |
| | |
| | | logIt("read packet error, id: %lld", id); |
| | | break; |
| | | } |
| | | // 非音视频 |
| | | if (in->notVideoAudio(&data->getAVPacket())){ |
| | | continue; |
| | | } |
| | | |
| | | // 非国标跳过第一帧,测试第一帧有问题 |
| | | if (!gb_ && id < 0){ |
| | | id++; |
| | | id++; v_id++; a_id++; |
| | | continue; |
| | | } |
| | | |
| | | CPacket pkt{data, v_id, a_id, id}; |
| | | // decode error |
| | | if (run_worker(in.get(), data, id) == -1){ |
| | | if (run_worker(in.get(), pkt) == -1){ |
| | | break; |
| | | } |
| | | |
| | | if (in->isVideoPkt(&data->getAVPacket())){ |
| | | v_id++; |
| | | }else{ |
| | | a_id++; |
| | | } |
| | | |
| | | id++; |
| | | |
| | | //本地文件太快sleep一下 |
| | | if (exist){ |
| | | usleep(wTime); |
| | | } |
| | | |
| | | id++; |
| | | } |
| | | |
| | | deinit_worker(); |
| | |
| | | rec_->SetRecMinCacheTime(mind); |
| | | } |
| | | |
| | | void Wrapper::BuildRecorder(const char* id, const char *output, const int mindur, const int maxdur, const bool audio){ |
| | | void Wrapper::BuildRecorder(const char* id, const char *output, const int64_t &fid, 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, a); |
| | | rec_->NewRec(id, output, fid, mindur, maxdur, a); |
| | | }else{ |
| | | std::string rid(id), dir(output); |
| | | fn_rec_lazy_ = |
| | | [=]{rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur, a);}; |
| | | [=]{rec_->NewRec(rid.c_str(), dir.c_str(), fid, mindur, maxdur, a);}; |
| | | } |
| | | } |
| | | |
| | |
| | | free(c); |
| | | } |
| | | |
| | | |
| | | uint8_t* ConvertYUV2BGR(uint8_t *src, const int w, const int h, const int dst_w, const int dst_h, int *length){ |
| | | return NULL; |
| | | |
| | | // int oldw = w, oldh = h, neww = dst_w, newh = dst_h; |
| | | // // setting cache and shared modes |
| | | // cudaDeviceSetCacheConfig(cudaFuncCachePreferL1); |
| | | // cudaDeviceSetSharedMemConfig(cudaSharedMemBankSizeFourByte); |
| | | |
| | | // // allocating and transferring image and binding to texture object |
| | | // cudaChannelFormatDesc chandesc_img = cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned); |
| | | // cudaArray* d_img_arr; |
| | | // cudaMallocArray(&d_img_arr, &chandesc_img, oldw, oldh, cudaArrayTextureGather); |
| | | // cudaMemcpyToArray(d_img_arr, 0, 0, image, oldh * oldw, cudaMemcpyHostToDevice); |
| | | // struct cudaResourceDesc resdesc_img; |
| | | // memset(&resdesc_img, 0, sizeof(resdesc_img)); |
| | | // resdesc_img.resType = cudaResourceTypeArray; |
| | | // resdesc_img.res.array.array = d_img_arr; |
| | | // struct cudaTextureDesc texdesc_img; |
| | | // memset(&texdesc_img, 0, sizeof(texdesc_img)); |
| | | // texdesc_img.addressMode[0] = cudaAddressModeClamp; |
| | | // texdesc_img.addressMode[1] = cudaAddressModeClamp; |
| | | // texdesc_img.readMode = cudaReadModeNormalizedFloat; |
| | | // texdesc_img.filterMode = cudaFilterModePoint; |
| | | // texdesc_img.normalizedCoords = 0; |
| | | // cudaTextureObject_t d_img_tex = 0; |
| | | // cudaCreateTextureObject(&d_img_tex, &resdesc_img, &texdesc_img, nullptr); |
| | | |
| | | // uint8_t* d_out = nullptr; |
| | | // cudaMalloc(&d_out, total); |
| | | |
| | | // for (int i = 0; i < warmups; ++i) CUDALERP(d_img_tex, oldw, oldh, d_out, neww, newh); |
| | | // auto start = high_resolution_clock::now(); |
| | | // for (int i = 0; i < runs; ++i) CUDALERP(d_img_tex, oldw, oldh, d_out, neww, newh); |
| | | // auto end = high_resolution_clock::now(); |
| | | // auto sum = (end - start) / runs; |
| | | |
| | | // auto h_out = new uint8_t[neww * newh]; |
| | | // cudaMemcpy(h_out, d_out, total, cudaMemcpyDeviceToHost); |
| | | } |
| | | } |
| | | |
| | |
| | | #include <memory> |
| | | #include "common/callback.hpp" |
| | | |
| | | |
| | | class CPacket; |
| | | |
| | | namespace ffwrapper{ |
| | | class FormatIn; |
| | |
| | | std::unique_ptr<ffwrapper::FormatIn> init_reader(const char* input); |
| | | |
| | | void init_worker(ffwrapper::FormatIn *in); |
| | | int run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); |
| | | int run_worker(ffwrapper::FormatIn *in, const CPacket &pkt); |
| | | 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, const bool audio); |
| | | void BuildRecorder(const char* id, const char *dir, const int64_t &fid, 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 CPUDec(){cpu_ = 1;} |
| | | void AudioSwitch(const bool a); |
| | | void SetRecMinCacheTime(const int mind); |
| | | |
| | | int GetFPS(){return fps_;} |
| | | public: //decoder |
| | | void BuildDecoder(); |
| | | void GetPicDecoder(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id); |
| | |
| | | // 录像请求缓存,等待runstream后添加 |
| | | std::function<void()> fn_rec_lazy_; |
| | | bool logit_; |
| | | int fps_; |
| | | }; |
| | | |
| | | uint8_t* Decode(const char *file, const int gb, int *w, int *h); |
| | |
| | | const int dstW, const int dstH, const int dstFormat, const int flag); |
| | | uint8_t *Convert(void *h, uint8_t *src); |
| | | void DestoryConvertor(void *h); |
| | | |
| | | uint8_t* ConvertYUV2BGR(uint8_t *src, const int w, const int h, const int dst_w, const int dst_h, int *length); |
| | | } |
| | | |
| | | #endif |
| | |
| | | |
| | | // NewConv new conv |
| | | func NewConv(srcW, srcH, dstW, dstH, scaleFlag int) *GoConv { |
| | | c := C.wrap_fn_create_conv(C.int(srcW), C.int(srcH), C.int(SrcFormat), |
| | | c := C.wrap_fn_create_conv(unsafe.Pointer(libcffmpeg), C.int(srcW), C.int(srcH), C.int(SrcFormat), |
| | | C.int(dstW), C.int(dstH), C.int(DstFormat), C.int(scaleFlag)) |
| | | |
| | | if c == nil { |
| | |
| | | |
| | | // NewResizer resize |
| | | func NewResizer(srcW, srcH, format, dstW, dstH, scaleFlag int) *GoConv { |
| | | c := C.wrap_fn_create_conv(C.int(srcW), C.int(srcH), C.int(format), |
| | | c := C.wrap_fn_create_conv(unsafe.Pointer(libcffmpeg), C.int(srcW), C.int(srcH), C.int(format), |
| | | C.int(dstW), C.int(dstH), C.int(format), C.int(scaleFlag)) |
| | | |
| | | if c == nil { |
| | |
| | | // Free free |
| | | func (c *GoConv) Free() { |
| | | if c.conv != nil { |
| | | C.wrap_fn_destroy_conv(c.conv) |
| | | C.wrap_fn_destroy_conv(unsafe.Pointer(libcffmpeg), c.conv) |
| | | } |
| | | } |
| | | |
| | |
| | | cin := C.CBytes(src) |
| | | defer C.free(cin) |
| | | |
| | | bgr := C.wrap_fn_conv(c.conv, (*C.uchar)(cin)) |
| | | bgr := C.wrap_fn_conv(unsafe.Pointer(libcffmpeg), c.conv, (*C.uchar)(cin)) |
| | | defer C.free(unsafe.Pointer(bgr)) |
| | | |
| | | if bgr != nil { |
| | |
| | | |
| | | // BuildDecoder build decoder |
| | | func (h *GoFFMPEG) BuildDecoder() { |
| | | C.wrap_fn_decoder(h.ffmpeg) |
| | | C.wrap_fn_decoder(unsafe.Pointer(libcffmpeg), h.ffmpeg) |
| | | } |
| | | |
| | | // GetYUV get yuv data |
| | |
| | | var length C.int |
| | | var srcW, srcH, srcF C.int |
| | | |
| | | p := C.wrap_fn_decoder_pic(h.ffmpeg, &srcW, &srcH, &srcF, &length, &fid) |
| | | p := C.wrap_fn_decoder_pic(unsafe.Pointer(libcffmpeg), h.ffmpeg, &srcW, &srcH, &srcF, &length, &fid) |
| | | if srcW == 0 || srcH == 0 { |
| | | return nil, 0, 0, 0 |
| | | } |
| | |
| | | |
| | | var width C.int |
| | | var height C.int |
| | | p := C.wrap_fn_decode(in, C.int(withGB), &width, &height) |
| | | p := C.wrap_fn_decode(unsafe.Pointer(libcffmpeg), in, C.int(withGB), &width, &height) |
| | | defer C.free(p) |
| | | |
| | | if width > 0 && height > 0 { |
| | |
| | | #include "libcffmpeg.h" |
| | | */ |
| | | import "C" |
| | | import "unsafe" |
| | | |
| | | ///////////////for encoder |
| | | |
| | |
| | | } |
| | | |
| | | return &GoEncoder{ |
| | | enc: C.wrap_fn_create_encoder(C.int(w), C.int(h), C.int(fps), C.int(br), C.int(sFlag), C.int(gi)), |
| | | enc: C.wrap_fn_create_encoder(unsafe.Pointer(libcffmpeg), C.int(w), C.int(h), C.int(fps), C.int(br), C.int(sFlag), C.int(gi)), |
| | | } |
| | | } |
| | | |
| | | // Free free |
| | | func (e *GoEncoder) Free() { |
| | | if e.enc != nil { |
| | | C.wrap_fn_destroy_encoder(e.enc) |
| | | C.wrap_fn_destroy_encoder(unsafe.Pointer(libcffmpeg), e.enc) |
| | | } |
| | | } |
| | | |
| | |
| | | cin := C.CBytes(in) |
| | | defer C.free(cin) |
| | | |
| | | p := C.wrap_fn_encode(e.enc, cin, C.int(w), C.int(h), &size, &key) |
| | | p := C.wrap_fn_encode(unsafe.Pointer(libcffmpeg), e.enc, cin, C.int(w), C.int(h), &size, &key) |
| | | defer C.free(p) |
| | | if p != nil && size > 0 { |
| | | b := C.GoBytes(p, size) |
| | |
| | | // New 2nd new |
| | | func New(GB, CPU bool) *GoFFMPEG { |
| | | |
| | | f := C.wrap_fn_create() |
| | | f := C.wrap_fn_create(unsafe.Pointer(libcffmpeg)) |
| | | |
| | | if f == nil { |
| | | return nil |
| | | } |
| | | if GB { |
| | | C.wrap_fn_run_gb28181(f) |
| | | C.wrap_fn_run_gb28181(unsafe.Pointer(libcffmpeg), f) |
| | | } |
| | | if CPU { |
| | | C.wrap_fn_use_cpu(f) |
| | | C.wrap_fn_use_cpu(unsafe.Pointer(libcffmpeg), f) |
| | | } |
| | | |
| | | return &GoFFMPEG{ |
| | |
| | | lf := C.CString(ffmpegLog) |
| | | defer C.free(unsafe.Pointer(lf)) |
| | | |
| | | f := C.wrap_fn_create2(lf) |
| | | f := C.wrap_fn_create2(unsafe.Pointer(libcffmpeg), lf) |
| | | if f == nil { |
| | | return nil |
| | | } |
| | | if GB { |
| | | C.wrap_fn_run_gb28181(f) |
| | | C.wrap_fn_run_gb28181(unsafe.Pointer(libcffmpeg), f) |
| | | } |
| | | if CPU { |
| | | C.wrap_fn_use_cpu(f) |
| | | C.wrap_fn_use_cpu(unsafe.Pointer(libcffmpeg), f) |
| | | } |
| | | |
| | | return &GoFFMPEG{ |
| | |
| | | // Free free handle |
| | | func (h *GoFFMPEG) Free() { |
| | | if h.ffmpeg != nil { |
| | | C.wrap_fn_destroy(h.ffmpeg) |
| | | C.wrap_fn_destroy(unsafe.Pointer(libcffmpeg), h.ffmpeg) |
| | | } |
| | | } |
| | | |
| | |
| | | in := C.CString(input) |
| | | defer C.free(unsafe.Pointer(in)) |
| | | |
| | | C.wrap_fn_run(h.ffmpeg, in) |
| | | C.wrap_fn_run(unsafe.Pointer(libcffmpeg), h.ffmpeg, in) |
| | | } |
| | | |
| | | // FPS fps |
| | | func (h *GoFFMPEG) FPS() int { |
| | | return int(C.wrap_fn_fps(unsafe.Pointer(libcffmpeg), h.ffmpeg)) |
| | | } |
| | |
| | | func (h *GoFFMPEG) FireRecorder(sid string, id int64) { |
| | | csid := C.CString(sid) |
| | | defer C.free(unsafe.Pointer(csid)) |
| | | C.wrap_fn_fire_recorder(h.ffmpeg, csid, C.long(id)) |
| | | C.wrap_fn_fire_recorder(unsafe.Pointer(libcffmpeg), h.ffmpeg, csid, C.long(id)) |
| | | } |
| | | |
| | | // BuildRecorder build recorder |
| | | func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd int, audio bool) { |
| | | func (h *GoFFMPEG) BuildRecorder(sid, output string, id int64, mind, maxd int, audio bool) { |
| | | out := C.CString(output) |
| | | defer C.free(unsafe.Pointer(out)) |
| | | csid := C.CString(sid) |
| | |
| | | if audio { |
| | | a = 1 |
| | | } |
| | | C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd), C.int(a)) |
| | | C.wrap_fn_recorder(unsafe.Pointer(libcffmpeg), h.ffmpeg, csid, out, C.long(id), C.int(mind), C.int(maxd), C.int(a)) |
| | | } |
| | | |
| | | // GetInfoRecorder info |
| | |
| | | var p *C.char |
| | | var pl C.int |
| | | |
| | | C.wrap_fn_info_recorder(h.ffmpeg, &i, &id, &idl, &p, &pl) |
| | | C.wrap_fn_info_recorder(unsafe.Pointer(libcffmpeg), h.ffmpeg, &i, &id, &idl, &p, &pl) |
| | | // if p == nil { |
| | | // return -1, "" |
| | | // } |
| | |
| | | |
| | | // SetRecDurationForCache cache |
| | | func (h *GoFFMPEG) SetRecDurationForCache(min, max int) { |
| | | C.wrap_fn_rec_duration(h.ffmpeg, C.int(min), C.int(max)) |
| | | C.wrap_fn_rec_duration(unsafe.Pointer(libcffmpeg), h.ffmpeg, C.int(min), C.int(max)) |
| | | } |
| | |
| | | var key C.int |
| | | var size C.int |
| | | |
| | | p := C.wrap_fn_get_avpacket(h.ffmpeg, &size, &key) |
| | | p := C.wrap_fn_get_avpacket(unsafe.Pointer(libcffmpeg), h.ffmpeg, &size, &key) |
| | | if size <= 0 { |
| | | return nil, 0, -1 |
| | | } |
| | |
| | | libcffmpeg init_libcffmpeg(const char *so_file){ |
| | | libcffmpeg lib = dlopen(so_file, RTLD_LAZY); |
| | | if(lib){ |
| | | fn_create = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create"); |
| | | release_if_err(fn_create, lib); |
| | | fn_create2 = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create2"); |
| | | release_if_err(fn_create2, lib); |
| | | |
| | | fn_destroy = (lib_cffmpeg_destroy)dlsym(lib, "c_ffmpeg_destroy"); |
| | | release_if_err(fn_destroy, lib); |
| | | |
| | | fn_run = (lib_cffmpeg_run)dlsym(lib, "c_ffmpeg_run"); |
| | | release_if_err(fn_run, lib); |
| | | fn_gb28181 = (lib_cffmpeg_gb28181)dlsym(lib, "c_ffmpeg_run_gb28181"); |
| | | release_if_err(fn_gb28181, lib); |
| | | |
| | | fn_cpu = (lib_cffmpeg_cpu)dlsym(lib, "c_ffmepg_use_cpu"); |
| | | release_if_err(fn_cpu, lib); |
| | | |
| | | fn_rec_duration = (lib_cffmpeg_rec_duration)dlsym(lib, "c_ffmpeg_set_record_duration"); |
| | | release_if_err(fn_rec_duration, lib); |
| | | fn_recorder = (lib_cffmpeg_recorder)dlsym(lib, "c_ffmpeg_build_recorder"); |
| | | release_if_err(fn_recorder, lib); |
| | | fn_fire_recorder = (lib_cffmpeg_fire_recorder)dlsym(lib, "c_ffmpeg_fire_recorder"); |
| | | release_if_err(fn_fire_recorder, lib); |
| | | fn_info_recorder = (lib_cffmpeg_info_recorder)dlsym(lib, "c_ffmpeg_get_info_recorder"); |
| | | release_if_err(fn_info_recorder, lib); |
| | | |
| | | fn_decoder = (lib_cffmpeg_decoder)dlsym(lib, "c_ffmpeg_build_decoder"); |
| | | release_if_err(fn_decoder, lib); |
| | | fn_decoder_pic = (lib_cffmpeg_pic)dlsym(lib, "c_ffmpeg_get_pic_decoder"); |
| | | release_if_err(fn_decoder_pic, lib); |
| | | |
| | | fn_get_avpacket = (lib_cffmpeg_avpacket)dlsym(lib, "c_ffmpeg_get_avpacket"); |
| | | release_if_err(fn_get_avpacket, lib); |
| | | |
| | | fn_decode = (lib_cffmpeg_decode)dlsym(lib, "c_ffmpeg_decode"); |
| | | release_if_err(fn_decode, lib); |
| | | |
| | | fn_create_encoder = (lib_cffmpeg_create_encoder)dlsym(lib, "c_ffmpeg_create_encoder"); |
| | | release_if_err(fn_create_encoder, lib); |
| | | fn_destroy_encoder = (lib_cffmpeg_destroy_encoder)dlsym(lib, "c_ffmpeg_destroy_encoder"); |
| | | release_if_err(fn_destroy_encoder, lib); |
| | | fn_encode = (lib_cffmpeg_encode)dlsym(lib, "c_ffmpeg_encode"); |
| | | release_if_err(fn_encode, lib); |
| | | |
| | | fn_create_conv = (lib_cffmpeg_create_conv)dlsym(lib, "c_ffmpeg_create_conv"); |
| | | release_if_err(fn_create_conv, lib); |
| | | fn_destroy_conv = (lib_cffmpeg_destroy_conv)dlsym(lib, "c_ffmpeg_destroy_conv"); |
| | | release_if_err(fn_destroy_conv, lib); |
| | | fn_conv = (lib_cffmpeg_conv)dlsym(lib, "c_ffmpeg_conv"); |
| | | release_if_err(fn_conv, lib); |
| | | |
| | | fn_gpu_conv = (lib_gpu_conv)dlsym(lib, "c_gpu_conv"); |
| | | release_if_err(fn_gpu_conv, lib); |
| | | |
| | | }else{ |
| | | printf("dlopen - %s\n", dlerror()); |
| | |
| | | } |
| | | } |
| | | |
| | | cffmpeg wrap_fn_create(){ |
| | | cffmpeg wrap_fn_create(void *lib){ |
| | | if (!fn_create){ |
| | | fn_create = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create"); |
| | | release_if_err(fn_create, lib); |
| | | } |
| | | |
| | | return fn_create(); |
| | | } |
| | | |
| | | cffmpeg wrap_fn_create2(const char *logfile){ |
| | | cffmpeg wrap_fn_create2(void *lib, const char *logfile){ |
| | | if (!fn_create2){ |
| | | fn_create2 = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create2"); |
| | | release_if_err(fn_create2, lib); |
| | | } |
| | | return fn_create2(logfile); |
| | | } |
| | | |
| | | void wrap_fn_destroy(const cffmpeg h){ |
| | | void wrap_fn_destroy(void *lib, const cffmpeg h){ |
| | | fn_destroy(h); |
| | | } |
| | | |
| | | void wrap_fn_run(const cffmpeg h, const char* input){ |
| | | void wrap_fn_run(void *lib, const cffmpeg h, const char* input){ |
| | | if (!fn_run){ |
| | | fn_run = (lib_cffmpeg_run)dlsym(lib, "c_ffmpeg_run"); |
| | | if (!fn_run) return; |
| | | } |
| | | |
| | | fn_run(h, input); |
| | | } |
| | | |
| | | void wrap_fn_run_gb28181(const cffmpeg h){ |
| | | int wrap_fn_fps(void *lib, const cffmpeg h){ |
| | | if(!fn_fps){ |
| | | fn_fps = (lib_cffmpeg_fps)dlsym(lib, "c_ffmpeg_get_fps"); |
| | | if (!fn_fps) return 25; |
| | | } |
| | | return fn_fps(h); |
| | | } |
| | | |
| | | void wrap_fn_run_gb28181(void *lib, const cffmpeg h){ |
| | | if (!fn_gb28181){ |
| | | fn_gb28181 = (lib_cffmpeg_gb28181)dlsym(lib, "c_ffmpeg_run_gb28181"); |
| | | if (!fn_gb28181) return; |
| | | } |
| | | fn_gb28181(h); |
| | | } |
| | | |
| | | void wrap_fn_use_cpu(const cffmpeg h){ |
| | | void wrap_fn_use_cpu(void *lib, const cffmpeg h){ |
| | | if (!fn_cpu){ |
| | | fn_cpu = (lib_cffmpeg_cpu)dlsym(lib, "c_ffmepg_use_cpu"); |
| | | if (!fn_cpu) return; |
| | | } |
| | | fn_cpu(h); |
| | | } |
| | | |
| | | 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_recorder(void *lib, const cffmpeg h, const char* id, const char* dir, const int64_t fid, int mind, int maxd, int audio){ |
| | | if (!fn_recorder){ |
| | | fn_recorder = (lib_cffmpeg_recorder)dlsym(lib, "c_ffmpeg_build_recorder"); |
| | | if (!fn_recorder) return; |
| | | } |
| | | fn_recorder(h, id, dir, fid, mind, maxd, audio); |
| | | } |
| | | |
| | | void wrap_fn_rec_duration(const cffmpeg h, const int min, const int max){ |
| | | void wrap_fn_rec_duration(void *lib, const cffmpeg h, const int min, const int max){ |
| | | if (!fn_rec_duration){ |
| | | fn_rec_duration = (lib_cffmpeg_rec_duration)dlsym(lib, "c_ffmpeg_set_record_duration"); |
| | | if (!fn_rec_duration) return; |
| | | } |
| | | fn_rec_duration(h, min, max); |
| | | } |
| | | |
| | | void wrap_fn_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){ |
| | | void wrap_fn_fire_recorder(void *lib, const cffmpeg h, const char* sid, const int64_t id){ |
| | | if (!fn_fire_recorder){ |
| | | fn_fire_recorder = (lib_cffmpeg_fire_recorder)dlsym(lib, "c_ffmpeg_fire_recorder"); |
| | | if (!fn_fire_recorder) return; |
| | | } |
| | | fn_fire_recorder(h, sid, id); |
| | | } |
| | | |
| | | void wrap_fn_info_recorder(const cffmpeg h, int* index, char** recid, int* recidLen, char** fpath, int* pathLen){ |
| | | void wrap_fn_info_recorder(void *lib, const cffmpeg h, int* index, char** recid, int* recidLen, char** fpath, int* pathLen){ |
| | | if (!fn_info_recorder){ |
| | | fn_info_recorder = (lib_cffmpeg_info_recorder)dlsym(lib, "c_ffmpeg_get_info_recorder"); |
| | | if (!fn_info_recorder) return; |
| | | } |
| | | return fn_info_recorder(h, index, recid, recidLen, fpath, pathLen); |
| | | } |
| | | |
| | | void wrap_fn_decoder(const cffmpeg h){ |
| | | void wrap_fn_decoder(void *lib, const cffmpeg h){ |
| | | if (!fn_decoder){ |
| | | fn_decoder = (lib_cffmpeg_decoder)dlsym(lib, "c_ffmpeg_build_decoder"); |
| | | if (!fn_decoder) return; |
| | | } |
| | | fn_decoder(h); |
| | | } |
| | | |
| | | void* wrap_fn_decoder_pic(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id){ |
| | | void* wrap_fn_decoder_pic(void *lib, const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id){ |
| | | if (!fn_decoder_pic){ |
| | | fn_decoder_pic = (lib_cffmpeg_pic)dlsym(lib, "c_ffmpeg_get_pic_decoder"); |
| | | release_if_err(fn_decoder_pic, lib); |
| | | } |
| | | return fn_decoder_pic(h, wid, hei, format, length, id); |
| | | } |
| | | |
| | | void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key){ |
| | | void* wrap_fn_get_avpacket(void *lib, const cffmpeg h, int* size, int* key){ |
| | | if(!fn_get_avpacket){ |
| | | fn_get_avpacket = (lib_cffmpeg_avpacket)dlsym(lib, "c_ffmpeg_get_avpacket"); |
| | | release_if_err(fn_get_avpacket, lib); |
| | | } |
| | | return fn_get_avpacket(h, size, key); |
| | | } |
| | | |
| | | // return val: -1 open error; -2, find stream error; -3, converter create error |
| | | void* wrap_fn_decode(const char* file, const int gb, int* wid, int* hei){ |
| | | void* wrap_fn_decode(void *lib, const char* file, const int gb, int* wid, int* hei){ |
| | | if (!fn_decode){ |
| | | fn_decode = (lib_cffmpeg_decode)dlsym(lib, "c_ffmpeg_decode"); |
| | | release_if_err(fn_decode, lib); |
| | | } |
| | | return fn_decode(file, gb, wid, hei); |
| | | } |
| | | |
| | | void* wran_fn_gpu_conv(void *in, const int w, const int h, const int dst_w, const int dst_h, int *length){ |
| | | return fn_gpu_conv(in, w, h, dst_w, dst_h, length); |
| | | } |
| | | |
| | | // for encoder |
| | | cencoder wrap_fn_create_encoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi){ |
| | | cencoder wrap_fn_create_encoder(void *lib, const int w, const int h, const int fps, const int br, const int scale_flag, const int gi){ |
| | | if (!fn_create_encoder){ |
| | | fn_create_encoder = (lib_cffmpeg_create_encoder)dlsym(lib, "c_ffmpeg_create_encoder"); |
| | | release_if_err(fn_create_encoder, lib); |
| | | } |
| | | return fn_create_encoder(w, h, fps, br, scale_flag, gi); |
| | | } |
| | | |
| | | void wrap_fn_destroy_encoder(const cencoder h){ |
| | | void wrap_fn_destroy_encoder(void *lib, const cencoder h){ |
| | | if (!fn_destroy_encoder){ |
| | | fn_destroy_encoder = (lib_cffmpeg_destroy_encoder)dlsym(lib, "c_ffmpeg_destroy_encoder"); |
| | | if(!fn_destroy_encoder) return; |
| | | } |
| | | fn_destroy_encoder(h); |
| | | } |
| | | |
| | | void* wrap_fn_encode(cencoder hdl, void *in, const int w, const int h, int *out_size, int *key){ |
| | | void* wrap_fn_encode(void *lib, cencoder hdl, void *in, const int w, const int h, int *out_size, int *key){ |
| | | if (!fn_encode){ |
| | | fn_encode = (lib_cffmpeg_encode)dlsym(lib, "c_ffmpeg_encode"); |
| | | release_if_err(fn_encode, lib); |
| | | } |
| | | |
| | | uint8_t *out = NULL; |
| | | const int flag = fn_encode(hdl, (uint8_t*)in, w, h, &out, out_size, key); |
| | | if (flag > 0 && out != NULL) { |
| | |
| | | } |
| | | |
| | | // for conv |
| | | cconv wrap_fn_create_conv(const int srcW, const int srcH, const int srcFormat, |
| | | cconv wrap_fn_create_conv(void *lib, const int srcW, const int srcH, const int srcFormat, |
| | | const int dstW, const int dstH, const int dstFormat, const int flag){ |
| | | if (!fn_create_conv){ |
| | | fn_create_conv = (lib_cffmpeg_create_conv)dlsym(lib, "c_ffmpeg_create_conv"); |
| | | release_if_err(fn_create_conv, lib); |
| | | } |
| | | return fn_create_conv(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flag); |
| | | } |
| | | |
| | | void wrap_fn_destroy_conv(const cconv h){ |
| | | void wrap_fn_destroy_conv(void *lib, const cconv h){ |
| | | if (!fn_destroy_conv){ |
| | | fn_destroy_conv = (lib_cffmpeg_destroy_conv)dlsym(lib, "c_ffmpeg_destroy_conv"); |
| | | if(!fn_destroy_conv) return; |
| | | } |
| | | fn_destroy_conv(h); |
| | | } |
| | | void* wrap_fn_conv(const cconv h, uint8_t *in){ |
| | | |
| | | void* wrap_fn_conv(void *lib, const cconv h, uint8_t *in){ |
| | | if (!fn_conv){ |
| | | fn_conv = (lib_cffmpeg_conv)dlsym(lib, "c_ffmpeg_conv"); |
| | | release_if_err(fn_conv, lib); |
| | | } |
| | | |
| | | return fn_conv(h, in); |
| | | } |
| | |
| | | typedef cffmpeg(*lib_cffmpeg_create2)(const char*); |
| | | typedef void (*lib_cffmpeg_destroy)(const cffmpeg); |
| | | typedef void (*lib_cffmpeg_run)(const cffmpeg, const char*); |
| | | typedef int (*lib_cffmpeg_fps)(const cffmpeg); |
| | | typedef void (*lib_cffmpeg_gb28181)(const cffmpeg); |
| | | typedef void (*lib_cffmpeg_cpu)(const cffmpeg); |
| | | typedef void (*lib_cffmpeg_rec_duration)(const cffmpeg, const int, const int); |
| | | typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, int, int, int); |
| | | typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, const int64_t, 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); |
| | | typedef void*(*lib_cffmpeg_pic)(const cffmpeg, int*, int*, int*, int*, int64_t*); |
| | | typedef void*(*lib_cffmpeg_avpacket)(const cffmpeg, int*, int*); |
| | | typedef void*(*lib_cffmpeg_decode)(const char*, const int, int*, int*); |
| | | typedef void*(*lib_gpu_conv)(void*, const int, const int, const int, const int, int *); |
| | | |
| | | static lib_cffmpeg_create fn_create = NULL; |
| | | static lib_cffmpeg_create2 fn_create2 = NULL; |
| | | static lib_cffmpeg_destroy fn_destroy = NULL; |
| | | static lib_cffmpeg_run fn_run = NULL; |
| | | static lib_cffmpeg_fps fn_fps = NULL; |
| | | static lib_cffmpeg_gb28181 fn_gb28181 = NULL; |
| | | static lib_cffmpeg_cpu fn_cpu = NULL; |
| | | static lib_cffmpeg_rec_duration fn_rec_duration = NULL; |
| | |
| | | static lib_cffmpeg_pic fn_decoder_pic = NULL; |
| | | static lib_cffmpeg_avpacket fn_get_avpacket = NULL; |
| | | static lib_cffmpeg_decode fn_decode = NULL; |
| | | static lib_gpu_conv fn_gpu_conv = NULL; |
| | | |
| | | typedef void* libcffmpeg; |
| | | libcffmpeg init_libcffmpeg(const char *so_file); |
| | | void release_libcffmpeg(libcffmpeg lib); |
| | | |
| | | cffmpeg wrap_fn_create(); |
| | | cffmpeg wrap_fn_create2(const char *logfile); |
| | | void wrap_fn_destroy(const cffmpeg h); |
| | | void wrap_fn_run(const cffmpeg h, const char* input); |
| | | void wrap_fn_run_gb28181(const cffmpeg h); |
| | | void wrap_fn_use_cpu(const cffmpeg h); |
| | | void wrap_fn_rec_duration(const cffmpeg h, const int min, const int max); |
| | | 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); |
| | | void* wrap_fn_decoder_pic(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id); |
| | | void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key); |
| | | void* wrap_fn_decode(const char* file, const int gb, int* wid, int* hei); |
| | | void* wran_fn_gpu_conv(void *in, const int w, const int h, const int dst_w, const int dst_h, int *length); |
| | | cffmpeg wrap_fn_create(void *lib); |
| | | cffmpeg wrap_fn_create2(void *lib, const char *logfile); |
| | | void wrap_fn_destroy(void *lib, const cffmpeg h); |
| | | void wrap_fn_run(void *lib, const cffmpeg h, const char* input); |
| | | int wrap_fn_fps(void *lib, const cffmpeg h); |
| | | void wrap_fn_run_gb28181(void *lib, const cffmpeg h); |
| | | void wrap_fn_use_cpu(void *lib, const cffmpeg h); |
| | | void wrap_fn_rec_duration(void *lib, const cffmpeg h, const int min, const int max); |
| | | void wrap_fn_recorder(void *lib, const cffmpeg h, const char* id, const char* dir, const int64_t fid, int mind, int maxd, int audio); |
| | | void wrap_fn_fire_recorder(void *lib, const cffmpeg h, const char *sid, const int64_t id); |
| | | void wrap_fn_info_recorder(void *lib, const cffmpeg, int* index, char** recid, int* recidLen, char** fpath, int* pathLen); |
| | | void wrap_fn_decoder(void *lib, const cffmpeg h); |
| | | void* wrap_fn_decoder_pic(void *lib, const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id); |
| | | void* wrap_fn_get_avpacket(void *lib, const cffmpeg h, int* size, int* key); |
| | | void* wrap_fn_decode(void *lib, const char* file, const int gb, int* wid, int* hei); |
| | | // for encoder |
| | | typedef void* cencoder; |
| | | typedef cencoder (*lib_cffmpeg_create_encoder)(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi); |
| | |
| | | static lib_cffmpeg_destroy_encoder fn_destroy_encoder = NULL; |
| | | static lib_cffmpeg_encode fn_encode = NULL; |
| | | |
| | | cencoder wrap_fn_create_encoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi); |
| | | void wrap_fn_destroy_encoder(const cencoder h); |
| | | void* wrap_fn_encode(cencoder hdl, void *in, const int w, const int h, int *out_size, int *key); |
| | | cencoder wrap_fn_create_encoder(void *lib, const int w, const int h, const int fps, const int br, const int scale_flag, const int gi); |
| | | void wrap_fn_destroy_encoder(void *lib, const cencoder h); |
| | | void* wrap_fn_encode(void *lib, cencoder hdl, void *in, const int w, const int h, int *out_size, int *key); |
| | | |
| | | |
| | | // for conv |
| | |
| | | static lib_cffmpeg_destroy_conv fn_destroy_conv = NULL; |
| | | static lib_cffmpeg_conv fn_conv = NULL; |
| | | |
| | | cconv wrap_fn_create_conv(const int srcW, const int srcH, const int srcFormat, |
| | | cconv wrap_fn_create_conv(void *lib, const int srcW, const int srcH, const int srcFormat, |
| | | const int dstW, const int dstH, const int dstFormat, const int flag); |
| | | void wrap_fn_destroy_conv(const cconv h); |
| | | void* wrap_fn_conv(const cconv h, uint8_t *in); |
| | | void wrap_fn_destroy_conv(void *lib, const cconv h); |
| | | void* wrap_fn_conv(void *lib, const cconv h, uint8_t *in); |
| | | |
| | | #ifdef __cplusplus |
| | | } |