Statistics
| Branch: | Revision:

ffmpeg / libavfilter / parseutils.c @ 34017fd9

History | View | Annotate | Download (18.1 KB)

1
/*
2
 * copyright (c) 2009 Stefano Sabatini
3
 * This file is part of FFmpeg.
4
 *
5
 * FFmpeg is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * FFmpeg is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with FFmpeg; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
 */
19

    
20
/**
21
 * @file
22
 * parsing utils
23
 */
24

    
25
#include <strings.h>
26
#include "libavutil/avutil.h"
27
#include "libavutil/avstring.h"
28
#include "libavutil/random_seed.h"
29
#include "parseutils.h"
30

    
31
#define WHITESPACES " \n\t"
32

    
33
char *av_get_token(const char **buf, const char *term)
34
{
35
    char *out = av_malloc(strlen(*buf) + 1);
36
    char *ret= out, *end= out;
37
    const char *p = *buf;
38
    if (!out) return NULL;
39
    p += strspn(p, WHITESPACES);
40

    
41
    while(*p && !strspn(p, term)) {
42
        char c = *p++;
43
        if(c == '\\' && *p){
44
            *out++ = *p++;
45
            end= out;
46
        }else if(c == '\''){
47
            while(*p && *p != '\'')
48
                *out++ = *p++;
49
            if(*p){
50
                p++;
51
                end= out;
52
            }
53
        }else{
54
            *out++ = c;
55
        }
56
    }
57

    
58
    do{
59
        *out-- = 0;
60
    }while(out >= end && strspn(out, WHITESPACES));
61

    
62
    *buf = p;
63

    
64
    return ret;
65
}
66

    
67
typedef struct {
68
    const char *name;            ///< a string representing the name of the color
69
    uint8_t     rgb_color[3];    ///< RGB values for the color
70
} ColorEntry;
71

    
72
static ColorEntry color_table[] = {
73
    { "AliceBlue",            { 0xF0, 0xF8, 0xFF } },
74
    { "AntiqueWhite",         { 0xFA, 0xEB, 0xD7 } },
75
    { "Aqua",                 { 0x00, 0xFF, 0xFF } },
76
    { "Aquamarine",           { 0x7F, 0xFF, 0xD4 } },
77
    { "Azure",                { 0xF0, 0xFF, 0xFF } },
78
    { "Beige",                { 0xF5, 0xF5, 0xDC } },
79
    { "Bisque",               { 0xFF, 0xE4, 0xC4 } },
80
    { "Black",                { 0x00, 0x00, 0x00 } },
81
    { "BlanchedAlmond",       { 0xFF, 0xEB, 0xCD } },
82
    { "Blue",                 { 0x00, 0x00, 0xFF } },
83
    { "BlueViolet",           { 0x8A, 0x2B, 0xE2 } },
84
    { "Brown",                { 0xA5, 0x2A, 0x2A } },
85
    { "BurlyWood",            { 0xDE, 0xB8, 0x87 } },
86
    { "CadetBlue",            { 0x5F, 0x9E, 0xA0 } },
87
    { "Chartreuse",           { 0x7F, 0xFF, 0x00 } },
88
    { "Chocolate",            { 0xD2, 0x69, 0x1E } },
89
    { "Coral",                { 0xFF, 0x7F, 0x50 } },
90
    { "CornflowerBlue",       { 0x64, 0x95, 0xED } },
91
    { "Cornsilk",             { 0xFF, 0xF8, 0xDC } },
92
    { "Crimson",              { 0xDC, 0x14, 0x3C } },
93
    { "Cyan",                 { 0x00, 0xFF, 0xFF } },
94
    { "DarkBlue",             { 0x00, 0x00, 0x8B } },
95
    { "DarkCyan",             { 0x00, 0x8B, 0x8B } },
96
    { "DarkGoldenRod",        { 0xB8, 0x86, 0x0B } },
97
    { "DarkGray",             { 0xA9, 0xA9, 0xA9 } },
98
    { "DarkGreen",            { 0x00, 0x64, 0x00 } },
99
    { "DarkKhaki",            { 0xBD, 0xB7, 0x6B } },
100
    { "DarkMagenta",          { 0x8B, 0x00, 0x8B } },
101
    { "DarkOliveGreen",       { 0x55, 0x6B, 0x2F } },
102
    { "Darkorange",           { 0xFF, 0x8C, 0x00 } },
103
    { "DarkOrchid",           { 0x99, 0x32, 0xCC } },
104
    { "DarkRed",              { 0x8B, 0x00, 0x00 } },
105
    { "DarkSalmon",           { 0xE9, 0x96, 0x7A } },
106
    { "DarkSeaGreen",         { 0x8F, 0xBC, 0x8F } },
107
    { "DarkSlateBlue",        { 0x48, 0x3D, 0x8B } },
108
    { "DarkSlateGray",        { 0x2F, 0x4F, 0x4F } },
109
    { "DarkTurquoise",        { 0x00, 0xCE, 0xD1 } },
110
    { "DarkViolet",           { 0x94, 0x00, 0xD3 } },
111
    { "DeepPink",             { 0xFF, 0x14, 0x93 } },
112
    { "DeepSkyBlue",          { 0x00, 0xBF, 0xFF } },
113
    { "DimGray",              { 0x69, 0x69, 0x69 } },
114
    { "DodgerBlue",           { 0x1E, 0x90, 0xFF } },
115
    { "FireBrick",            { 0xB2, 0x22, 0x22 } },
116
    { "FloralWhite",          { 0xFF, 0xFA, 0xF0 } },
117
    { "ForestGreen",          { 0x22, 0x8B, 0x22 } },
118
    { "Fuchsia",              { 0xFF, 0x00, 0xFF } },
119
    { "Gainsboro",            { 0xDC, 0xDC, 0xDC } },
120
    { "GhostWhite",           { 0xF8, 0xF8, 0xFF } },
121
    { "Gold",                 { 0xFF, 0xD7, 0x00 } },
122
    { "GoldenRod",            { 0xDA, 0xA5, 0x20 } },
123
    { "Gray",                 { 0x80, 0x80, 0x80 } },
124
    { "Green",                { 0x00, 0x80, 0x00 } },
125
    { "GreenYellow",          { 0xAD, 0xFF, 0x2F } },
126
    { "HoneyDew",             { 0xF0, 0xFF, 0xF0 } },
127
    { "HotPink",              { 0xFF, 0x69, 0xB4 } },
128
    { "IndianRed",            { 0xCD, 0x5C, 0x5C } },
129
    { "Indigo",               { 0x4B, 0x00, 0x82 } },
130
    { "Ivory",                { 0xFF, 0xFF, 0xF0 } },
131
    { "Khaki",                { 0xF0, 0xE6, 0x8C } },
132
    { "Lavender",             { 0xE6, 0xE6, 0xFA } },
133
    { "LavenderBlush",        { 0xFF, 0xF0, 0xF5 } },
134
    { "LawnGreen",            { 0x7C, 0xFC, 0x00 } },
135
    { "LemonChiffon",         { 0xFF, 0xFA, 0xCD } },
136
    { "LightBlue",            { 0xAD, 0xD8, 0xE6 } },
137
    { "LightCoral",           { 0xF0, 0x80, 0x80 } },
138
    { "LightCyan",            { 0xE0, 0xFF, 0xFF } },
139
    { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
140
    { "LightGrey",            { 0xD3, 0xD3, 0xD3 } },
141
    { "LightGreen",           { 0x90, 0xEE, 0x90 } },
142
    { "LightPink",            { 0xFF, 0xB6, 0xC1 } },
143
    { "LightSalmon",          { 0xFF, 0xA0, 0x7A } },
144
    { "LightSeaGreen",        { 0x20, 0xB2, 0xAA } },
145
    { "LightSkyBlue",         { 0x87, 0xCE, 0xFA } },
146
    { "LightSlateGray",       { 0x77, 0x88, 0x99 } },
147
    { "LightSteelBlue",       { 0xB0, 0xC4, 0xDE } },
148
    { "LightYellow",          { 0xFF, 0xFF, 0xE0 } },
149
    { "Lime",                 { 0x00, 0xFF, 0x00 } },
150
    { "LimeGreen",            { 0x32, 0xCD, 0x32 } },
151
    { "Linen",                { 0xFA, 0xF0, 0xE6 } },
152
    { "Magenta",              { 0xFF, 0x00, 0xFF } },
153
    { "Maroon",               { 0x80, 0x00, 0x00 } },
154
    { "MediumAquaMarine",     { 0x66, 0xCD, 0xAA } },
155
    { "MediumBlue",           { 0x00, 0x00, 0xCD } },
156
    { "MediumOrchid",         { 0xBA, 0x55, 0xD3 } },
157
    { "MediumPurple",         { 0x93, 0x70, 0xD8 } },
158
    { "MediumSeaGreen",       { 0x3C, 0xB3, 0x71 } },
159
    { "MediumSlateBlue",      { 0x7B, 0x68, 0xEE } },
160
    { "MediumSpringGreen",    { 0x00, 0xFA, 0x9A } },
161
    { "MediumTurquoise",      { 0x48, 0xD1, 0xCC } },
162
    { "MediumVioletRed",      { 0xC7, 0x15, 0x85 } },
163
    { "MidnightBlue",         { 0x19, 0x19, 0x70 } },
164
    { "MintCream",            { 0xF5, 0xFF, 0xFA } },
165
    { "MistyRose",            { 0xFF, 0xE4, 0xE1 } },
166
    { "Moccasin",             { 0xFF, 0xE4, 0xB5 } },
167
    { "NavajoWhite",          { 0xFF, 0xDE, 0xAD } },
168
    { "Navy",                 { 0x00, 0x00, 0x80 } },
169
    { "OldLace",              { 0xFD, 0xF5, 0xE6 } },
170
    { "Olive",                { 0x80, 0x80, 0x00 } },
171
    { "OliveDrab",            { 0x6B, 0x8E, 0x23 } },
172
    { "Orange",               { 0xFF, 0xA5, 0x00 } },
173
    { "OrangeRed",            { 0xFF, 0x45, 0x00 } },
174
    { "Orchid",               { 0xDA, 0x70, 0xD6 } },
175
    { "PaleGoldenRod",        { 0xEE, 0xE8, 0xAA } },
176
    { "PaleGreen",            { 0x98, 0xFB, 0x98 } },
177
    { "PaleTurquoise",        { 0xAF, 0xEE, 0xEE } },
178
    { "PaleVioletRed",        { 0xD8, 0x70, 0x93 } },
179
    { "PapayaWhip",           { 0xFF, 0xEF, 0xD5 } },
180
    { "PeachPuff",            { 0xFF, 0xDA, 0xB9 } },
181
    { "Peru",                 { 0xCD, 0x85, 0x3F } },
182
    { "Pink",                 { 0xFF, 0xC0, 0xCB } },
183
    { "Plum",                 { 0xDD, 0xA0, 0xDD } },
184
    { "PowderBlue",           { 0xB0, 0xE0, 0xE6 } },
185
    { "Purple",               { 0x80, 0x00, 0x80 } },
186
    { "Red",                  { 0xFF, 0x00, 0x00 } },
187
    { "RosyBrown",            { 0xBC, 0x8F, 0x8F } },
188
    { "RoyalBlue",            { 0x41, 0x69, 0xE1 } },
189
    { "SaddleBrown",          { 0x8B, 0x45, 0x13 } },
190
    { "Salmon",               { 0xFA, 0x80, 0x72 } },
191
    { "SandyBrown",           { 0xF4, 0xA4, 0x60 } },
192
    { "SeaGreen",             { 0x2E, 0x8B, 0x57 } },
193
    { "SeaShell",             { 0xFF, 0xF5, 0xEE } },
194
    { "Sienna",               { 0xA0, 0x52, 0x2D } },
195
    { "Silver",               { 0xC0, 0xC0, 0xC0 } },
196
    { "SkyBlue",              { 0x87, 0xCE, 0xEB } },
197
    { "SlateBlue",            { 0x6A, 0x5A, 0xCD } },
198
    { "SlateGray",            { 0x70, 0x80, 0x90 } },
199
    { "Snow",                 { 0xFF, 0xFA, 0xFA } },
200
    { "SpringGreen",          { 0x00, 0xFF, 0x7F } },
201
    { "SteelBlue",            { 0x46, 0x82, 0xB4 } },
202
    { "Tan",                  { 0xD2, 0xB4, 0x8C } },
203
    { "Teal",                 { 0x00, 0x80, 0x80 } },
204
    { "Thistle",              { 0xD8, 0xBF, 0xD8 } },
205
    { "Tomato",               { 0xFF, 0x63, 0x47 } },
206
    { "Turquoise",            { 0x40, 0xE0, 0xD0 } },
207
    { "Violet",               { 0xEE, 0x82, 0xEE } },
208
    { "Wheat",                { 0xF5, 0xDE, 0xB3 } },
209
    { "White",                { 0xFF, 0xFF, 0xFF } },
210
    { "WhiteSmoke",           { 0xF5, 0xF5, 0xF5 } },
211
    { "Yellow",               { 0xFF, 0xFF, 0x00 } },
212
    { "YellowGreen",          { 0x9A, 0xCD, 0x32 } },
213
};
214

    
215
static int color_table_compare(const void *lhs, const void *rhs)
216
{
217
    return strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
218
}
219

    
220
#define ALPHA_SEP '@'
221

    
222
int av_parse_color(uint8_t *rgba_color, const char *color_string, void *log_ctx)
223
{
224
    char *tail, color_string2[128];
225
    const ColorEntry *entry;
226
    av_strlcpy(color_string2, color_string, sizeof(color_string2));
227
    if ((tail = strchr(color_string2, ALPHA_SEP)))
228
        *tail++ = 0;
229
    rgba_color[3] = 255;
230

    
231
    if (!strcasecmp(color_string2, "random") || !strcasecmp(color_string2, "bikeshed")) {
232
        int rgba = av_get_random_seed();
233
        rgba_color[0] = rgba >> 24;
234
        rgba_color[1] = rgba >> 16;
235
        rgba_color[2] = rgba >> 8;
236
        rgba_color[3] = rgba;
237
    } else if (!strncmp(color_string2, "0x", 2)) {
238
        char *tail;
239
        int len = strlen(color_string2);
240
        unsigned int rgba = strtoul(color_string2, &tail, 16);
241

    
242
        if (*tail || (len != 8 && len != 10)) {
243
            av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
244
            return AVERROR(EINVAL);
245
        }
246
        if (len == 10) {
247
            rgba_color[3] = rgba;
248
            rgba >>= 8;
249
        }
250
        rgba_color[0] = rgba >> 16;
251
        rgba_color[1] = rgba >> 8;
252
        rgba_color[2] = rgba;
253
    } else {
254
        entry = bsearch(color_string2,
255
                        color_table,
256
                        FF_ARRAY_ELEMS(color_table),
257
                        sizeof(ColorEntry),
258
                        color_table_compare);
259
        if (!entry) {
260
            av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
261
            return AVERROR(EINVAL);
262
        }
263
        memcpy(rgba_color, entry->rgb_color, 3);
264
    }
265

    
266
    if (tail) {
267
        unsigned long int alpha;
268
        const char *alpha_string = tail;
269
        if (!strncmp(alpha_string, "0x", 2)) {
270
            alpha = strtoul(alpha_string, &tail, 16);
271
        } else {
272
            alpha = strtoul(alpha_string, &tail, 10);
273
            if (*tail) {
274
                double d = strtod(alpha_string, &tail);
275
                alpha = d * 255;
276
            }
277
        }
278

    
279
        if (tail == alpha_string || *tail || alpha > 255) {
280
            av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
281
                   alpha_string, color_string);
282
            return AVERROR(EINVAL);
283
        }
284
        rgba_color[3] = alpha;
285
    }
286

    
287
    return 0;
288
}
289

    
290
/**
291
 * Store the value in the field in ctx that is named like key.
292
 * ctx must be an AVClass context, storing is done using AVOptions.
293
 *
294
 * @param buf the string to parse, buf will be updated to point at the
295
 * separator just after the parsed key/value pair
296
 * @param key_val_sep a 0-terminated list of characters used to
297
 * separate key from value
298
 * @param pairs_sep a 0-terminated list of characters used to separate
299
 * two pairs from each other
300
 * @return 0 if the key/value pair has been successfully parsed and
301
 * set, or a negative value corresponding to an AVERROR code in case
302
 * of error:
303
 * AVERROR(EINVAL) if the key/value pair cannot be parsed,
304
 * the error code issued by av_set_string3() if the key/value pair
305
 * cannot be set
306
 */
