| | |
| | | |
| | | #include <stdexcept> |
| | | #include <unistd.h> |
| | | #include <stdlib.h> |
| | | #include <time.h> |
| | | |
| | | extern "C"{ |
| | | #include <libavformat/avformat.h> |
| | |
| | | #include <libavutil/opt.h> |
| | | #include <libavutil/avassert.h> |
| | | #include <libavutil/imgutils.h> |
| | | #include <libswscale/swscale.h> |
| | | #include <libswscale/swscale.h> |
| | | } |
| | | |
| | | #include "../log/log.hpp" |
| | |
| | | ,dec_ctx_(NULL) |
| | | ,vs_idx_(-1) |
| | | ,as_idx_(-1) |
| | | ,prop_(NULL) |
| | | ,hw_accl_(hw) |
| | | ,io_ctx_(NULL) |
| | | ,read_io_buff_(NULL) |
| | |
| | | ,fps_(25.0) |
| | | {} |
| | | |
| | | FormatIn::FormatIn(const VideoProp &prop, bool hw/*=true*/) |
| | | :ctx_(NULL) |
| | | ,dec_ctx_(NULL) |
| | | ,vs_idx_(-1) |
| | | ,as_idx_(-1) |
| | | ,prop_(NULL) |
| | | ,hw_accl_(hw) |
| | | ,io_ctx_(NULL) |
| | | ,read_io_buff_(NULL) |
| | | ,read_io_buff_size_(32768) |
| | | ,handle_gb28181(NULL) |
| | | ,fps_(25.0) |
| | | { |
| | | prop_ = new VideoProp; |
| | | *prop_ = prop; |
| | | } |
| | | |
| | | FormatIn::~FormatIn() |
| | | { |
| | | logIt("free format in"); |
| | | if (prop_) delete prop_; |
| | | |
| | | if(dec_ctx_){ |
| | | avcodec_close(dec_ctx_); |
| | | avcodec_free_context(&dec_ctx_); |
| | |
| | | avformat_close_input(&ctx_); |
| | | ctx_ = NULL; |
| | | } |
| | | |
| | | |
| | | if (handle_gb28181){ |
| | | delete handle_gb28181; |
| | | } |
| | | |
| | | if(io_ctx_){ |
| | | av_freep(&io_ctx_->buffer); |
| | | avio_context_free(&io_ctx_); |
| | | av_freep(&io_ctx_); |
| | | io_ctx_ = NULL; |
| | | } |
| | | |
| | |
| | | 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"); |
| | |
| | | const int ret = avformat_open_input(&ctx_, filename, NULL, options); |
| | | // if(ret < 0){ |
| | | // logIt("open %s failed:%s",filename, |
| | | // getAVErrorDesc(ret).c_str()); |
| | | // getAVErrorDesc(ret).c_str()); |
| | | // } |
| | | |
| | | return ret; |
| | |
| | | const int ret = avformat_find_stream_info(ctx_, options); |
| | | if(ret < 0){ |
| | | logIt("find %s stream info failed:%s", |
| | | ctx_->filename,getAVErrorDesc(ret).c_str()); |
| | | ctx_->filename,getAVErrorDesc(ret).c_str()); |
| | | |
| | | return false; |
| | | } |
| | |
| | | fps_ = av_q2d(in->r_frame_rate); |
| | | }else if(in->avg_frame_rate.num >=1 && in->avg_frame_rate.den >= 1){ |
| | | fps_ = av_q2d(in->avg_frame_rate); |
| | | } |
| | | } |
| | | logIt("in stream video fps %f, time_base: %d : %d, size: %dx%d", fps_, in->time_base.num, in->time_base.den, in->codecpar->width, in->codecpar->height); |
| | | |
| | | |
| | | } |
| | | if (type == AVMEDIA_TYPE_AUDIO){ |
| | | auto in = ctx_->streams[i]; |
| | |
| | | return ctx_->streams[vs_idx_]->codecpar->codec_id == AV_CODEC_ID_HEVC; |
| | | } |
| | | |
| | | const bool FormatIn::IsAVC1()const{ |
| | | if (IsHEVC()) return false; |
| | | |
| | | char p[100] = {0}; |
| | | char *sub = av_fourcc_make_string(p, ctx_->streams[vs_idx_]->codecpar->codec_tag); |
| | | const int ret = strcmp(sub, "avc1"); |
| | | if (ret == 0) return true; |
| | | return false; |
| | | } |
| | | |
| | | bool FormatIn::openCodec(AVDictionary **options){ |
| | | if (vs_idx_ == -1) return false; |
| | | |
| | |
| | | |
| | | int idle_gpu = -1; |
| | | |
| | | srand((unsigned)time(NULL)); |
| | | |
| | | constexpr int need = 350; // M |
| | | constexpr int reserved = 512; // M |
| | | |
| | | for (int i = 0; i < 2; ++i) |
| | | { |
| | | if(hw_accl_){ |
| | | // idle_gpu = gpu::getGPUPrior(300, 1024, 0); |
| | | idle_gpu = gpu::getGPU(300); |
| | | |
| | | // 设置gpu index |
| | | if (prop_->gpu_index_ > -1){ |
| | | if (!gpu::satisfy(prop_->gpu_index_, need, reserved)){ |
| | | hw_accl_ = false; |
| | | continue; |
| | | } |
| | | idle_gpu = prop_->gpu_index_; |
| | | }else{ |
| | | idle_gpu = gpu::getGPUPrior(need, reserved, 0); |
| | | // idle_gpu = gpu::getGPU(300); |
| | | usleep(2000000 + rand()%3000000); |
| | | if (!gpu::satisfy(idle_gpu, need, reserved)){ |
| | | hw_accl_ = false; |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if(idle_gpu < 0){ |
| | | logIt("NO GPU RESOURCE TO DECODE"); |
| | | hw_accl_ = false; |
| | | continue; |
| | | } |
| | | |
| | | |
| | | std::string codec_name(avcodec_get_name(codecpar->codec_id)); |
| | | codec_name += "_cuvid"; |
| | | dec = avcodec_find_decoder_by_name(codec_name.c_str()); |
| | | |
| | | |
| | | if(!dec){ |
| | | hw_accl_ = false; |
| | | continue; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | return flag; |
| | | } |
| | | |
| | |
| | | int FormatIn::readPacket(AVPacket *pkt_out){ |
| | | |
| | | auto flag = av_read_frame(ctx_, pkt_out); |
| | | |
| | | return flag; |
| | | } |
| | | |
| | |
| | | av_packet_rescale_ts(pkt, in->time_base, in->codec->time_base); |
| | | int ret = avcodec_send_packet(dec_ctx_, pkt); |
| | | if(ret < 0){ |
| | | logIt("avcodec_send_packet error : %s", getAVErrorDesc(ret).c_str()); |
| | | logIt("pkt size %d avcodec_send_packet error : %s", pkt->size, getAVErrorDesc(ret).c_str()); |
| | | return -1; |
| | | } |
| | | while (ret >= 0) { |