⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc.cpp

📁 avisynth-source-0.3.zip,avi edit src
💻 CPP
📖 第 1 页 / 共 2 页
字号:
class StackHorizontal : public VideoFilterWithRefcount {
  const PVideoFilter child1, child2;
  VideoInfo vi1, vi2;
  unsigned char *mybuffer1, *mybuffer2;
public:
  StackHorizontal(PVideoFilter _child1, PVideoFilter _child2) : child1(_child1), child2(_child2), mybuffer1(0), mybuffer2(0) {
    child1->GetVideoInfo(&vi1);
    child2->GetVideoInfo(&vi2);

    if (vi1.height != vi2.height)
      throw FilterChainError("StackHorizontal: image heights don't match");
    if (vi1.pixel_type != vi2.pixel_type)
      throw FilterChainError("StackHorizontal: image formats don't match");
  }
  void GetFrame(int n, unsigned char* buf) {
    if (!mybuffer1) {
      mybuffer1 = new unsigned char[vi1.ImageSize()];
      mybuffer2 = new unsigned char[vi2.ImageSize()];
    }
    child1->GetFrame(n, mybuffer1);
    child2->GetFrame(n, mybuffer2);
    int row_size_1 = vi1.RowSize(), row_size_2 = vi2.RowSize();
    int row_size = row_size_1 + row_size_2;
    for (int y=0; y<vi1.height; ++y) {
      memcpy(buf+y*row_size, mybuffer1+y*row_size_1, row_size_1);
      memcpy(buf+y*row_size+row_size_1, mybuffer2+y*row_size_2, row_size_2);
    }
  }
  void GetAudio(void* buf, int start, int count) { child1->GetAudio(buf, start, count); }
  void GetVideoInfo(VideoInfo* pvi) {
    *pvi = vi1;
    pvi->width += vi2.width;
    pvi->num_frames = max(pvi->num_frames, vi2.num_frames);
    pvi->num_audio_samples = max(pvi->num_audio_samples, vi2.num_audio_samples);
  }
  bool GetParity(int n) { return child1->GetParity(n); }
  ~StackHorizontal() {
    if (mybuffer1) delete[] mybuffer1;
    if (mybuffer2) delete[] mybuffer2;
  }

  static PVideoFilter __cdecl Create(const FilterInfo* self, const Arg* args, const char* arg_types) {
    if (arg_types[1])
      return new StackHorizontal(args[0].clip, Create(self, args+1, arg_types+1));
    else
      return args[0].clip;
  }
};


/********************************************************************
********************************************************************/


class ShowFiveVersions : public VideoFilterWithRefcount {
  PVideoFilter child[5];
  VideoInfo vi;
  unsigned char* mybuffer;
public:
  ShowFiveVersions(PVideoFilter* children) {
    mybuffer = 0;
    for (int b=0; b<5; ++b)
      child[b] = children[b];

    child[0]->GetVideoInfo(&vi);
    // if any of the VideoInfo structs from the children differ, fail
    for (int c=1; c<5; ++c) {
      VideoInfo viprime;
      child[c]->GetVideoInfo(&viprime);
      vi.num_frames = viprime.num_frames = max(vi.num_frames, viprime.num_frames);
      if (memcmp(&vi, &viprime, sizeof(VideoInfo)))
        throw FilterChainError("ShowFiveVersions: video attributes of all streams must be identical");
    }
  }
  void GetFrame(int n, unsigned char* buf) {
    if (!mybuffer)
      mybuffer = new unsigned char[vi.ImageSize()];
    int src_row_size = vi.RowSize();
    int dst_row_size = src_row_size * 3;
    for (int c=0; c<5; ++c) {
      int dst_base = ((c&1)^vi.IsRGB()) * (vi.height * dst_row_size)
        + c * (src_row_size >> 1);   // staggered arrangement
      if (dst_base & 3) dst_base += 2;
      child[c]->GetFrame(n, mybuffer);
      for (int y=0; y<vi.height; ++y)
        memcpy(buf+dst_base+y*dst_row_size, mybuffer+y*src_row_size, src_row_size);
    }
  }
  void GetAudio(void* buf, int start, int count) { child[0]->GetAudio(buf, start, count); }
  void GetVideoInfo(VideoInfo* pvi) {
    *pvi = vi;
    pvi->width *= 3;
    pvi->height *= 2;
  }
  bool GetParity(int n) { return child[0]->GetParity(n); }

  static PVideoFilter __cdecl Create(const FilterInfo* self, const Arg* args, const char*) {
    PVideoFilter children[5];
    for (int i=0; i<5; ++i)
      children[i] = args[i].clip;
    return new ShowFiveVersions(children);
  }
};


/********************************************************************
********************************************************************/


