| | |
| | | io_ctx_ = NULL; |
| | | } |
| | | if(ctx_){ |
| | | avformat_close_input(&ctx_); |
| | | avformat_free_context(ctx_); |
| | | if (!ctx_->oformat){ |
| | | avformat_free_context(ctx_); |
| | | }else{ |
| | | avformat_close_input(&ctx_); |
| | | } |
| | | ctx_ = NULL; |
| | | if(dec_ctx_){ |
| | | avcodec_close(dec_ctx_); |
| | |
| | | auto err = av_probe_input_buffer(ctx_->pb, &ctx_->iformat, NULL, NULL, 0, read_io_buff_size_); |
| | | if(err != 0){ |
| | | logIt("open with custom io prob input buffer error:%d\n", err); |
| | | logIt("failed:%s", getAVErrorDesc(err).c_str()); |
| | | logIt("custom io failed:%s", getAVErrorDesc(err).c_str()); |
| | | return -1; |
| | | } |
| | | |
| | |
| | | int ret = openWithCustomIO(handle_gb28181, handle_gb28181->readData, options); |
| | | if(ret < 0){ |
| | | logIt("do openWithCustomIO failed:%d",ret); |
| | | } |
| | | }else{ |
| | | ret = avformat_open_input(&ctx_, "", NULL, options); |
| | | } |
| | | |
| | | ret = avformat_open_input(&ctx_, "", NULL, options); |
| | | // if(ret < 0){ |
| | | // logIt("open %s failed:%s",filename, |
| | | // getAVErrorDesc(ret).c_str()); |
| | |
| | | #include "../ffmpeg/bridge/cvbridge.hpp" |
| | | #include "../ffmpeg/format/FormatIn.hpp" |
| | | #include "../ffmpeg/data/CodedData.hpp" |
| | | #include "../ffmpeg/data/FrameData.hpp" |
| | | #include "../ffmpeg/log/log.hpp" |
| | | |
| | | extern "C"{ |
| | |
| | | ,conv_h_(h) |
| | | ,conv_flag_(f) |
| | | ,decRef_(dec) |
| | | ,thread_(nullptr) |
| | | ,stop_{false} |
| | | {} |
| | | |
| | | decoder::~decoder(){ |
| | | if (thread_){ |
| | | stop_.store(true); |
| | | thread_->join(); |
| | | } |
| | | |
| | | if (conv_){ |
| | | delete conv_; |
| | | } |
| | | |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> l(mutex_pkt_); |
| | | list_pkt_.clear(); |
| | | } |
| | | |
| | | { |
| | |
| | | return list_pic_.size(); |
| | | } |
| | | |
| | | void decoder::Start(){ |
| | | if (thread_) return; |
| | | thread_.reset(new std::thread([&]{ |
| | | if (initDecoder() != 0) { |
| | | return; |
| | | } |
| | | |
| | | while(!stop_.load()){ |
| | | |
| | | std::unique_lock<std::mutex> locker(mutex_pkt_); |
| | | cv_.wait(locker, [&]{ |
| | | return !list_pkt_.empty() || stop_.load(); |
| | | }); |
| | | if (stop_.load()){ |
| | | break; |
| | | } |
| | | |
| | | auto pkt = list_pkt_.front(); |
| | | list_pkt_.pop_front(); |
| | | |
| | | AVFrame *frame = av_frame_alloc(); |
| | | AVPacket np(pkt.data->getAVPacket()); |
| | | av_copy_packet(&np, &pkt.data->getAVPacket()); |
| | | |
| | | auto ret = decRef_->decode(frame, &np); |
| | | av_packet_unref(&np); |
| | | |
| | | if (ret == 0){ |
| | | saveFrame(frame, pkt.id); |
| | | } |
| | | av_frame_free(&frame); |
| | | } |
| | | |
| | | })); |
| | | } |
| | | |
| | | int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | |
| | | if (!data) return -1; |
| | | if (decRef_->isAudioPkt(&data->getAVPacket())) return -2; |
| | | |
| | | // if (!thread_){ |
| | | // if (initDecoder() != 0) return -3; |
| | | // Start(); |
| | | // } |
| | | |
| | | // std::lock_guard<std::mutex> l(mutex_pkt_); |
| | | // list_pkt_.push_back({data, id}); |
| | | // cv_.notify_one(); |
| | | // return list_pkt_.size(); |
| | | |
| | | if (!conv_){ |
| | | if (initDecoder() != 0) return -3; |
| | | } |
| | |
| | | saveFrame(frame, id); |
| | | } |
| | | av_frame_free(&frame); |
| | | |
| | | } |
| | | |
| | | void decoder::GetFrame(unsigned char **data, int *w, int *h, int64_t *id){ |
| | |
| | | #include <atomic> |
| | | #include <condition_variable> |
| | | |
| | | #include "../common.hpp" |
| | | |
| | | struct AVFrame; |
| | | |
| | | namespace ffwrapper |
| | | { |
| | | class FormatIn; |
| | | class cvbridge; |
| | | |
| | | class CodedData; |
| | | } // namespace ffwrapper |
| | | |
| | | namespace cffmpeg_wrap |
| | |
| | | std::list<BGR24> list_pic_; |
| | | std::mutex mutex_pic_; |
| | | |
| | | std::unique_ptr<std::thread> thread_; |
| | | std::atomic_bool stop_; |
| | | |
| | | std::list<CPacket> list_pkt_; |
| | | std::mutex mutex_pkt_; |
| | | std::condition_variable cv_; |
| | | private: |
| | | int initDecoder(); |
| | | int saveFrame(AVFrame *frame, int64_t &id); |
| | |
| | | ,audio_(false) |
| | | ,gb_(0) |
| | | ,cpu_(0) |
| | | ,run_dec_(false) |
| | | ,thread_(nullptr) |
| | | ,stop_stream_(false) |
| | | ,stream_(nullptr) |
| | |
| | | decoder_ = new decoder(in, scale_w_, scale_h_, scale_f_); |
| | | |
| | | rec_->Load(in); |
| | | if(fn_rec_lazy_) fn_rec_lazy_(in); |
| | | if(fn_rec_lazy_) { |
| | | fn_rec_lazy_(); |
| | | fn_rec_lazy_ = nullptr; |
| | | } |
| | | } |
| | | |
| | | void Wrapper::run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | |
| | | if (stream_) stream_->SetPacket(data, id); |
| | | if (decoder_ && run_dec_) decoder_->SetFrame(data, id); |
| | | if (rec_->Loaded()) rec_->SetPacket(data, id); |
| | | if (decoder_) decoder_->SetFrame(data, id); |
| | | } |
| | | |
| | | void Wrapper::deinit_worker(){ |
| | |
| | | }else{ |
| | | std::string rid(id), dir(output); |
| | | fn_rec_lazy_ = |
| | | [=](ffwrapper::FormatIn *in){rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur, audio);}; |
| | | [=]{rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur, audio);}; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | ////////decoder |
| | | void Wrapper::BuildDecoder(){ |
| | | // use_decoder_ = true; |
| | | run_dec_ = true; |
| | | } |
| | | |
| | | void Wrapper::GetPicDecoder(unsigned char **data, int *w, int *h, int64_t *id){ |
| | |
| | | decoder_->GetFrame(data, w, h, id); |
| | | } |
| | | } |
| | | |
| | | |
| | | void Wrapper::GetPacket(unsigned char **pktData, int *size, int *key){ |
| | | if (stream_){ |
| | | stream_->GetPacket(pktData, size, key); |
| | |
| | | |
| | | uint8_t *pic = NULL; |
| | | *w = *h = 0; |
| | | |
| | | |
| | | int tryTime = 0; |
| | | while (tryTime++ < 100){ |
| | | |
| | |
| | | int scale_w_, scale_h_, scale_f_; |
| | | bool audio_; |
| | | int gb_, cpu_; |
| | | bool run_dec_; |
| | | // decoder 参数 |
| | | std::unique_ptr<std::thread> thread_; |
| | | std::atomic_bool stop_stream_; |
| | |
| | | // 录像类,一直存在 |
| | | rec* rec_; |
| | | // 录像请求缓存,等待runstream后添加 |
| | | std::function<void(ffwrapper::FormatIn*)> fn_rec_lazy_; |
| | | std::function<void()> fn_rec_lazy_; |
| | | }; |
| | | |
| | | uint8_t* Decode(const char *file, const int gb, int *w, int *h); |