Commit 2b65bb45 authored by Michael Niedermayer's avatar Michael Niedermayer

Change eval API to take parent log context and log level offset.

this is based on stefanos work, especially all bugs are his fault ;)

Originally committed as revision 23201 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 4880cfd9
......@@ -30,6 +30,7 @@
#include "eval.h"
typedef struct Parser{
const AVClass *class;
int stack_index;
char *s;
const double *const_value;
......@@ -39,11 +40,14 @@ typedef struct Parser{
double (* const *func2)(void *, double a, double b); // NULL terminated
const char * const *func2_name; // NULL terminated
void *opaque;
const char **error;
int log_offset;
void *log_ctx;
#define VARS 10
double var[VARS];
} Parser;
static const AVClass class = { "Eval", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(Parser,log_offset), offsetof(Parser,log_ctx) };
static const int8_t si_prefixes['z' - 'E' + 1]={
['y'-'E']= -24,
['z'-'E']= -21,
......@@ -201,7 +205,7 @@ static AVExpr * parse_primary(Parser *p) {
p->s= strchr(p->s, '(');
if(p->s==NULL){
*p->error = "undefined constant or missing (";
av_log(p, AV_LOG_ERROR, "undefined constant or missing (\n");
p->s= next;
ff_free_expr(d);
return NULL;
......@@ -211,7 +215,7 @@ static AVExpr * parse_primary(Parser *p) {
av_freep(&d);
d = parse_expr(p);
if(p->s[0] != ')'){
*p->error = "missing )";
av_log(p, AV_LOG_ERROR, "missing )\n");
ff_free_expr(d);
return NULL;
}
......@@ -224,7 +228,7 @@ static AVExpr * parse_primary(Parser *p) {
d->param[1] = parse_expr(p);
}
if(p->s[0] != ')'){
*p->error = "missing )";
av_log(p, AV_LOG_ERROR, "missing )\n");
ff_free_expr(d);
return NULL;
}
......@@ -273,7 +277,7 @@ static AVExpr * parse_primary(Parser *p) {
}
}
*p->error = "unknown function";
av_log(p, AV_LOG_ERROR, "unknown function\n");
ff_free_expr(d);
return NULL;
}
......@@ -373,7 +377,8 @@ AVExpr *ff_parse_expr(const char *s,
const char * const *const_name,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
const char **error){
int log_offset, void *log_ctx)
{
Parser p;
AVExpr *e = NULL;
char *w = av_malloc(strlen(s) + 1);
......@@ -386,6 +391,7 @@ AVExpr *ff_parse_expr(const char *s,
if (!isspace(*s++)) *wp++ = s[-1];
*wp++ = 0;
p.class = &class;
p.stack_index=100;
p.s= w;
p.const_name = const_name;
......@@ -393,7 +399,8 @@ AVExpr *ff_parse_expr(const char *s,
p.func1_name = func1_name;
p.func2 = func2;
p.func2_name = func2_name;
p.error= error;
p.log_offset = log_offset;
p.log_ctx = log_ctx;
e = parse_expr(&p);
if (!verify_expr(e)) {
......@@ -417,8 +424,9 @@ double ff_parse_and_eval_expr(const char *s,
const char * const *const_name, const double *const_value,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
void *opaque, const char **error){
AVExpr *e = ff_parse_expr(s, const_name, func1_name, func1, func2_name, func2, error);
void *opaque, int log_offset, void *log_ctx)
{
AVExpr *e = ff_parse_expr(s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx);
double d;
if (!e) return NAN;
d = ff_eval_expr(e, const_value, opaque);
......@@ -440,12 +448,12 @@ static const char *const_names[]={
};
int main(void){
int i;
printf("%f == 12.7\n", ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL));
printf("%f == 12.7\n", ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL));
printf("%f == 0.931322575\n", ff_parse_and_eval_expr("80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL));
for(i=0; i<1050; i++){
START_TIMER
ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL);
ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
STOP_TIMER("ff_parse_and_eval_expr")
}
return 0;
......
......@@ -39,15 +39,15 @@ typedef struct AVExpr AVExpr;
* @param func1 NULL terminated array of function pointers for functions which take 1 argument
* @param func2_name NULL terminated array of zero terminated strings of func2 identifers
* @param func2 NULL terminated array of function pointers for functions which take 2 arguments
* @param error pointer to a char* which is set to an error message if something goes wrong
* @param opaque a pointer which will be passed to all functions from func1 and func2
* @param log_ctx parent logging context
* @return the value of the expression
*/
double ff_parse_and_eval_expr(const char *s,
const char * const *const_name, const double *const_value,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
void *opaque, const char **error);
void *opaque, int log_offset, void *log_ctx);
/**
* Parses an expression.
......@@ -58,7 +58,7 @@ double ff_parse_and_eval_expr(const char *s,
* @param func1 NULL terminated array of function pointers for functions which take 1 argument
* @param func2_name NULL terminated array of zero terminated strings of func2 identifers
* @param func2 NULL terminated array of function pointers for functions which take 2 arguments
* @param error pointer to a char* which is set to an error message if something goes wrong
* @param log_ctx parent logging context
* @return AVExpr which must be freed with ff_free_expr() by the user when it is not needed anymore
* NULL if anything went wrong
*/
......@@ -66,7 +66,7 @@ AVExpr *ff_parse_expr(const char *s,
const char * const *const_name,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
const char **error);
int log_offset, void *log_ctx);
/**
* Evaluates a previously parsed expression.
......
......@@ -147,7 +147,6 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
char buf[256];
int cmd=0;
double d;
const char *error = NULL;
if(*val == '+' || *val == '-')
cmd= *(val++);
......@@ -156,8 +155,7 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
buf[i]= val[i];
buf[i]=0;
d = ff_parse_and_eval_expr(buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, &error);
if(isnan(d)) {
{
const AVOption *o_named= av_find_opt(obj, buf, o->unit, 0, 0);
if(o_named && o_named->type == FF_OPT_TYPE_CONST)
d= o_named->default_val;
......@@ -167,9 +165,11 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
else if(!strcmp(buf, "none" )) d= 0;
else if(!strcmp(buf, "all" )) d= ~0;
else {
if (error)
av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\": %s\n", val, error);
d = ff_parse_and_eval_expr(buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
if (isnan(d)){
av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
return AVERROR(EINVAL);
}
}
}
if(o->type == FF_OPT_TYPE_FLAGS){
......
......@@ -67,7 +67,6 @@ int ff_rate_control_init(MpegEncContext *s)
{
RateControlContext *rcc= &s->rc_context;
int i;
const char *error = NULL;
static const char * const const_names[]={
"PI",
"E",
......@@ -107,9 +106,9 @@ int ff_rate_control_init(MpegEncContext *s)
};
emms_c();
rcc->rc_eq_eval = ff_parse_expr(s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, &error);
rcc->rc_eq_eval = ff_parse_expr(s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, 0, s->avctx);
if (!rcc->rc_eq_eval) {
av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\": %s\n", s->avctx->rc_eq, error? error : "");
av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", s->avctx->rc_eq);
return -1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment