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

📄 script.cpp

📁 avisynth-source-0.3.zip,avi edit src
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        *eos = 0;
        type = 's';
        string = next_char+2;
        next_char = eos+2;
      } else {
        throw FilterChainError(Sprintf("unexpected character \"%c\"", *next_char));
      }
      break;
  }
  while (isspace(*next_char))
    ++next_char;
}


class ScriptParser {

  Tokenizer tokenizer;
  VarTable var_table;
  int line_no;
  char line[2000];

  PVideoFilter ParseStatement() {
    // check for null statement
    if (tokenizer.GetType() == 0)
      return 0;
    // return and end statements
    if (tokenizer.GetType() == 'x') {
      if (!lstrcmpi(tokenizer.GetAsIdentifier(), "end")) {
        return var_table.GetValue("last");
      } else if (!lstrcmpi(tokenizer.GetAsIdentifier(), "return")) {
        tokenizer.NextToken();
        return ParseExpressionAtEOL();
      }
    }
    // assignment statement
    PVideoFilter* result_dest = &var_table.Lookup("last")->val;
    if (tokenizer.GetType() == 'x' && *tokenizer.NextCharPointer() == '=') {
      result_dest = &var_table.Lookup(tokenizer.GetAsIdentifier())->val;
      tokenizer.Reset(tokenizer.NextCharPointer()+1);
    }

    *result_dest = ParseExpressionAtEOL();

    return 0;
  }

  PVideoFilter ParseExpressionAtEOL() {
    PVideoFilter result = ParseExpression();
    if (tokenizer.GetType() != 0) {
      throw FilterChainError(Sprintf("mysterious gunk found around script line %d, position %d",
        line_no, tokenizer.CurCharPointer() - line + 1));
    }
    return result;
  }

  PVideoFilter ParseExpression() {
    PVideoFilter pvf = ParseOOP(0);
    if (tokenizer.GetType() == '+' || tokenizer.GetType() == '++') {
      bool aligned = (tokenizer.GetType() == '++');
      tokenizer.NextToken();
      return new_Splice(aligned, pvf, ParseExpression());
    } else {
      return pvf;
    }
  }

  PVideoFilter ParseOOP(PVideoFilter object) {
    PVideoFilter pvf;

    if (!object && tokenizer.GetType() == '(') {
      tokenizer.NextToken();
      pvf = ParseExpression();
      if (tokenizer.GetType() != ')') {
        throw FilterChainError(Sprintf("expected a ) at script line %d, position %d",
          line_no, tokenizer.CurCharPointer() - line + 1));
      }
      tokenizer.NextToken();
    } else {
      pvf = ParseFunction(object);
    }

    if (tokenizer.GetType() == '.') {
      tokenizer.NextToken();
      return ParseOOP(pvf);
    } else {
      return pvf;
    }
  }

  PVideoFilter ParseFunction(PVideoFilter object) {
    if (tokenizer.GetType() == 'x') {
      const char* filter_name = SearchForFilterName(tokenizer.GetAsIdentifier());
      if (filter_name) {
        // filter
        tokenizer.NextToken();
        char arg_types[64];
        Arg args[64];
        int num_args = ParseArgumentList(args, arg_types, 60);
        arg_types[num_args] = 0;
        // add object as last arg
        if (object) {
          if (strchr(arg_types, 'c') || strchr(arg_types, '+') || strchr(arg_types, '*'))
            throw FilterChainError("OOP notation can only be used with linear filters");
          arg_types[num_args] = 'c';
          args[num_args].clip = object;
          arg_types[++num_args] = 0;
        }
        FilterInfo* fi = SearchForMatchingFilter(filter_name, arg_types);
        if (!fi) {
          // try adding implicit 'last' arg
          if (!object) {
            PVideoFilter& last = var_table.GetValue("last");
            if (last) {
              arg_types[num_args] = 'c';
              args[num_args].clip = last;
              arg_types[++num_args] = 0;
              fi = SearchForMatchingFilter(filter_name, arg_types);
            }
          }
          if (!fi)
            throw FilterChainError(Sprintf("invalid arguments for filter %s", filter_name));
        }
        // promote int->float
        for (int y = 0; fi->param_types[y]; ++y) {
          if (fi->param_types[y] == 'f' && arg_types[y] == 'i') {
            args[y].floating_pt = float(args[y].integer);
            arg_types[y] = 'f';
          }
        }
        // create the filter
        return fi->pFilterFactoryFunction(fi, args, arg_types);
      } else {
        // variable
        PVideoFilter result = var_table.GetValue(tokenizer.GetAsIdentifier());
        if (object || result == 0) {
          throw FilterChainError(Sprintf("I don't know what \"%s\" means on line %d",
            tokenizer.GetAsIdentifier(), line_no));
        }
        tokenizer.NextToken();
        return result;
      }
    } else {
      throw FilterChainError(Sprintf("expected a %sfilter name at script line %d, position %d",
        object ? "" : "variable or ", line_no, tokenizer.CurCharPointer() - line + 1));
    }
  }

  int ParseArgumentList(Arg* args, char* arg_types, int max_args) {
    bool parenthesized = false;
    if (tokenizer.GetType() == '(') {
      tokenizer.NextToken();
      parenthesized = true;
    } else if (tokenizer.GetType() == '.' || tokenizer.GetType() == ',' || tokenizer.GetType() == '+' || tokenizer.GetType() == '++' || tokenizer.GetType() == ')') {
      return 0;
    }
    int num_args = 0;
    while (1) {
      if (parenthesized && tokenizer.GetType() == ')') {
        tokenizer.NextToken();
        return num_args;
      }
      if (!parenthesized && tokenizer.GetType() == 0) {
        return num_args;
      }
      if (num_args) {
        if (tokenizer.GetType() != ',') {
          if (parenthesized) {
            throw FilterChainError(Sprintf("expected a , or ) at script line %d, position %d",
              line_no, tokenizer.CurCharPointer() - line + 1));
          } else {
            return num_args;
          }
        }
        tokenizer.NextToken();    // skip ','
      }
      if (num_args == max_args) {
        throw FilterChainError(Sprintf("argument list too long around script line %d, position %d",
          line_no, tokenizer.CurCharPointer() - line + 1));
      }
      arg_types[num_args++] = ParseArgument(&args[num_args]);
    }
  }

  char ParseArgument(Arg* arg) {
    if (tokenizer.GetType() == 'i') {
      // int
      arg->integer = tokenizer.GetAsInt();
      tokenizer.NextToken();
      return 'i';
    } else if (tokenizer.GetType() == 'f') {
      // float
      arg->floating_pt = tokenizer.GetAsFloat();
      tokenizer.NextToken();
      return 'f';
    } else if (tokenizer.GetType() == 's') {
      // string
      arg->string = tokenizer.GetAsString();
      tokenizer.NextToken();
      return 's';
    } else if (tokenizer.GetType() == 'x' || tokenizer.GetType() == '(') {
      // expression
      arg->clip = ParseExpression();
      return 'c';
    } else {
      throw FilterChainError(Sprintf("expected a filter argument around script line %d, position %d",
        line_no, tokenizer.CurCharPointer() - line + 1));
    }
  }

  bool ParseDirective(const char* line) {
    char filename[256];
    if (sscanf(line, ".loadplugin \"%[^\"]\"", filename) == 1) {
      LoadPlugin(filename);
      return true;
    }
    return false;
  }

public:
  PVideoFilter ParseScript(const char filename[]) {
    FILE* f = fopen(filename, "r");

    try {
      if (!f)
        throw FilterChainError(Sprintf("Couldn't open input file %s", filename));
      line_no = 0;
      PVideoFilter result;
      while (fgets(line, sizeof(line), f)) {
        ++line_no;
        if (line[0] == '.') {
          ParseDirective(line);
        } else {
          tokenizer.Reset(line);
          result = ParseStatement();
          if (result) break;
        }
      }
      if (!result) result = var_table.GetValue("last");
      if (!result)
        throw FilterChainError("script has no return value!");
      fclose(f);
      return result;
    }

    catch (FilterChainError error) {
      if (f) fclose(f);
      VideoInfo viError;
      memset(&viError, 0, sizeof(viError));
      viError.width = (11*strlen(error.msg)) & -4;
      viError.height = 32;
      viError.fps_denominator = viError.fps_numerator = 1;
      viError.num_frames = 10;
      viError.pixel_type = VideoInfo::BGR24;
      return new_Subtitle(error.msg, -1, 23, 0, 999999, "Arial", 24, 0xFF3333, 0, new_Blackness(&viError));
    }
  }
};


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

class CootieCatcher : public VideoFilterWithRefcount {
  PVideoFilter child;
  VideoInfo vi;
  void MakeErrorStream(const char msg[]) {
    child = new_Subtitle(msg, 0, 15, 0, 999999, "Arial", 16, 0xFF3333, 0, new_Blackness(&vi));
  }
public:
  CootieCatcher(PVideoFilter _child) : child(_child) { child->GetVideoInfo(&vi); }
  void GetFrame(int n, unsigned char* buf) {
    try {
      child->GetFrame(n, buf);
    }
    catch (FilterChainError error) {
      MakeErrorStream(error.msg);
      child->GetFrame(n, buf);
    }
  }
  void GetAudio(void* buf, int start, int count) {
    try {
      child->GetAudio(buf, start, count);
    }
    catch (FilterChainError error) {
      MakeErrorStream(error.msg);
      child->GetAudio(buf, start, count);
    }
  }
  void GetVideoInfo(VideoInfo* pvi) { child->GetVideoInfo(pvi); }
  bool GetParity(int n) { return child->GetParity(n); }
};


PVideoFilter CreateFilterChain(const char filename[]) {
  ScriptParser parser;
  return new CootieCatcher(parser.ParseScript(filename));
}

⌨️ 快捷键说明

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