#include "decoder.hpp" #include "../ffmpeg/bridge/cvbridge.hpp" #include "../ffmpeg/format/FormatIn.hpp" #include "../ffmpeg/data/CodedData.hpp" #include "../ffmpeg/log/log.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_){ av_frame_free(&i.frm); } 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, int64_t &id){ while(list_frm_.size() > 50){ for(int i = 0; i < 12; i++){ auto t = list_frm_.front(); av_frame_free(&t.frm); list_frm_.pop_front(); } } list_frm_.push_back({frame,id}); return list_frm_.size(); } int decoder::SetFrame(std::shared_ptr data, int64_t &id){ if (!data) return -1; if (!decRef_->isVideoPkt(&data->getAVPacket())) return -2; if (decRef_->getCodecContext() == NULL){ 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); } } void decoder::GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id){ AVFrame *frm = NULL; { 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(); frm = p.frm; *id = p.id; *w = frm->width; *h = frm->height; *format = frm->format; } *length = avpicture_get_size((enum AVPixelFormat)frm->format, frm->width, frm->height); if (*length <= 0){ logIt("get raw frame data error"); *data = NULL; *w = *h = 0; *id = -1; return; } unsigned char *picData = (unsigned char*)malloc(*length); auto ret = avpicture_layout((const AVPicture*)frm, (enum AVPixelFormat)frm->format, frm->width, frm->height, picData, *length); av_frame_free(&frm); if (ret < 0){ *data = NULL; *w = *h = 0; *id = -1; free(picData); return; } *data = picData; } } // namespace cffmpeg_wrap