diff --git a/libavutil/eval.c b/libavutil/eval.c
index 5da9a6d83b..58e3742245 100644
--- a/libavutil/eval.c
+++ b/libavutil/eval.c
@@ -142,6 +142,40 @@ double av_strtod(const char *numstr, char **tail)
     return d;
 }
 
+static int parse_string_literal(Parser *p, char **tail, char **literal_str)
+{
+  char *parse_str = p->s;
+  char *next = parse_str;
+  char *literal = NULL;
+  int nbyte;
+
+    if(parse_str[0] == '\'' || parse_str[0] == '"') {
+
+      next = strchr(parse_str + 1, parse_str[0]);
+            
+      if(next == NULL) {
+        av_log(p, AV_LOG_ERROR, "Unterminated string in '%s'\n", parse_str);
+        return AVERROR(EINVAL);
+      } else {
+        nbyte = next - parse_str; /* Includes space for \0 */
+        literal = av_mallocz(nbyte);
+        if (!literal)
+          return AVERROR(ENOMEM);
+
+        strncpy(literal, parse_str+1, nbyte-1);
+        literal[nbyte-1] = '\0';
+        next++;                 /* step past the ending quote */
+      }
+    }
+
+    /* if requested, fill in tail with the position after the last parsed
+       character */
+    if (tail)
+        *tail = next;
+    *literal_str = literal;
+    return 0;
+}
+
 #define IS_IDENTIFIER_CHAR(c) ((c) - '0' <= 9U || (c) - 'a' <= 25U || (c) - 'A' <= 25U || (c) == '_')
 
 static int strmatch(const char *s, const char *prefix)
@@ -154,17 +188,27 @@ static int strmatch(const char *s, const char *prefix)
     return !IS_IDENTIFIER_CHAR(s[i]);
 }
 
+
+struct AVGetExprBuffer {
+  int ndata;
+  char *data;
+};
+
 struct AVExpr {
     enum {
-        e_value, e_const, e_func0, e_func1, e_func2,
+        e_value, e_const, e_string, e_buffer, e_func0, e_func1, e_func2,
         e_squish, e_gauss, e_ld, e_isnan, e_isinf,
         e_mod, e_max, e_min, e_eq, e_gt, e_gte, e_lte, e_lt,
         e_pow, e_mul, e_div, e_add,
         e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, e_round,
         e_sqrt, e_not, e_random, e_hypot, e_gcd,
         e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip, e_atan2, e_lerp,
+        e_get,
     } type;
-    double value; // is sign in other types
+    union {
+        double value; // is sign in other types
+        void *pointer;
+    };
     union {
         int const_index;
         double (*func0)(double);
@@ -300,6 +344,12 @@ static double eval_expr(Parser *p, AVExpr *e)
             p->var[0] = var0;
             return -low_v<high_v ? low : high;
         }
+        case e_get: {
+          struct AVGetExprBuffer * buffer = (struct AVGetExprBuffer * )e->param[1]->pointer;
+          int index = (int)eval_expr(p, e->param[0]);
+          index = (index < 0)?0:((index >= buffer->ndata)?buffer->ndata-1:index);
+          return e->value * buffer->data[index];
+        }
         default: {
             double d = eval_expr(p, e->param[0]);
             double d2 = eval_expr(p, e->param[1]);
@@ -345,11 +395,23 @@ static int parse_primary(AVExpr **e, Parser *p)
 {
     AVExpr *d = av_mallocz(sizeof(AVExpr));
     char *next = p->s, *s0 = p->s;
+    char * literal_str;
     int ret, i;
 
     if (!d)
         return AVERROR(ENOMEM);
 
+    if((ret = parse_string_literal(p, &next, &literal_str)) != 0)
+        return ret;
+
+    if(literal_str != NULL) {
+        d->type = e_string;
+        d->pointer = literal_str;
+        p->s = next;
+        *e = d;
+        return 0;
+    }
+
     /* number */
     d->value = av_strtod(p->s, &next);
     if (next != p->s) {
@@ -470,6 +532,7 @@ static int parse_primary(AVExpr **e, Parser *p)
     else if (strmatch(next, "clip"  )) d->type = e_clip;
     else if (strmatch(next, "atan2" )) d->type = e_atan2;
     else if (strmatch(next, "lerp"  )) d->type = e_lerp;
+    else if (strmatch(next, "get"   )) d->type = e_get;
     else {
         for (i=0; p->func1_names && p->func1_names[i]; i++) {
             if (strmatch(next, p->func1_names[i])) {
@@ -637,12 +700,55 @@ static int parse_expr(AVExpr **e, Parser *p)
     return 0;
 }
 
+
+static int init_get_expr(AVExpr *e)
+{
+  FILE * fp;
+  char * fname = (char *)e->pointer;
+  struct AVGetExprBuffer * buffer;
+  int nbyte;
+
+  if((fp = fopen(fname, "rb")) == NULL)
+    return 0;
+  fseek(fp, 0, SEEK_END);
+  nbyte = ftell(fp);
+  fseek(fp, 0, SEEK_SET);
+
+  buffer = av_malloc(nbyte + sizeof(struct AVGetExprBuffer));
+  if(buffer == NULL)
+    {
+      fclose(fp);
+      return 0;
+    }
+
+  buffer->ndata = nbyte;
+  buffer->data = (char *)(buffer + 1);  /* Add sizeof the struct */
+
+  if(fread(buffer->data, nbyte, 1, fp) != 1)
+    {
+      fclose(fp);
+      av_free(buffer);
+      return 0;
+    }
+
+  e->pointer = buffer;
+  e->type = e_buffer;
+  av_free(fname);
+  fclose(fp);
+
+  return 1;
+}
+
 static int verify_expr(AVExpr *e)
 {
     if (!e) return 0;
     switch (e->type) {
         case e_value:
         case e_const: return 1;
+        /* string and buffer types are currently only exposed to e_get.
+           So if we got here, something is wrong. */
+        case e_string:
+        case e_buffer: return 0; 
         case e_func0:
         case e_func1:
         case e_squish:
@@ -672,6 +778,14 @@ static int verify_expr(AVExpr *e)
             return verify_expr(e->param[0]) &&
                    verify_expr(e->param[1]) &&
                    verify_expr(e->param[2]);
+        case e_get:
+          if(!e->param[1] || e->param[1]->type != e_string)
+            return 0;
+          /* Since there is no separate init for the expression, and nothing
+             other than get currently needs initialization, initializing 
+             from verify_expr() was the least amount of new code. */
+          return verify_expr(e->param[0]) && init_get_expr(e->param[1]);
+
         default: return verify_expr(e->param[0]) && verify_expr(e->param[1]) && !e->param[2];
     }
 }
