mirror of https://github.com/FFmpeg/FFmpeg.git
Generalize drawtext utilities to make them usable in other filters. This will be needed to introduce the QR code source and filter without duplicating functionality.release/7.0
parent
c2ab41b7e0
commit
732fb122e6
4 changed files with 743 additions and 403 deletions
@ -0,0 +1,382 @@ |
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg. |
||||||
|
* |
||||||
|
* FFmpeg is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU Lesser General Public |
||||||
|
* License as published by the Free Software Foundation; either |
||||||
|
* version 2.1 of the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* FFmpeg is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||||
|
* Lesser General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU Lesser General Public |
||||||
|
* License along with FFmpeg; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @file |
||||||
|
* text expansion utilities |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <fenv.h> |
||||||
|
#include <math.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include "textutils.h" |
||||||
|
#include "libavutil/avutil.h" |
||||||
|
#include "libavutil/error.h" |
||||||
|
#include "libavutil/file.h" |
||||||
|
#include "libavutil/time.h" |
||||||
|
|
||||||
|
static int ff_expand_text_function_internal(FFExpandTextContext *expand_text, AVBPrint *bp, |
||||||
|
char *name, unsigned argc, char **argv) |
||||||
|
{ |
||||||
|
void *log_ctx = expand_text->log_ctx; |
||||||
|
FFExpandTextFunction *functions = expand_text->functions; |
||||||
|
unsigned i; |
||||||
|
|
||||||
|
for (i = 0; i < expand_text->functions_nb; i++) { |
||||||
|
if (strcmp(name, functions[i].name)) |
||||||
|
continue; |
||||||
|
if (argc < functions[i].argc_min) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "%%{%s} requires at least %d arguments\n", |
||||||
|
name, functions[i].argc_min); |
||||||
|
return AVERROR(EINVAL); |
||||||
|
} |
||||||
|
if (argc > functions[i].argc_max) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "%%{%s} requires at most %d arguments\n", |
||||||
|
name, functions[i].argc_max); |
||||||
|
return AVERROR(EINVAL); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
if (i >= expand_text->functions_nb) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "%%{%s} is not known\n", name); |
||||||
|
return AVERROR(EINVAL); |
||||||
|
} |
||||||
|
|
||||||
|
return functions[i].func(log_ctx, bp, name, argc, argv); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand text template pointed to by *rtext. |
||||||
|
* |
||||||
|
* Expand text template defined in text using the logic defined in a text |
||||||
|
* expander object. |
||||||
|
* |
||||||
|
* This function expects the text to be in the format %{FUNCTION_NAME[:PARAMS]}, |
||||||
|
* where PARAMS is a sequence of strings separated by : and represents the function |
||||||
|
* arguments to use for the function evaluation. |
||||||
|
* |
||||||
|
* @param text_expander TextExpander object used to expand the text |
||||||
|
* @param bp BPrint object where the expanded text is written to |
||||||
|
* @param rtext pointer to pointer to the text to expand, it is updated to point |
||||||
|
* to the next part of the template to process |
||||||
|
* @return negative value corresponding to an AVERROR error code in case of |
||||||
|
* errors, a non-negative value otherwise |
||||||
|
*/ |
||||||
|
static int ff_expand_text_function(FFExpandTextContext *expand_text, AVBPrint *bp, char **rtext) |
||||||
|
{ |
||||||
|
void *log_ctx = expand_text->log_ctx; |
||||||
|
const char *text = *rtext; |
||||||
|
char *argv[16] = { NULL }; |
||||||
|
unsigned argc = 0, i; |
||||||
|
int ret; |
||||||
|
|
||||||
|
if (*text != '{') { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "Stray %% near '%s'\n", text); |
||||||
|
return AVERROR(EINVAL); |
||||||
|
} |
||||||
|
text++; |
||||||
|
while (1) { |
||||||
|
if (!(argv[argc++] = av_get_token(&text, ":}"))) { |
||||||
|
ret = AVERROR(ENOMEM); |
||||||
|
goto end; |
||||||
|
} |
||||||
|
if (!*text) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "Unterminated %%{} near '%s'\n", *rtext); |
||||||
|
ret = AVERROR(EINVAL); |
||||||
|
goto end; |
||||||
|
} |
||||||
|
if (argc == FF_ARRAY_ELEMS(argv)) |
||||||
|
av_freep(&argv[--argc]); /* error will be caught later */ |
||||||
|
if (*text == '}') |
||||||
|
break; |
||||||
|
text++; |
||||||
|
} |
||||||
|
|
||||||
|
if ((ret = ff_expand_text_function_internal(expand_text, bp, argv[0], argc - 1, argv + 1)) < 0) |
||||||
|
goto end; |
||||||
|
ret = 0; |
||||||
|
*rtext = (char *)text + 1; |
||||||
|
|
||||||
|
end: |
||||||
|
for (i = 0; i < argc; i++) |
||||||
|
av_freep(&argv[i]); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
int ff_expand_text(FFExpandTextContext *expand_text, char *text, AVBPrint *bp) |
||||||
|
{ |
||||||
|
int ret; |
||||||
|
|
||||||
|
av_bprint_clear(bp); |
||||||
|
if (!text) |
||||||
|
return 0; |
||||||
|
|
||||||
|
while (*text) { |
||||||
|
if (*text == '\\' && text[1]) { |
||||||
|
av_bprint_chars(bp, text[1], 1); |
||||||
|
text += 2; |
||||||
|
} else if (*text == '%') { |
||||||
|
text++; |
||||||
|
if ((ret = ff_expand_text_function(expand_text, bp, &text)) < 0) |
||||||
|
return ret; |
||||||
|
} else { |
||||||
|
av_bprint_chars(bp, *text, 1); |
||||||
|
text++; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!av_bprint_is_complete(bp)) |
||||||
|
return AVERROR(ENOMEM); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int ff_print_pts(void *log_ctx, AVBPrint *bp, double pts, const char *delta, |
||||||
|
const char *fmt, const char *strftime_fmt) |
||||||
|
{ |
||||||
|
int ret; |
||||||
|
|
||||||
|
if (delta) { |
||||||
|
int64_t delta_i; |
||||||
|
if ((ret = av_parse_time(&delta_i, delta, 1)) < 0) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "Invalid delta '%s'\n", delta); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
pts += (double)delta_i / AV_TIME_BASE; |
||||||
|
} |
||||||
|
|
||||||
|
if (!strcmp(fmt, "flt")) { |
||||||
|
av_bprintf(bp, "%.6f", pts); |
||||||
|
} else if (!strcmp(fmt, "hms") || |
||||||
|
!strcmp(fmt, "hms24hh")) { |
||||||
|
if (isnan(pts)) { |
||||||
|
av_bprintf(bp, " ??:??:??.???"); |
||||||
|
} else { |
||||||
|
int64_t ms = llrint(pts * 1000); |
||||||
|
char sign = ' '; |
||||||
|
if (ms < 0) { |
||||||
|
sign = '-'; |
||||||
|
ms = -ms; |
||||||
|
} |
||||||
|
if (!strcmp(fmt, "hms24hh")) { |
||||||
|
/* wrap around 24 hours */ |
||||||
|
ms %= 24 * 60 * 60 * 1000; |
||||||
|
} |
||||||
|
av_bprintf(bp, "%c%02d:%02d:%02d.%03d", sign, |
||||||
|
(int)(ms / (60 * 60 * 1000)), |
||||||
|
(int)(ms / (60 * 1000)) % 60, |
||||||
|
(int)(ms / 1000) % 60, |
||||||
|
(int)(ms % 1000)); |
||||||
|
} |
||||||
|
} else if (!strcmp(fmt, "localtime") || |
||||||
|
!strcmp(fmt, "gmtime")) { |
||||||
|
struct tm tm; |
||||||
|
time_t ms = (time_t)pts; |
||||||
|
if (!strcmp(fmt, "localtime")) |
||||||
|
localtime_r(&ms, &tm); |
||||||
|
else |
||||||
|
gmtime_r(&ms, &tm); |
||||||
|
av_bprint_strftime(bp, av_x_if_null(strftime_fmt, "%Y-%m-%d %H:%M:%S"), &tm); |
||||||
|
} else { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "Invalid format '%s'\n", fmt); |
||||||
|
return AVERROR(EINVAL); |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int ff_print_time(void *log_ctx, AVBPrint *bp, |
||||||
|
const char *strftime_fmt, char localtime) |
||||||
|
{ |
||||||
|
const char *fmt = av_x_if_null(strftime_fmt, "%Y-%m-%d %H:%M:%S"); |
||||||
|
const char *fmt_begin = fmt; |
||||||
|
int64_t unow; |
||||||
|
time_t now; |
||||||
|
struct tm tm; |
||||||
|
const char *begin; |
||||||
|
const char *tmp; |
||||||
|
int len; |
||||||
|
int div; |
||||||
|
AVBPrint fmt_bp; |
||||||
|
|
||||||
|
av_bprint_init(&fmt_bp, 0, AV_BPRINT_SIZE_UNLIMITED); |
||||||
|
|
||||||
|
unow = av_gettime(); |
||||||
|
now = unow / 1000000; |
||||||
|
if (localtime) |
||||||
|
localtime_r(&now, &tm); |
||||||
|
else |
||||||
|
tm = *gmtime_r(&now, &tm); |
||||||
|
|
||||||
|
// manually parse format for %N (fractional seconds)
|
||||||
|
begin = fmt; |
||||||
|
while ((begin = strchr(begin, '%'))) { |
||||||
|
tmp = begin + 1; |
||||||
|
len = 0; |
||||||
|
|
||||||
|
// skip escaped "%%"
|
||||||
|
if (*tmp == '%') { |
||||||
|
begin = tmp + 1; |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// count digits between % and possible N
|
||||||
|
while (*tmp != '\0' && av_isdigit((int)*tmp)) { |
||||||
|
len++; |
||||||
|
tmp++; |
||||||
|
} |
||||||
|
|
||||||
|
// N encountered, insert time
|
||||||
|
if (*tmp == 'N') { |
||||||
|
int num_digits = 3; // default show millisecond [1,6]
|
||||||
|
|
||||||
|
// if digit given, expect [1,6], warn & clamp otherwise
|
||||||
|
if (len == 1) { |
||||||
|
num_digits = av_clip(*(begin + 1) - '0', 1, 6); |
||||||
|
} else if (len > 1) { |
||||||
|
av_log(log_ctx, AV_LOG_WARNING, "Invalid number of decimals for %%N, using default of %i\n", num_digits); |
||||||
|
} |
||||||
|
|
||||||
|
len += 2; // add % and N to get length of string part
|
||||||
|
|
||||||
|
div = pow(10, 6 - num_digits); |
||||||
|
|
||||||
|
av_bprintf(&fmt_bp, "%.*s%0*d", (int)(begin - fmt_begin), fmt_begin, num_digits, (int)(unow % 1000000) / div); |
||||||
|
|
||||||
|
begin += len; |
||||||
|
fmt_begin = begin; |
||||||
|
|
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
begin = tmp; |
||||||
|
} |
||||||
|
|
||||||
|
av_bprintf(&fmt_bp, "%s", fmt_begin); |
||||||
|
if (!av_bprint_is_complete(&fmt_bp)) { |
||||||
|
av_log(log_ctx, AV_LOG_WARNING, "Format string truncated at %u/%u.", fmt_bp.size, fmt_bp.len); |
||||||
|
} |
||||||
|
|
||||||
|
av_bprint_strftime(bp, fmt_bp.str, &tm); |
||||||
|
|
||||||
|
av_bprint_finalize(&fmt_bp, NULL); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int ff_print_eval_expr(void *log_ctx, AVBPrint *bp, |
||||||
|
const char *expr, |
||||||
|
const char * const *fun_names, const ff_eval_func2 *fun_values, |
||||||
|
const char * const *var_names, const double *var_values, |
||||||
|
void *eval_ctx) |
||||||
|
{ |
||||||
|
double res; |
||||||
|
int ret; |
||||||
|
|
||||||
|
ret = av_expr_parse_and_eval(&res, expr, var_names, var_values, |
||||||
|
NULL, NULL, fun_names, fun_values, |
||||||
|
eval_ctx, 0, log_ctx); |
||||||
|
if (ret < 0) |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, |
||||||
|
"Text expansion expression '%s' is not valid\n", |
||||||
|
expr); |
||||||
|
else |
||||||
|
av_bprintf(bp, "%f", res); |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
int ff_print_formatted_eval_expr(void *log_ctx, AVBPrint *bp, |
||||||
|
const char *expr, |
||||||
|
const char * const *fun_names, const ff_eval_func2 *fun_values, |
||||||
|
const char * const *var_names, const double *var_values, |
||||||
|
void *eval_ctx, |
||||||
|
const char format, int positions) |
||||||
|
{ |
||||||
|
double res; |
||||||
|
int intval; |
||||||
|
int ret; |
||||||
|
char fmt_str[30] = "%"; |
||||||
|
|
||||||
|
ret = av_expr_parse_and_eval(&res, expr, var_names, var_values, |
||||||
|
NULL, NULL, fun_names, fun_values, |
||||||
|
eval_ctx, 0, log_ctx); |
||||||
|
if (ret < 0) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, |
||||||
|
"Text expansion expression '%s' is not valid\n", |
||||||
|
expr); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
if (!strchr("xXdu", format)) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "Invalid format '%c' specified," |
||||||
|
" allowed values: 'x', 'X', 'd', 'u'\n", format); |
||||||
|
return AVERROR(EINVAL); |
||||||
|
} |
||||||
|
|
||||||
|
feclearexcept(FE_ALL_EXCEPT); |
||||||
|
intval = res; |
||||||
|
#if defined(FE_INVALID) && defined(FE_OVERFLOW) && defined(FE_UNDERFLOW) |
||||||
|
if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval); |
||||||
|
return AVERROR(EINVAL); |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
if (positions >= 0) |
||||||
|
av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions); |
||||||
|
av_strlcatf(fmt_str, sizeof(fmt_str), "%c", format); |
||||||
|
|
||||||
|
av_log(log_ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n", |
||||||
|
res, expr, fmt_str); |
||||||
|
|
||||||
|
av_bprintf(bp, fmt_str, intval); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int ff_load_textfile(void *log_ctx, const char *textfile, |
||||||
|
unsigned char **text, size_t *text_size) |
||||||
|
{ |
||||||
|
int err; |
||||||
|
uint8_t *textbuf; |
||||||
|
uint8_t *tmp; |
||||||
|
size_t textbuf_size; |
||||||
|
|
||||||
|
if ((err = av_file_map(textfile, &textbuf, &textbuf_size, 0, log_ctx)) < 0) { |
||||||
|
av_log(log_ctx, AV_LOG_ERROR, |
||||||
|
"The text file '%s' could not be read or is empty\n", |
||||||
|
textfile); |
||||||
|
return err; |
||||||
|
} |
||||||
|
|
||||||
|
if (textbuf_size > 0 && ff_is_newline(textbuf[textbuf_size - 1])) |
||||||
|
textbuf_size--; |
||||||
|
if (textbuf_size > SIZE_MAX - 1 || !(tmp = av_realloc(*text, textbuf_size + 1))) { |
||||||
|
av_file_unmap(textbuf, textbuf_size); |
||||||
|
return AVERROR(ENOMEM); |
||||||
|
} |
||||||
|
*text = tmp; |
||||||
|
memcpy(*text, textbuf, textbuf_size); |
||||||
|
(*text)[textbuf_size] = 0; |
||||||
|
if (text_size) |
||||||
|
*text_size = textbuf_size; |
||||||
|
av_file_unmap(textbuf, textbuf_size); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,229 @@ |
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg. |
||||||
|
* |
||||||
|
* FFmpeg is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU Lesser General Public |
||||||
|
* License as published by the Free Software Foundation; either |
||||||
|
* version 2.1 of the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* FFmpeg is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||||
|
* Lesser General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU Lesser General Public |
||||||
|
* License along with FFmpeg; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @file |
||||||
|
* text utilities |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef AVFILTER_TEXTUTILS_H |
||||||
|
#define AVFILTER_TEXTUTILS_H |
||||||
|
|
||||||
|
#include "libavutil/bprint.h" |
||||||
|
#include "libavutil/eval.h" |
||||||
|
#include "libavutil/log.h" |
||||||
|
#include "libavutil/parseutils.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
* Function used to expand a template sequence in the format |
||||||
|
* %{FUNCTION_NAME[:PARAMS]}, defined in the TextExpander object. |
||||||
|
*/ |
||||||
|
typedef struct FFExpandTextFunction { |
||||||
|
/**
|
||||||
|
* name of the function |
||||||
|
*/ |
||||||
|
const char *name; |
||||||
|
|
||||||
|
/**
|
||||||
|
* minimum and maximum number of arguments accepted by the |
||||||
|
* function in the PARAMS |
||||||
|
*/ |
||||||
|
unsigned argc_min, argc_max; |
||||||
|
|
||||||
|
/**
|
||||||
|
* actual function used to perform the expansion |
||||||
|
*/ |
||||||
|
int (*func)(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **args); |
||||||
|
} FFExpandTextFunction; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Text expander context, used to encapsulate the logic to expand a |
||||||
|
* given text template. |
||||||
|
* |
||||||
|
* A backslash character @samp{\} in a text template, followed by any |
||||||
|
* character, always expands to the second character. |
||||||
|
* Sequences of the form %{FUNCTION_NAME[:PARAMS]} are expanded using a |
||||||
|
* function defined in the object. The text between the braces is a |
||||||
|
* function name, possibly followed by arguments separated by ':'. If |
||||||
|
* the arguments contain special characters or delimiters (':' or |
||||||
|
* '}'), they should be escaped. |
||||||
|
*/ |
||||||
|
typedef struct FFExpandTextContext { |
||||||
|
/**
|
||||||
|
* log context to pass to the function, used for logging and for |
||||||
|
* accessing the context for the function |
||||||
|
*/ |
||||||
|
void *log_ctx; |
||||||
|
|
||||||
|
/**
|
||||||
|
* list of functions to use to expand sequences in the format |
||||||
|
* FUNCTION_NAME{PARAMS} |
||||||
|
*/ |
||||||
|
FFExpandTextFunction *functions; |
||||||
|
|
||||||
|
/**
|
||||||
|
* number of functions |
||||||
|
*/ |
||||||
|
unsigned int functions_nb; |
||||||
|
} FFExpandTextContext; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand text template. |
||||||
|
* |
||||||
|
* Expand text template defined in text using the logic defined in a text |
||||||
|
* expander object. |
||||||
|
* |
||||||
|
* @param expand_text text expansion context used to expand the text |
||||||
|
* @param text template text to expand |
||||||
|
* @param bp BPrint object where the expanded text is written to |
||||||
|
* @return negative value corresponding to an AVERROR error code in case of |
||||||
|
* errors, a non-negative value otherwise |
||||||
|
*/ |
||||||
|
int ff_expand_text(FFExpandTextContext *expand_text, char *text, AVBPrint *bp); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Print PTS representation to an AVBPrint object. |
||||||
|
* |
||||||
|
* @param log_ctx pointer to av_log object |
||||||
|
* @param bp AVBPrint object where the PTS textual representation is written to |
||||||
|
* @param pts PTS value expressed as a double to represent |
||||||
|
* @param delta delta time parsed by av_parse_time(), added to the PTS |
||||||
|
* @param fmt string representing the format to use for printing, can be |
||||||
|
* "flt" - use a float representation with 6 decimal digits, |
||||||
|
* "hms" - use HH:MM:SS.MMM format, |
||||||
|
* "hms24hh" - same as "hms" but wraps the hours in 24hh format |
||||||
|
* (so that it is expressed in the range 00-23), |
||||||
|
* "localtime" or "gmtime" - expand the PTS according to the |
||||||
|
* @code{strftime()} function rules, using either the corresponding |
||||||
|
* @code{localtime()} or @code{gmtime()} time |
||||||
|
* @param strftime_fmt: @code{strftime()} format to use to represent the PTS in |
||||||
|
* case the format "localtime" or "gmtime" was selected, if not specified |
||||||
|
* defaults to "%Y-%m-%d %H:%M:%S" |
||||||
|
* @return negative value corresponding to an AVERROR error code in case of |
||||||
|
* errors, a non-negative value otherwise |
||||||
|
*/ |
||||||
|
int ff_print_pts(void *log_ctx, AVBPrint *bp, double pts, const char *delta, |
||||||
|
const char *fmt, const char *strftime_fmt); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Print time representation to an AVBPrint object. |
||||||
|
* |
||||||
|
* @param log_ctx pointer to av_log object |
||||||
|
* @param bp AVBPrint object where the time textual representation is written to |
||||||
|
* @param strftime_fmt: strftime() format to use to represent the time in case |
||||||
|
* if not specified defaults to "%Y-%m-%d %H:%M:%S". The format string is |
||||||
|
* extended to support the %[1-6]N after %S which prints fractions of the |
||||||
|
* second with optionally specified number of digits, if not specified |
||||||
|
* defaults to 3. |
||||||
|
* @param localtime use local time to compute the time if non-zero, otherwise |
||||||
|
* use UTC |
||||||
|
* @return negative value corresponding to an AVERROR error code in case of |
||||||
|
* errors, a non-negative value otherwise |
||||||
|
*/ |
||||||
|
int ff_print_time(void *log_ctx, AVBPrint *bp, const char *strftime_fmt, char localtime); |
||||||
|
|
||||||
|
typedef double (*ff_eval_func2)(void *, double a, double b); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate and print expression to an AVBprint object. |
||||||
|
* The output is written as a double representation. |
||||||
|
* |
||||||
|
* This is a wrapper around av_expr_parse_and_eval() and following the |
||||||
|
* same rules. |
||||||
|
* |
||||||
|
* @param log_ctx pointer to av_log object |
||||||
|
* @param bp AVBPrint object where the evaluated expression is written to |
||||||
|
* @param expr the expression to be evaluated |
||||||
|
* @param fun_names names of the ff_eval_func2 functions used to evaluate the expression |
||||||
|
* @param fun_values values of the ff_eval_func2 functions used to evaluate the expression |
||||||
|
* @param var_names names of the variables used in the expression |
||||||
|
* @param var_values values of the variables used in the expression |
||||||
|
* @param eval_ctx evaluation context to be passed to some functions |
||||||
|
* |
||||||
|
* @return negative value corresponding to an AVERROR error code in case of |
||||||
|
* errors, a non-negative value otherwise |
||||||
|
*/ |
||||||
|
int ff_print_eval_expr(void *log_ctx, AVBPrint *bp, |
||||||
|
const char *expr, |
||||||
|
const char * const *fun_names, const ff_eval_func2 *fun_values, |
||||||
|
const char * const *var_names, const double *var_values, |
||||||
|
void *eval_ctx); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate and print expression to an AVBprint object, using the |
||||||
|
* specified format. |
||||||
|
* |
||||||
|
* This is a wrapper around av_expr_parse_and_eval() and following the |
||||||
|
* same rules. |
||||||
|
* |
||||||
|
* The format is specified as a printf format character, optionally |
||||||
|
* preceded by the positions numbers for zero-padding. |
||||||
|
* |
||||||
|
* The following formats are accepted: |
||||||
|
* - x: use lowercase hexadecimal representation |
||||||
|
* - X: use uppercase hexadecimal representation |
||||||
|
* - d: use decimal representation |
||||||
|
* - u: use unsigned decimal representation |
||||||
|
* |
||||||
|
* @param log_ctx pointer to av_log object |
||||||
|
* @param bp AVBPrint object where the evaluated expression is written to |
||||||
|
* @param expr the expression to be evaluated |
||||||
|
* @param fun_names names of the ff_eval_func2 functions used to evaluate the expression |
||||||
|
* @param fun_values values of the ff_eval_func2 functions used to evaluate the expression |
||||||
|
* @param var_names names of the variables used in the expression |
||||||
|
* @param var_values values of the variables used in the expression |
||||||
|
* @param eval_ctx evaluation context to be passed to some functions |
||||||
|
* @param format a character representing the format, to be chosen in xXdu |
||||||
|
* @param positions final size of the value representation with 0-padding |
||||||
|
* @return negative value corresponding to an AVERROR error code in case of |
||||||
|
* errors, a non-negative value otherwise |
||||||
|
*/ |
||||||
|
int ff_print_formatted_eval_expr(void *log_ctx, AVBPrint *bp, |
||||||
|
const char *expr, |
||||||
|
const char * const *fun_names, const ff_eval_func2 *fun_values, |
||||||
|
const char * const *var_names, const double *var_values, |
||||||
|
void *eval_ctx, |
||||||
|
const char format, int positions); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the character is a newline. |
||||||
|
* |
||||||
|
* @param c character to check |
||||||
|
* @return non-negative value in case c is a newline, 0 otherwise |
||||||
|
*/ |
||||||
|
static inline int ff_is_newline(uint32_t c) |
||||||
|
{ |
||||||
|
return c == '\n' || c == '\r' || c == '\f' || c == '\v'; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Load text file into the buffer pointed by text. |
||||||
|
* |
||||||
|
* @param log_ctx pointer to av_log object |
||||||
|
* @param textfile filename containing the text to load |
||||||
|
* @param text pointer to the text buffer where the loaded text will be |
||||||
|
* loaded |
||||||
|
* @param text_size pointer to the value to set with the loaded text data, |
||||||
|
* including the terminating 0 character |
||||||
|
* @return negative value corresponding to an AVERROR error code in case of |
||||||
|
* errors, a non-negative value otherwise |
||||||
|
*/ |
||||||
|
int ff_load_textfile(void *log_ctx, const char *textfile, |
||||||
|
unsigned char **text, size_t *text_size); |
||||||
|
|
||||||
|
#endif /* AVFILTER_TEXTUTILS__H */ |
Loading…
Reference in new issue