4 * Copyright (C) 2001 Szabolcs Berecz <szabi@inf.elte.hu>
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 #include "libmpcodecs/img_format.h"
41 #include "codec-cfg.h"
43 #include "stream/stream.h"
46 static const char embedded_file
[] =
47 #include "codecs.conf.h"
49 static const struct bstr builtin_codecs_conf
= {
50 .start
= (char *)embedded_file
, .len
= sizeof(embedded_file
) - 1
53 #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
54 ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
55 ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
57 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
59 #define MAX_NR_TOKEN 16
67 static int codecs_conf_release
;
68 char * codecs_file
= NULL
;
70 static int add_to_fourcc(char *s
, char *alias
, unsigned int *fourcc
,
76 /* find first unused slot */
77 for (i
= 0; i
< CODECS_MAX_FOURCC
&& fourcc
[i
] != 0xffffffff; i
++)
79 freeslots
= CODECS_MAX_FOURCC
- i
;
81 goto err_out_too_many
;
85 goto err_out_parse_error
;
86 tmp
= mmioFOURCC(s
[0], s
[1], s
[2], s
[3]);
87 for (j
= 0; j
< i
; j
++)
89 goto err_out_duplicated
;
91 map
[i
] = alias
? mmioFOURCC(alias
[0], alias
[1], alias
[2], alias
[3]) : tmp
;
94 } while ((*(s
++) == ',') && --freeslots
);
97 goto err_out_too_many
;
99 goto err_out_parse_error
;
102 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"duplicated FourCC");
105 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"too many FourCCs/formats...");
108 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error");
112 static int add_to_format(char *s
, char *alias
,unsigned int *fourcc
, unsigned int *fourccmap
)
117 /* find first unused slot */
118 for (i
= 0; i
< CODECS_MAX_FOURCC
&& fourcc
[i
] != 0xffffffff; i
++)
120 if (i
== CODECS_MAX_FOURCC
) {
121 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"too many FourCCs/formats...");
125 fourcc
[i
]=strtoul(s
,&endptr
,0);
126 if (*endptr
!= '\0') {
127 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error (format ID not a number?)");
132 fourccmap
[i
]=strtoul(alias
,&endptr
,0);
133 if (*endptr
!= '\0') {
134 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error (format ID alias not a number?)");
138 fourccmap
[i
]=fourcc
[i
];
140 for (j
= 0; j
< i
; j
++)
141 if (fourcc
[j
] == fourcc
[i
]) {
142 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"duplicated format ID");
149 static const struct {
151 const unsigned int num
;
153 // note: due to parser deficiencies/simplicity, if one format
154 // name matches the beginning of another, the longer one _must_
155 // come first in this list.
156 {"YV12", IMGFMT_YV12
},
157 {"I420", IMGFMT_I420
},
158 {"IYUV", IMGFMT_IYUV
},
159 {"NV12", IMGFMT_NV12
},
160 {"NV21", IMGFMT_NV21
},
161 {"YVU9", IMGFMT_YVU9
},
162 {"IF09", IMGFMT_IF09
},
163 {"444P16LE", IMGFMT_444P16_LE
},
164 {"444P16BE", IMGFMT_444P16_BE
},
165 {"422P16LE", IMGFMT_422P16_LE
},
166 {"422P16BE", IMGFMT_422P16_BE
},
167 {"420P16LE", IMGFMT_420P16_LE
},
168 {"420P16BE", IMGFMT_420P16_BE
},
169 {"444P16", IMGFMT_444P16
},
170 {"444P10", IMGFMT_444P10
},
171 {"444P9", IMGFMT_444P9
},
172 {"422P16", IMGFMT_422P16
},
173 {"422P10", IMGFMT_422P10
},
174 {"420P16", IMGFMT_420P16
},
175 {"420P10", IMGFMT_420P10
},
176 {"420P9", IMGFMT_420P9
},
177 {"420A", IMGFMT_420A
},
178 {"444P", IMGFMT_444P
},
179 {"422P", IMGFMT_422P
},
180 {"411P", IMGFMT_411P
},
181 {"440P", IMGFMT_440P
},
182 {"Y800", IMGFMT_Y800
},
185 {"YUY2", IMGFMT_YUY2
},
186 {"UYVY", IMGFMT_UYVY
},
187 {"YVYU", IMGFMT_YVYU
},
189 {"RGB48LE", IMGFMT_RGB48LE
},
190 {"RGB48BE", IMGFMT_RGB48BE
},
191 {"RGB4", IMGFMT_RGB4
},
192 {"RGB8", IMGFMT_RGB8
},
193 {"RGB15", IMGFMT_RGB15
},
194 {"RGB16", IMGFMT_RGB16
},
195 {"RGB24", IMGFMT_RGB24
},
196 {"RGB32", IMGFMT_RGB32
},
197 {"BGR4", IMGFMT_BGR4
},
198 {"BGR8", IMGFMT_BGR8
},
199 {"BGR15", IMGFMT_BGR15
},
200 {"BGR16", IMGFMT_BGR16
},
201 {"BGR24", IMGFMT_BGR24
},
202 {"BGR32", IMGFMT_BGR32
},
203 {"RGB1", IMGFMT_RGB1
},
204 {"BGR1", IMGFMT_BGR1
},
206 {"MPES", IMGFMT_MPEGPES
},
208 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2
},
209 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2
},
211 {"VDPAU_MPEG1",IMGFMT_VDPAU_MPEG1
},
212 {"VDPAU_MPEG2",IMGFMT_VDPAU_MPEG2
},
213 {"VDPAU_H264",IMGFMT_VDPAU_H264
},
214 {"VDPAU_WMV3",IMGFMT_VDPAU_WMV3
},
215 {"VDPAU_VC1",IMGFMT_VDPAU_VC1
},
216 {"VDPAU_MPEG4",IMGFMT_VDPAU_MPEG4
},
222 static int add_to_inout(char *sfmt
, char *sflags
, unsigned int *outfmt
,
223 unsigned char *outflags
)
226 static char *flagstr
[] = {
238 for (i
= 0; i
< CODECS_MAX_OUTFMT
&& outfmt
[i
] != 0xffffffff; i
++)
240 freeslots
= CODECS_MAX_OUTFMT
- i
;
242 goto err_out_too_many
;
247 for (j
= 0; flagstr
[j
] != NULL
; j
++)
248 if (!strncmp(sflags
, flagstr
[j
],
251 if (flagstr
[j
] == NULL
)
252 goto err_out_parse_error
;
254 sflags
+=strlen(flagstr
[j
]);
255 } while (*(sflags
++) == ',');
257 if (*(--sflags
) != '\0')
258 goto err_out_parse_error
;
262 for (j
= 0; fmt_table
[j
].name
!= NULL
; j
++)
263 if (!strncmp(sfmt
, fmt_table
[j
].name
, strlen(fmt_table
[j
].name
)))
265 if (fmt_table
[j
].name
== NULL
)
266 goto err_out_parse_error
;
267 outfmt
[i
] = fmt_table
[j
].num
;
270 sfmt
+=strlen(fmt_table
[j
].name
);
271 } while ((*(sfmt
++) == ',') && --freeslots
);
274 goto err_out_too_many
;
276 if (*(--sfmt
) != '\0')
277 goto err_out_parse_error
;
281 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"too many out...");
284 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error");
288 static int validate_codec(codecs_t
*c
, int type
)
291 char *tmp_name
= c
->name
;
293 for (i
= 0; i
< strlen(tmp_name
) && isalnum(tmp_name
[i
]); i
++)
296 if (i
< strlen(tmp_name
)) {
297 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) name is not valid!\n", c
->name
);
302 c
->info
= strdup(c
->name
);
305 if (c
->fourcc
[0] == 0xffffffff) {
306 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) does not have FourCC/format!\n", c
->name
);
312 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) does not have a driver!\n", c
->name
);
317 //FIXME: codec->driver == 4;... <- this should not be put in here...
318 //FIXME: Where are they defined ????????????
319 if (!c
->dll
&& (c
->driver
== 4 ||
320 (c
->driver
== 2 && type
== TYPE_VIDEO
))) {
321 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) needs a 'dll'!\n", c
->name
);
324 // FIXME: Can guid.f1 be 0? How does one know that it was not given?
325 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
327 if (type
== TYPE_VIDEO
)
328 if (c
->outfmt
[0] == 0xffffffff) {
329 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) needs an 'outfmt'!\n", c
->name
);
336 static int add_comment(char *s
, char **d
)
346 if (!(*d
= realloc(*d
, pos
+ strlen(s
) + 1))) {
347 mp_tmsg(MSGT_CODECCFG
,MSGL_FATAL
,"Can't allocate memory for comment. ");
354 static short get_cpuflags(char *s
)
356 static char *flagstr
[] = {
366 for (i
= 0; flagstr
[i
]; i
++)
367 if (!strncmp(s
, flagstr
[i
], strlen(flagstr
[i
])))
370 goto err_out_parse_error
;
372 s
+= strlen(flagstr
[i
]);
373 } while (*(s
++) == ',');
376 goto err_out_parse_error
;
383 static struct bstr filetext
;
384 static int line_num
= 0;
386 static char *token
[MAX_NR_TOKEN
];
387 static int read_nextline
= 1;
389 static int get_token(int min
, int max
)
395 if (max
>= MAX_NR_TOKEN
) {
396 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"get_token(): max >= MAX_MR_TOKEN!");
400 memset(token
, 0x00, sizeof(*token
) * max
);
405 struct bstr nextline
= bstr_getline(filetext
, &filetext
);
406 line
= nextline
.start
;
407 line
[nextline
.len
- 1] = 0;
412 for (i
= 0; i
< max
; i
++) {
413 while (isspace(line
[line_pos
]))
415 if (line
[line_pos
] == '\0' || line
[line_pos
] == '#' ||
416 line
[line_pos
] == ';') {
422 token
[i
] = line
+ line_pos
;
424 if (c
== '"' || c
== '\'') {
426 while (line
[++line_pos
] != c
&& line
[line_pos
])
429 for (/* NOTHING */; !isspace(line
[line_pos
]) &&
430 line
[line_pos
]; line_pos
++)
433 if (!line
[line_pos
]) {
439 line
[line_pos
] = '\0';
451 static codecs_t
*video_codecs
=NULL
;
452 static codecs_t
*audio_codecs
=NULL
;
453 static int nr_vcodecs
= 0;
454 static int nr_acodecs
= 0;
456 int parse_codec_cfg(const char *cfgfile
)
458 codecs_t
*codec
= NULL
; // current codec
459 codecs_t
**codecsp
= NULL
;// points to audio_codecs or to video_codecs
460 char *endptr
; // strtoul()...
462 int codec_type
; /* TYPE_VIDEO/TYPE_AUDIO */
466 for (struct bstr s
= builtin_codecs_conf
; ; bstr_getline(s
, &s
)) {
469 if (bstr_eatstart0(&s
, "release ")) {
470 codec_cfg_min
= atoi(s
.start
);
475 // in case we call it a second time
476 codecs_uninit_free();
482 // Avoid printing errors from open_stream when trying optional files
483 if (!mp_path_exists(cfgfile
)) {
484 mp_tmsg(MSGT_CODECCFG
, MSGL_V
,
485 "No optional codecs config file: %s\n", cfgfile
);
488 mp_msg(MSGT_CODECCFG
, MSGL_V
, "Reading codec config file: %s\n",
490 struct stream
*s
= open_stream(cfgfile
, NULL
, NULL
);
493 filetext
= stream_read_complete(s
, NULL
, 10000000, 1);
498 // Parsing modifies the data
499 filetext
= bstrdup(NULL
, builtin_codecs_conf
);
500 void *tmpmem
= filetext
.start
;
505 * this only catches release lines at the start of
506 * codecs.conf, before audiocodecs and videocodecs.
508 while ((tmp
= get_token(1, 1)) == RET_EOL
)
512 if (!strcmp(token
[0], "release")) {
513 if (get_token(1, 2) < 0)
514 goto err_out_parse_error
;
515 tmp
= atoi(token
[0]);
516 if (tmp
< codec_cfg_min
)
517 goto err_out_release_num
;
518 codecs_conf_release
= tmp
;
519 while ((tmp
= get_token(1, 1)) == RET_EOL
)
524 goto err_out_release_num
;
527 * check if the next block starts with 'audiocodec' or
530 if (!strcmp(token
[0], "audiocodec") || !strcmp(token
[0], "videocodec"))
532 goto err_out_parse_error
;
534 while ((tmp
= get_token(1, 1)) != RET_EOF
) {
537 if (!strcmp(token
[0], "audiocodec") ||
538 !strcmp(token
[0], "videocodec")) {
539 if (!validate_codec(codec
, codec_type
))
540 goto err_out_not_valid
;
542 if (*token
[0] == 'v') {
543 codec_type
= TYPE_VIDEO
;
544 nr_codecsp
= &nr_vcodecs
;
545 codecsp
= &video_codecs
;
546 } else if (*token
[0] == 'a') {
547 codec_type
= TYPE_AUDIO
;
548 nr_codecsp
= &nr_acodecs
;
549 codecsp
= &audio_codecs
;
552 mp_msg(MSGT_CODECCFG
,MSGL_ERR
,"picsba\n");
556 if (!(*codecsp
= realloc(*codecsp
,
557 sizeof(codecs_t
) * (*nr_codecsp
+ 2)))) {
558 mp_tmsg(MSGT_CODECCFG
,MSGL_FATAL
,"Can't realloc '*codecsp': %s\n", strerror(errno
));
561 codec
=*codecsp
+ *nr_codecsp
;
563 memset(codec
,0,sizeof(codecs_t
));
564 memset(codec
->fourcc
, 0xff, sizeof(codec
->fourcc
));
565 memset(codec
->outfmt
, 0xff, sizeof(codec
->outfmt
));
566 memset(codec
->infmt
, 0xff, sizeof(codec
->infmt
));
568 if (get_token(1, 1) < 0)
569 goto err_out_parse_error
;
570 for (i
= 0; i
< *nr_codecsp
- 1; i
++) {
571 if(( (*codecsp
)[i
].name
!=NULL
) &&
572 (!strcmp(token
[0], (*codecsp
)[i
].name
)) ) {
573 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Codec name '%s' isn't unique.", token
[0]);
574 goto err_out_print_linenum
;
577 if (!(codec
->name
= strdup(token
[0]))) {
578 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'name': %s\n", strerror(errno
));
581 } else if (!strcmp(token
[0], "info")) {
582 if (codec
->info
|| get_token(1, 1) < 0)
583 goto err_out_parse_error
;
584 if (!(codec
->info
= strdup(token
[0]))) {
585 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'info': %s\n", strerror(errno
));
588 } else if (!strcmp(token
[0], "comment")) {
589 if (get_token(1, 1) < 0)
590 goto err_out_parse_error
;
591 add_comment(token
[0], &codec
->comment
);
592 } else if (!strcmp(token
[0], "fourcc")) {
593 if (get_token(1, 2) < 0)
594 goto err_out_parse_error
;
595 if (!add_to_fourcc(token
[0], token
[1],
598 goto err_out_print_linenum
;
599 } else if (!strcmp(token
[0], "format")) {
600 if (get_token(1, 2) < 0)
601 goto err_out_parse_error
;
602 if (!add_to_format(token
[0], token
[1],
603 codec
->fourcc
,codec
->fourccmap
))
604 goto err_out_print_linenum
;
605 } else if (!strcmp(token
[0], "driver")) {
606 if (get_token(1, 1) < 0)
607 goto err_out_parse_error
;
608 if (!(codec
->drv
= strdup(token
[0]))) {
609 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'driver': %s\n", strerror(errno
));
612 } else if (!strcmp(token
[0], "dll")) {
613 if (get_token(1, 1) < 0)
614 goto err_out_parse_error
;
615 if (!(codec
->dll
= strdup(token
[0]))) {
616 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'dll': %s", strerror(errno
));
619 } else if (!strcmp(token
[0], "guid")) {
620 if (get_token(11, 11) < 0)
621 goto err_out_parse_error
;
622 codec
->guid
.f1
=strtoul(token
[0],&endptr
,0);
623 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
625 goto err_out_parse_error
;
626 codec
->guid
.f2
=strtoul(token
[1],&endptr
,0);
627 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
629 goto err_out_parse_error
;
630 codec
->guid
.f3
=strtoul(token
[2],&endptr
,0);
631 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
633 goto err_out_parse_error
;
634 for (i
= 0; i
< 8; i
++) {
635 codec
->guid
.f4
[i
]=strtoul(token
[i
+ 3],&endptr
,0);
636 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
638 goto err_out_parse_error
;
640 } else if (!strcmp(token
[0], "out")) {
641 if (get_token(1, 2) < 0)
642 goto err_out_parse_error
;
643 if (!add_to_inout(token
[0], token
[1], codec
->outfmt
,
645 goto err_out_print_linenum
;
646 } else if (!strcmp(token
[0], "in")) {
647 if (get_token(1, 2) < 0)
648 goto err_out_parse_error
;
649 if (!add_to_inout(token
[0], token
[1], codec
->infmt
,
651 goto err_out_print_linenum
;
652 } else if (!strcmp(token
[0], "flags")) {
653 if (get_token(1, 1) < 0)
654 goto err_out_parse_error
;
655 if (!strcmp(token
[0], "seekable"))
656 codec
->flags
|= CODECS_FLAG_SEEKABLE
;
657 else if (!strcmp(token
[0], "align16"))
658 codec
->flags
|= CODECS_FLAG_ALIGN16
;
660 goto err_out_parse_error
;
661 } else if (!strcmp(token
[0], "status")) {
662 if (get_token(1, 1) < 0)
663 goto err_out_parse_error
;
664 if (!strcasecmp(token
[0], "working"))
665 codec
->status
= CODECS_STATUS_WORKING
;
666 else if (!strcasecmp(token
[0], "crashing"))
667 codec
->status
= CODECS_STATUS_NOT_WORKING
;
668 else if (!strcasecmp(token
[0], "untested"))
669 codec
->status
= CODECS_STATUS_UNTESTED
;
670 else if (!strcasecmp(token
[0], "buggy"))
671 codec
->status
= CODECS_STATUS_PROBLEMS
;
673 goto err_out_parse_error
;
674 } else if (!strcmp(token
[0], "cpuflags")) {
675 if (get_token(1, 1) < 0)
676 goto err_out_parse_error
;
677 if (!(codec
->cpuflags
= get_cpuflags(token
[0])))
678 goto err_out_parse_error
;
680 goto err_out_parse_error
;
682 if (!validate_codec(codec
, codec_type
))
683 goto err_out_not_valid
;
684 mp_tmsg(MSGT_CODECCFG
, MSGL_V
, "%d audio & %d video codecs\n", nr_acodecs
,
686 if(video_codecs
) video_codecs
[nr_vcodecs
].name
= NULL
;
687 if(audio_codecs
) audio_codecs
[nr_acodecs
].name
= NULL
;
694 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error");
695 err_out_print_linenum
:
698 codecs_uninit_free();
705 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Codec is not defined correctly.");
706 goto err_out_print_linenum
;
708 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"This codecs.conf is too old and incompatible with this MPlayer release!");
709 goto err_out_print_linenum
;
712 static void codecs_free(codecs_t
* codecs
,int count
) {
714 for ( i
= 0; i
< count
; i
++)
715 if ( codecs
[i
].name
) {
716 free(codecs
[i
].name
);
717 free(codecs
[i
].info
);
718 free(codecs
[i
].comment
);
725 void codecs_uninit_free(void) {
727 codecs_free(video_codecs
,nr_vcodecs
);
730 codecs_free(audio_codecs
,nr_acodecs
);
734 codecs_t
*find_audio_codec(unsigned int fourcc
, unsigned int *fourccmap
,
735 codecs_t
*start
, int force
)
737 return find_codec(fourcc
, fourccmap
, start
, 1, force
);
740 codecs_t
*find_video_codec(unsigned int fourcc
, unsigned int *fourccmap
,
741 codecs_t
*start
, int force
)
743 return find_codec(fourcc
, fourccmap
, start
, 0, force
);
746 codecs_t
* find_codec(unsigned int fourcc
,unsigned int *fourccmap
,
747 codecs_t
*start
, int audioflag
, int force
)
754 for (/* NOTHING */; start
->name
; start
++) {
755 for (j
= 0; j
< CODECS_MAX_FOURCC
; j
++) {
756 if (start
->fourcc
[j
] == fourcc
) {
758 *fourccmap
= start
->fourccmap
[j
];
774 for (/* NOTHING */; i
--; c
++) {
775 if(start
&& c
<=start
) continue;
776 for (j
= 0; j
< CODECS_MAX_FOURCC
; j
++) {
777 // FIXME: do NOT hardwire 'null' name here:
778 if (c
->fourcc
[j
]==fourcc
|| !strcmp(c
->drv
,"null")) {
780 *fourccmap
= c
->fourccmap
[j
];
790 void stringset_init(stringset_t
*set
) {
791 *set
= calloc(1, sizeof(char *));
794 void stringset_free(stringset_t
*set
) {
796 while ((*set
)[count
]) free((*set
)[count
++]);
801 void stringset_add(stringset_t
*set
, const char *str
) {
803 while ((*set
)[count
]) count
++;
805 *set
= realloc(*set
, sizeof(char *) * (count
+ 1));
806 (*set
)[count
- 1] = strdup(str
);
807 (*set
)[count
] = NULL
;
810 int stringset_test(stringset_t
*set
, const char *str
) {
812 for (s
= *set
; *s
; s
++)
813 if (strcmp(*s
, str
) == 0)
818 void list_codecs(int audioflag
){
825 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"ac: afm: status: info: [lib/dll]\n");
829 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"vc: vfm: status: info: [lib/dll]\n");
832 for (/* NOTHING */; i
--; c
++) {
835 case CODECS_STATUS_WORKING
: s
="working ";break;
836 case CODECS_STATUS_PROBLEMS
: s
="problems";break;
837 case CODECS_STATUS_NOT_WORKING
: s
="crashing";break;
838 case CODECS_STATUS_UNTESTED
: s
="untested";break;
841 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"%-11s %-9s %s %s [%s]\n",c
->name
,c
->drv
,s
,c
->info
,c
->dll
);
843 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"%-11s %-9s %s %s\n",c
->name
,c
->drv
,s
,c
->info
);