| | |
| | | #include <libavformat/avformat.h> |
| | | #include <libavutil/opt.h> |
| | | #include <libswscale/swscale.h> |
| | | #include <libavcodec/avcodec.h> |
| | | } |
| | | |
| | | using namespace ffwrapper; |
| | |
| | | ,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_pic_); |
| | | for(auto &i : list_pic_){ |
| | | free(i.data); |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> l(mutex_pkt_); |
| | | list_pkt_.clear(); |
| | | } |
| | | list_pic_.clear(); |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> l(mutex_pic_); |
| | | for(auto &i : list_pic_){ |
| | | free(i.data); |
| | | } |
| | | list_pic_.clear(); |
| | | } |
| | | } |
| | | |
| | | int decoder::initDecoder(){ |
| | |
| | | if(decRef_->getCodecContext() == NULL){ |
| | | |
| | | bool flag = true; |
| | | flag = decRef_->openCodec(AVMEDIA_TYPE_VIDEO, NULL); |
| | | flag = decRef_->openCodec(NULL); |
| | | auto dec_ctx = decRef_->getCodecContext(); |
| | | if(conv_){ |
| | | delete conv_; |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ |
| | | if (!data) return -1; |
| | | if (decRef_->isAudioPkt(data->getAVPacket())) return -2; |
| | | |
| | | if (!conv_){ |
| | | initDecoder(); |
| | | } |
| | | auto frame(std::make_shared<FrameData>()); |
| | | auto ret = decRef_->decode(frame, data); |
| | | if(ret == 1){ |
| | | //缓存数据 |
| | | BGR24 pic; |
| | | AVFrame *frm = frame->getAVFrame(); |
| | | pic.w = conv_w_; |
| | | pic.h = conv_h_; |
| | | unsigned char *picData = (unsigned char*)malloc(pic.w * pic.h * 3); |
| | | conv_->copyPicture(picData, frm); |
| | | pic.data = picData; |
| | | pic.id = id; |
| | | |
| | | std::lock_guard<std::mutex> l(mutex_pic_); |
| | | while(list_pic_.size() > 10){ |
| | | for(int i = 0; i < 5; i++){ |
| | | auto t = list_pic_.front(); |
| | | free(t.data); |
| | | list_pic_.pop_front(); |
| | | } |
| | | int decoder::saveFrame(AVFrame *frame, int64_t &id){ |
| | | //缓存数据 |
| | | BGR24 pic; |
| | | AVFrame *frm = frame; |
| | | pic.w = conv_w_; |
| | | pic.h = conv_h_; |
| | | unsigned char *picData = (unsigned char*)malloc(pic.w * pic.h * 3); |
| | | conv_->copyPicture(picData, frm); |
| | | pic.data = picData; |
| | | pic.id = id; |
| | | std::lock_guard<std::mutex> l(mutex_pic_); |
| | | while(list_pic_.size() > 50){ |
| | | for(int i = 0; i < 12; i++){ |
| | | auto t = list_pic_.front(); |
| | | free(t.data); |
| | | list_pic_.pop_front(); |
| | | } |
| | | list_pic_.emplace_back(pic); |
| | | |
| | | } |
| | | list_pic_.emplace_back(pic); |
| | | 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; |
| | | } |
| | | |
| | | AVFrame *frame = av_frame_alloc(); |
| | | AVPacket np(data->getAVPacket()); |
| | | av_copy_packet(&np, &data->getAVPacket()); |
| | | auto ret = decRef_->decode(frame, &np); |
| | | av_packet_unref(&np); |
| | | |
| | | if (ret == 0){ |
| | | saveFrame(frame, id); |
| | | } |
| | | av_frame_free(&frame); |
| | | |
| | | } |
| | | |
| | | void decoder::GetFrame(unsigned char **data, int *w, int *h, int64_t *id){ |
| | | std::lock_guard<std::mutex> l(mutex_pic_); |
| | | if(list_pic_.empty()){ |