class Animate : public VideoFilterWithRefcount {
  enum { cache_size = 3 };
  PVideoFilter cache[cache_size];
  int cache_stage[cache_size];
  const int first, last;
  Arg *args_before, *args_after, *args_now;
  char arg_types[64];
  int num_args;
  FilterInfo* filter_info;
public:
  Animate(int _first, int _last, const char* name, const Arg* _args, const char* _arg_types)
   : first(_first), last(_last)
  {
    if (first >= last)
      throw FilterChainError("Animate: final frame number must be greater than initial");

    int len = strlen(_arg_types);
    num_args = len >> 1;
    if ((len & 1) || memcmp(_arg_types, _arg_types+num_args, num_args))
      throw FilterChainError("Animate: must have two identical argument lists");

    extern FilterInfo* SearchForMatchingFilter(const char* search_name, const char* arg_types);
    filter_info = SearchForMatchingFilter(name, _arg_types + num_args);
    if (!filter_info)
      throw FilterChainError("Animate: no appropriate filter found");

    strcpy(arg_types, _arg_types+num_args);
    args_before = new Arg[num_args*3];
    for (int a=0; a<num_args*2; ++a)
      args_before[a] = _args[a];
    args_after = args_before + num_args;
    args_now = args_after + num_args;

    // promote int->float, save strings, and check for unanimatible arguments
    for (int i=0; filter_info->param_types[i]; ++i) {
      if (filter_info->param_types[i] == 'f' && arg_types[i] == 'i') {
        arg_types[i] = 'f';
        args_before[i].floating_pt = float(args_before[i].integer);
        args_after[i].floating_pt = float(args_after[i].integer);
      }
      else if (arg_types[i] == 's') {
        if (strcmp(args_before[i].string, args_after[i].string))
          throw FilterChainError("Animate: string arguments must match before and after");
        args_after[i].string = args_before[i].string = MyStrdup(args_before[i].string);
      }
    }

    memset(cache_stage, -1, sizeof(cache_stage));
    cache[0] = filter_info->pFilterFactoryFunction(filter_info, args_before, arg_types);
    cache_stage[0] = 0;
    cache[1] = filter_info->pFilterFactoryFunction(filter_info, args_after, arg_types);
    cache_stage[1] = last-first;
    VideoInfo vi1, vi2;
    cache[0]->GetVideoInfo(&vi1);
    cache[1]->GetVideoInfo(&vi2);
    if (vi1.width != vi2.width || vi1.height != vi2.height)
      throw FilterChainError("Animate: initial and final video frame sizes must match");
  }

  void GetFrame(int n, unsigned char* buf) {
    int stage = min(max(n, first), last) - first;
    for (int i=0; i<cache_size; ++i)
      if (cache_stage[i] == stage) {
        cache[i]->GetFrame(n, buf);
        return;
      }
    // filter not found in cache--create it
    int furthest = 0;
    for (int j=1; j<cache_size; ++j)
      if (abs(stage-cache_stage[j]) > abs(stage-cache_stage[furthest]))
        furthest = j;

    int scale = last-first;
    for (int a=0; a<num_args; ++a) {
      switch (arg_types[a]) {
        case 'i':
          args_now[a].integer = int(((double)args_before[a].integer*(scale-stage) + (double)args_after[a].integer*stage) / scale + 0.5);
          break;
        case 'f':
          args_now[a].floating_pt = float(((double)args_before[a].floating_pt*(scale-stage) + (double)args_after[a].floating_pt*stage) / scale);
          break;
        case 's':
          args_now[a].string = args_before[a].string;
        case 'c':
          args_now[a].clip = args_before[a].clip;
      }
    }
    cache_stage[furthest] = stage;
    cache[furthest] = filter_info->pFilterFactoryFunction(filter_info, args_now, arg_types);
    cache[furthest]->GetFrame(n, buf);
  }

  void GetAudio(void* buf, int start, int count) {
    // this could be implemented better...
    cache[0]->GetAudio(buf, start, count);
  }

  void GetVideoInfo(VideoInfo* pvi) {
    cache[0]->GetVideoInfo(pvi);
  }

  bool GetParity(int n) { return cache[0]->GetParity(n); }

  ~Animate() {
    for (int i=0; i<num_args; ++i)
      if (arg_types[i] == 's')
        delete[] const_cast<char*>(args_before[i].string);
    delete[] args_before;
  }

  static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char* arg_types) {
    return new Animate(args[0].integer, args[1].integer, args[2].string, args+3, arg_types+3);
  }
};


/********************************************************************
********************************************************************/


FilterInfo misc_filters[] = {
  { "ConvertToRGB", "c", ConvertToRGB::Create },
  { "ConvertToYUY2", "c", ConvertToYUY2::Create },
  { "Subtract", "cc", Subtract::Create },
  { "StackVertical", "cc+", StackVertical::Create },
  { "StackHorizontal", "cc+", StackHorizontal::Create },
  { "ShowFiveVersions", "ccccc", ShowFiveVersions::Create },
  { "Animate", "iis*", Animate::Create },
  { 0,0,0 }
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -