#include "decoder.hpp" #include "../ffmpeg/bridge/cvbridge.hpp" #include "../ffmpeg/format/FormatIn.hpp" #include "../ffmpeg/data/CodedData.hpp" #include "../ffmpeg/log/log.hpp" #include "../common.hpp" extern "C"{ #include #include #include #include } using namespace ffwrapper; using namespace logif; namespace cffmpeg_wrap { decoder::decoder(ffwrapper::FormatIn *dec) :decRef_(dec) {} decoder::~decoder(){ std::lock_guard l(mutex_frm_); for(auto i : list_frm_){ free(i.data); } list_frm_.clear(); } int decoder::initDecoder(){ if (!decRef_) return -1; if(decRef_->getCodecContext() == NULL){ bool flag = true; flag = decRef_->openCodec(NULL); if (!flag){ logIt("FormatIn openCodec Failed!"); return -1; } } return 0; } int decoder::saveFrame(AVFrame *frame, const int64_t &id){ FRM frm; frm.width = frame->width; frm.height = frame->height; frm.format = frame->format; frm.id = id; frm.data = cvbridge::extractFrame(frame, &frm.length); std::lock_guard l(mutex_frm_); while(list_frm_.size() > 50){ for(int i = 0; i < 12; i++){ auto t = list_frm_.front(); free(t.data); list_frm_.pop_front(); } } if (!frm.data) return 0; list_frm_.push_back(frm); return list_frm_.size(); } int decoder::SetFrame(const CPacket &pkt){ auto data = pkt.data; if (!data) return -10; if (!decRef_->isVideoPkt(&data->getAVPacket())) return -20; if (decRef_->getCodecContext() == NULL){ if (initDecoder() != 0) return -30; } 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, pkt.v_id); } av_frame_free(&frame); return ret; } void decoder::GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id){ std::lock_guard l(mutex_frm_); if(list_frm_.empty()){ *data = NULL; *w = *h = 0; *id = -1; return; } auto p = list_frm_.front(); list_frm_.pop_front(); *data = p.data; *id = p.id; *w = p.width; *h = p.height; *format = p.format; *length = p.length; } } // namespace cffmpeg_wrap