video analysis2.0拆分,ffmpeg封装go接口库
zhangmeng
2020-10-09 a8b447be656145c9ba2a2d8319a10ae8f726de1f
csrc/ffmpeg/format/FormatIn.cpp
@@ -2,6 +2,8 @@
#include <stdexcept>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
extern "C"{
#include <libavformat/avformat.h>
@@ -10,7 +12,8 @@
#include <libavutil/opt.h>
#include <libavutil/avassert.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include <libswscale/swscale.h>
#include <libavutil/intreadwrite.h>
}
#include "../log/log.hpp"
@@ -28,17 +31,41 @@
   ,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)
    ,bsf_h264(NULL)
    ,bsf_hevc(NULL)
   {}
   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)
    ,bsf_h264(NULL)
    ,bsf_hevc(NULL)
   {
      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_);
@@ -49,17 +76,19 @@
         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;
      }
        if (bsf_h264) av_bsf_free(&bsf_h264);
        if (bsf_hevc) av_bsf_free(&bsf_hevc);
   }
////////////////////////////////////////////////////////////////////////
@@ -75,7 +104,7 @@
         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");
@@ -127,7 +156,7 @@
      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;
@@ -138,7 +167,7 @@
      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;
      }
@@ -158,8 +187,21 @@
                   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", fps_, in->time_base.num, in->time_base.den);
               }
            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 (IsHEVC()){
            }else if (isAVC1()) {
               const AVBitStreamFilter *f = av_bsf_get_by_name("h264_mp4toannexb");
                    if (f){
                        if (av_bsf_alloc(f, &bsf_h264) >= 0){
                            if (avcodec_parameters_copy(bsf_h264->par_in, in->codecpar) >= 0){
                                if (av_bsf_init(bsf_h264) < 0) bsf_h264 = NULL;
                            }
                        }
                    }
                }
         }
         if (type == AVMEDIA_TYPE_AUDIO){
            auto in = ctx_->streams[i];
@@ -178,6 +220,16 @@
      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;
@@ -191,20 +243,42 @@
      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);
            // 设置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;
@@ -233,7 +307,7 @@
            }
         }
      }
        return flag;
   }
@@ -303,7 +377,40 @@
   int FormatIn::readPacket(AVPacket *pkt_out){
      auto flag = av_read_frame(ctx_, pkt_out);
      if (flag < 0) return flag;
      AVBSFContext *bsf = NULL;
      if (IsHEVC()){
         if (pkt_out->size >= 5 &&
            AV_RB32(pkt_out->data) != 0x0000001 &&
                AV_RB24(pkt_out->data) != 0x000001 &&
                !bsf_hevc){
            const AVBitStreamFilter *f = av_bsf_get_by_name("hevc_mp4toannexb");
                if (f){
                   if (av_bsf_alloc(f, &bsf_hevc) >= 0){
                       if (avcodec_parameters_copy(bsf_hevc->par_in, ctx_->streams[vs_idx_]->codecpar) >= 0){
                           if (av_bsf_init(bsf_hevc) < 0) bsf_hevc = NULL;
                       }
                   }
                }
            }
            bsf = bsf_hevc;
      }else {
         bsf = bsf_h264;
      }
      
      if (bsf){
         if (av_bsf_send_packet(bsf, pkt_out) < 0){
                logIt("bsf_%s send packet failed", IsHEVC() ? "hevc" : "h264");
                return -1;
            }
            return av_bsf_receive_packet(bsf, pkt_out);
      }
      return flag;
   }