307
static int parse_key_value_pair(void *ctx, const char **buf,
308
                                const char *key_val_sep, const char *pairs_sep)
309
{
310
    char *key = av_get_token(buf, key_val_sep);
311
    char *val;
312
    int ret;
313

    
314
    if (*key && strspn(*buf, key_val_sep)) {
315
        (*buf)++;
316
        val = av_get_token(buf, pairs_sep);
317
    } else {
318
        av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
319
        av_free(key);
320
        return AVERROR(EINVAL);
321
    }
322

    
323
    av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
324

    
325
    ret = av_set_string3(ctx, key, val, 1, NULL);
326
    if (ret == AVERROR(ENOENT))
327
        av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
328

    
329
    av_free(key);
330
    av_free(val);
331
    return ret;
332
}
333

    
334
int av_set_options_string(void *ctx, const char *opts,
335
                          const char *key_val_sep, const char *pairs_sep)
336
{
337
    int ret, count = 0;
338

    
339
    while (*opts) {
340
        if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
341
            return ret;
342
        count++;
343

    
344
        if (*opts)
345
            opts++;
346
    }
347

    
348
    return count;
349
}
350

    
351
#ifdef TEST
352

    
353
#undef printf
354

    
355
typedef struct TestContext
356
{
357
    const AVClass *class;
358
    int num;
359
    int toggle;
360
    char *string;
361
    int flags;
362
    AVRational rational;
363
} TestContext;
364

    
365
#define OFFSET(x) offsetof(TestContext, x)
366

    
367
#define TEST_FLAG_COOL 01
368
#define TEST_FLAG_LAME 02
369
#define TEST_FLAG_MU   04
370

    
371
static const AVOption test_options[]= {
372
{"num",      "set num",        OFFSET(num),      FF_OPT_TYPE_INT,      0,              0,        100                 },
373
{"toggle",   "set toggle",     OFFSET(toggle),   FF_OPT_TYPE_INT,      0,              0,        1                   },
374
{"rational", "set rational",   OFFSET(rational), FF_OPT_TYPE_RATIONAL, 0,              0,        10                  },
375
{"string",   "set string",     OFFSET(string),   FF_OPT_TYPE_STRING,   0,              CHAR_MIN, CHAR_MAX            },
376
{"flags",    "set flags",      OFFSET(flags),    FF_OPT_TYPE_FLAGS,    0,              0,        INT_MAX, 0, "flags" },
377
{"cool",     "set cool flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_COOL, INT_MIN,  INT_MAX, 0, "flags" },
378
{"lame",     "set lame flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_LAME, INT_MIN,  INT_MAX, 0, "flags" },
379
{"mu",       "set mu flag ",   0,                FF_OPT_TYPE_CONST,    TEST_FLAG_MU,   INT_MIN,  INT_MAX, 0, "flags" },
380
{NULL},
381
};
382

    
383
static const char *test_get_name(void *ctx)
384
{
385
    return "test";
386
}
387

    
388
static const AVClass test_class = {
389
    "TestContext",
390
    test_get_name,
391
    test_options
392
};
393

    
394
int main(void)
395
{
396
    int i;
397

    
398
    const char *strings[] = {
399
        "''",
400
        "",
401
        ":",
402
        "\\",
403
        "'",
404
        "    ''    :",
405
        "    ''  ''  :",
406
        "foo   '' :",
407
        "'foo'",
408
        "foo     ",
409
        "foo\\",
410
        "foo':  blah:blah",
411
        "foo\\:  blah:blah",
412
        "foo\'",
413
        "'foo :  '  :blahblah",
414
        "\\ :blah",
415
        "     foo",
416
        "      foo       ",
417
        "      foo     \\ ",
418
        "foo ':blah",
419
        " foo   bar    :   blahblah",
420
        "\\f\\o\\o",
421
        "'foo : \\ \\  '   : blahblah",
422
        "'\\fo\\o:': blahblah",
423
        "\\'fo\\o\\:':  foo  '  :blahblah"
424
    };
425

    
426
    for (i=0; i < FF_ARRAY_ELEMS(strings); i++) {
427
        const char *p= strings[i];
428
        printf("|%s|", p);
429
        printf(" -> |%s|", av_get_token(&p, ":"));
430
        printf(" + |%s|\n", p);
431
    }
432

    
433
    printf("\nTesting av_parse_color()\n");
434
    {
435
        uint8_t rgba[4];
436
        const char *color_names[] = {
437
            "bikeshed",
438
            "RaNdOm",
439
            "foo",
440
            "red",
441
            "Red ",
442
            "RED",
443
            "Violet",
444
            "Yellow",
445
            "Red",
446
            "0x000000",
447
            "0x0000000",
448
            "0xff000000",
449
            "0x3e34ff",
450
            "0x3e34ffaa",
451
            "0xffXXee",
452
            "0xfoobar",
453
            "0xffffeeeeeeee",
454
            "red@foo",
455
            "random@10",
456
            "0xff0000@1.0",
457
            "red@",
458
            "red@0xfff",
459
            "red@0xf",
460
            "red@2",
461
            "red@0.1",
462
            "red@-1",
463
            "red@0.5",
464
            "red@1.0",
465
            "red@256",
466
            "red@10foo",
467
            "red@-1.0",
468
            "red@-0.0",
469
        };
470

    
471
        av_log_set_level(AV_LOG_DEBUG);
472

    
473
        for (int i = 0;  i < FF_ARRAY_ELEMS(color_names); i++) {
474
            if (av_parse_color(rgba, color_names[i], NULL) >= 0)
475
                printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
476
        }
477
    }
478

    
479
    printf("\nTesting av_set_options_string()\n");
480
    {
481
        TestContext test_ctx;
482
        const char *options[] = {
483
            "",
484
            ":",
485
            "=",
486
            "foo=:",
487
            ":=foo",
488
            "=foo",
489
            "foo=",
490
            "foo",
491
            "foo=val",
492
            "foo==val",
493
            "toggle=:",
494
            "string=:",
495
            "toggle=1 : foo",
496
            "toggle=100",
497
            "toggle==1",
498
            "flags=+mu-lame : num=42: toggle=0",
499
            "num=42 : string=blahblah",
500
            "rational=0 : rational=1/2 : rational=1/-1",
501
            "rational=-1/0",
502
        };
503

    
504
        test_ctx.class = &test_class;
505
        av_opt_set_defaults2(&test_ctx, 0, 0);
506
        test_ctx.string = av_strdup("default");
507

    
508
        av_log_set_level(AV_LOG_DEBUG);
509

    
510
        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
511
            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
512
            if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
513
                av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
514
            printf("\n");
515
        }
516
    }
517

    
518
    return 0;
519
}
520

    
521
#endif