4 * to compile test application:
5 * cc -I. -DTESTING -o codec-cfg-test codec-cfg.c mp_msg.o osdep/getch2.o -ltermcap
6 * to compile CODECS2HTML:
7 * gcc -DCODECS2HTML -o codecs2html codec-cfg.c mp_msg.o
9 * TODO: implement informat in CODECS2HTML too
11 * Copyright (C) 2001 Szabolcs Berecz <szabi@inf.elte.hu>
13 * This file is part of MPlayer.
15 * MPlayer is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * MPlayer is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License along
26 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
48 #define mp_tmsg mp_msg
50 #define mp_msg(t, l, m, args...) fprintf(stderr, m, ##args)
52 #define mp_msg(t, l, ...) fprintf(stderr, __VA_ARGS__)
57 #include "libmpcodecs/img_format.h"
58 #include "codec-cfg.h"
61 #define CODEC_CFG_MIN 20100000
63 #include "codecs.conf.h"
66 #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
67 ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
68 ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
70 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
72 #define MAX_NR_TOKEN 16
74 #define MAX_LINE_LEN 1000
82 static int codecs_conf_release
;
83 char * codecs_file
= NULL
;
85 static int add_to_fourcc(char *s
, char *alias
, unsigned int *fourcc
,
91 /* find first unused slot */
92 for (i
= 0; i
< CODECS_MAX_FOURCC
&& fourcc
[i
] != 0xffffffff; i
++)
94 freeslots
= CODECS_MAX_FOURCC
- i
;
96 goto err_out_too_many
;
99 tmp
= mmioFOURCC(s
[0], s
[1], s
[2], s
[3]);
100 for (j
= 0; j
< i
; j
++)
101 if (tmp
== fourcc
[j
])
102 goto err_out_duplicated
;
104 map
[i
] = alias
? mmioFOURCC(alias
[0], alias
[1], alias
[2], alias
[3]) : tmp
;
107 } while ((*(s
++) == ',') && --freeslots
);
110 goto err_out_too_many
;
112 goto err_out_parse_error
;
115 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"duplicated FourCC");
118 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"too many FourCCs/formats...");
121 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error");
125 static int add_to_format(char *s
, char *alias
,unsigned int *fourcc
, unsigned int *fourccmap
)
130 /* find first unused slot */
131 for (i
= 0; i
< CODECS_MAX_FOURCC
&& fourcc
[i
] != 0xffffffff; i
++)
133 if (i
== CODECS_MAX_FOURCC
) {
134 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"too many FourCCs/formats...");
138 fourcc
[i
]=strtoul(s
,&endptr
,0);
139 if (*endptr
!= '\0') {
140 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error (format ID not a number?)");
145 fourccmap
[i
]=strtoul(alias
,&endptr
,0);
146 if (*endptr
!= '\0') {
147 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error (format ID alias not a number?)");
151 fourccmap
[i
]=fourcc
[i
];
153 for (j
= 0; j
< i
; j
++)
154 if (fourcc
[j
] == fourcc
[i
]) {
155 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"duplicated format ID");
162 static const struct {
164 const unsigned int num
;
166 // note: due to parser deficiencies/simplicity, if one format
167 // name matches the beginning of another, the longer one _must_
168 // come first in this list.
169 {"YV12", IMGFMT_YV12
},
170 {"I420", IMGFMT_I420
},
171 {"IYUV", IMGFMT_IYUV
},
172 {"NV12", IMGFMT_NV12
},
173 {"NV21", IMGFMT_NV21
},
174 {"YVU9", IMGFMT_YVU9
},
175 {"IF09", IMGFMT_IF09
},
176 {"444P16LE", IMGFMT_444P16_LE
},
177 {"444P16BE", IMGFMT_444P16_BE
},
178 {"422P16LE", IMGFMT_422P16_LE
},
179 {"422P16BE", IMGFMT_422P16_BE
},
180 {"420P16LE", IMGFMT_420P16_LE
},
181 {"420P16BE", IMGFMT_420P16_BE
},
182 {"444P16", IMGFMT_444P16
},
183 {"444P10", IMGFMT_444P10
},
184 {"444P9", IMGFMT_444P9
},
185 {"422P16", IMGFMT_422P16
},
186 {"422P10", IMGFMT_422P10
},
187 {"420P16", IMGFMT_420P16
},
188 {"420P10", IMGFMT_420P10
},
189 {"420P9", IMGFMT_420P9
},
190 {"420A", IMGFMT_420A
},
191 {"444P", IMGFMT_444P
},
192 {"422P", IMGFMT_422P
},
193 {"411P", IMGFMT_411P
},
194 {"440P", IMGFMT_440P
},
195 {"Y800", IMGFMT_Y800
},
198 {"YUY2", IMGFMT_YUY2
},
199 {"UYVY", IMGFMT_UYVY
},
200 {"YVYU", IMGFMT_YVYU
},
202 {"RGB48LE", IMGFMT_RGB48LE
},
203 {"RGB48BE", IMGFMT_RGB48BE
},
204 {"RGB4", IMGFMT_RGB4
},
205 {"RGB8", IMGFMT_RGB8
},
206 {"RGB15", IMGFMT_RGB15
},
207 {"RGB16", IMGFMT_RGB16
},
208 {"RGB24", IMGFMT_RGB24
},
209 {"RGB32", IMGFMT_RGB32
},
210 {"BGR4", IMGFMT_BGR4
},
211 {"BGR8", IMGFMT_BGR8
},
212 {"BGR15", IMGFMT_BGR15
},
213 {"BGR16", IMGFMT_BGR16
},
214 {"BGR24", IMGFMT_BGR24
},
215 {"BGR32", IMGFMT_BGR32
},
216 {"RGB1", IMGFMT_RGB1
},
217 {"BGR1", IMGFMT_BGR1
},
219 {"MPES", IMGFMT_MPEGPES
},
221 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2
},
222 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2
},
224 {"VDPAU_MPEG1",IMGFMT_VDPAU_MPEG1
},
225 {"VDPAU_MPEG2",IMGFMT_VDPAU_MPEG2
},
226 {"VDPAU_H264",IMGFMT_VDPAU_H264
},
227 {"VDPAU_WMV3",IMGFMT_VDPAU_WMV3
},
228 {"VDPAU_VC1",IMGFMT_VDPAU_VC1
},
229 {"VDPAU_MPEG4",IMGFMT_VDPAU_MPEG4
},
235 static int add_to_inout(char *sfmt
, char *sflags
, unsigned int *outfmt
,
236 unsigned char *outflags
)
239 static char *flagstr
[] = {
251 for (i
= 0; i
< CODECS_MAX_OUTFMT
&& outfmt
[i
] != 0xffffffff; i
++)
253 freeslots
= CODECS_MAX_OUTFMT
- i
;
255 goto err_out_too_many
;
260 for (j
= 0; flagstr
[j
] != NULL
; j
++)
261 if (!strncmp(sflags
, flagstr
[j
],
264 if (flagstr
[j
] == NULL
)
265 goto err_out_parse_error
;
267 sflags
+=strlen(flagstr
[j
]);
268 } while (*(sflags
++) == ',');
270 if (*(--sflags
) != '\0')
271 goto err_out_parse_error
;
275 for (j
= 0; fmt_table
[j
].name
!= NULL
; j
++)
276 if (!strncmp(sfmt
, fmt_table
[j
].name
, strlen(fmt_table
[j
].name
)))
278 if (fmt_table
[j
].name
== NULL
)
279 goto err_out_parse_error
;
280 outfmt
[i
] = fmt_table
[j
].num
;
283 sfmt
+=strlen(fmt_table
[j
].name
);
284 } while ((*(sfmt
++) == ',') && --freeslots
);
287 goto err_out_too_many
;
289 if (*(--sfmt
) != '\0')
290 goto err_out_parse_error
;
294 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"too many out...");
297 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error");
301 static int validate_codec(codecs_t
*c
, int type
)
304 char *tmp_name
= c
->name
;
306 for (i
= 0; i
< strlen(tmp_name
) && isalnum(tmp_name
[i
]); i
++)
309 if (i
< strlen(tmp_name
)) {
310 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) name is not valid!\n", c
->name
);
315 c
->info
= strdup(c
->name
);
318 if (c
->fourcc
[0] == 0xffffffff) {
319 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) does not have FourCC/format!\n", c
->name
);
325 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) does not have a driver!\n", c
->name
);
330 //FIXME: codec->driver == 4;... <- this should not be put in here...
331 //FIXME: Where are they defined ????????????
332 if (!c
->dll
&& (c
->driver
== 4 ||
333 (c
->driver
== 2 && type
== TYPE_VIDEO
))) {
334 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) needs a 'dll'!\n", c
->name
);
337 // FIXME: Can guid.f1 be 0? How does one know that it was not given?
338 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
340 if (type
== TYPE_VIDEO
)
341 if (c
->outfmt
[0] == 0xffffffff) {
342 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"\ncodec(%s) needs an 'outfmt'!\n", c
->name
);
349 static int add_comment(char *s
, char **d
)
359 if (!(*d
= realloc(*d
, pos
+ strlen(s
) + 1))) {
360 mp_tmsg(MSGT_CODECCFG
,MSGL_FATAL
,"Can't allocate memory for comment. ");
367 static short get_cpuflags(char *s
)
369 static char *flagstr
[] = {
379 for (i
= 0; flagstr
[i
]; i
++)
380 if (!strncmp(s
, flagstr
[i
], strlen(flagstr
[i
])))
383 goto err_out_parse_error
;
385 s
+= strlen(flagstr
[i
]);
386 } while (*(s
++) == ',');
389 goto err_out_parse_error
;
397 static int line_num
= 0;
399 static char *token
[MAX_NR_TOKEN
];
400 static int read_nextline
= 1;
402 static int get_token(int min
, int max
)
408 if (max
>= MAX_NR_TOKEN
) {
409 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"get_token(): max >= MAX_MR_TOKEN!");
413 memset(token
, 0x00, sizeof(*token
) * max
);
416 if (!fgets(line
, MAX_LINE_LEN
, fp
))
422 for (i
= 0; i
< max
; i
++) {
423 while (isspace(line
[line_pos
]))
425 if (line
[line_pos
] == '\0' || line
[line_pos
] == '#' ||
426 line
[line_pos
] == ';') {
432 token
[i
] = line
+ line_pos
;
434 if (c
== '"' || c
== '\'') {
436 while (line
[++line_pos
] != c
&& line
[line_pos
])
439 for (/* NOTHING */; !isspace(line
[line_pos
]) &&
440 line
[line_pos
]; line_pos
++)
443 if (!line
[line_pos
]) {
449 line
[line_pos
] = '\0';
461 static codecs_t
*video_codecs
=NULL
;
462 static codecs_t
*audio_codecs
=NULL
;
463 static int nr_vcodecs
= 0;
464 static int nr_acodecs
= 0;
466 int parse_codec_cfg(const char *cfgfile
)
468 codecs_t
*codec
= NULL
; // current codec
469 codecs_t
**codecsp
= NULL
;// points to audio_codecs or to video_codecs
470 char *endptr
; // strtoul()...
472 int codec_type
; /* TYPE_VIDEO/TYPE_AUDIO */
475 // in case we call it a second time
476 codecs_uninit_free();
485 /* following casts are harmless since {video,audio}_codecs will stay
486 * untouched in this case */
487 video_codecs
= (codecs_t
*)builtin_video_codecs
;
488 audio_codecs
= (codecs_t
*)builtin_audio_codecs
;
489 nr_vcodecs
= sizeof(builtin_video_codecs
)/sizeof(codecs_t
);
490 nr_acodecs
= sizeof(builtin_audio_codecs
)/sizeof(codecs_t
);
495 mp_tmsg(MSGT_CODECCFG
,MSGL_V
,"Reading %s: ", cfgfile
);
497 if ((fp
= fopen(cfgfile
, "r")) == NULL
) {
498 mp_tmsg(MSGT_CODECCFG
,MSGL_V
,"Can't open '%s': %s\n", cfgfile
, strerror(errno
));
502 if ((line
= malloc(MAX_LINE_LEN
+ 1)) == NULL
) {
503 mp_tmsg(MSGT_CODECCFG
,MSGL_FATAL
,"Can't get memory for 'line': %s\n", strerror(errno
));
509 * this only catches release lines at the start of
510 * codecs.conf, before audiocodecs and videocodecs.
512 while ((tmp
= get_token(1, 1)) == RET_EOL
)
516 if (!strcmp(token
[0], "release")) {
517 if (get_token(1, 2) < 0)
518 goto err_out_parse_error
;
519 tmp
= atoi(token
[0]);
520 if (tmp
< CODEC_CFG_MIN
)
521 goto err_out_release_num
;
522 codecs_conf_release
= tmp
;
523 while ((tmp
= get_token(1, 1)) == RET_EOL
)
528 goto err_out_release_num
;
531 * check if the next block starts with 'audiocodec' or
534 if (!strcmp(token
[0], "audiocodec") || !strcmp(token
[0], "videocodec"))
536 goto err_out_parse_error
;
538 while ((tmp
= get_token(1, 1)) != RET_EOF
) {
541 if (!strcmp(token
[0], "audiocodec") ||
542 !strcmp(token
[0], "videocodec")) {
543 if (!validate_codec(codec
, codec_type
))
544 goto err_out_not_valid
;
546 if (*token
[0] == 'v') {
547 codec_type
= TYPE_VIDEO
;
548 nr_codecsp
= &nr_vcodecs
;
549 codecsp
= &video_codecs
;
550 } else if (*token
[0] == 'a') {
551 codec_type
= TYPE_AUDIO
;
552 nr_codecsp
= &nr_acodecs
;
553 codecsp
= &audio_codecs
;
556 mp_msg(MSGT_CODECCFG
,MSGL_ERR
,"picsba\n");
560 if (!(*codecsp
= realloc(*codecsp
,
561 sizeof(codecs_t
) * (*nr_codecsp
+ 2)))) {
562 mp_tmsg(MSGT_CODECCFG
,MSGL_FATAL
,"Can't realloc '*codecsp': %s\n", strerror(errno
));
565 codec
=*codecsp
+ *nr_codecsp
;
567 memset(codec
,0,sizeof(codecs_t
));
568 memset(codec
->fourcc
, 0xff, sizeof(codec
->fourcc
));
569 memset(codec
->outfmt
, 0xff, sizeof(codec
->outfmt
));
570 memset(codec
->infmt
, 0xff, sizeof(codec
->infmt
));
572 if (get_token(1, 1) < 0)
573 goto err_out_parse_error
;
574 for (i
= 0; i
< *nr_codecsp
- 1; i
++) {
575 if(( (*codecsp
)[i
].name
!=NULL
) &&
576 (!strcmp(token
[0], (*codecsp
)[i
].name
)) ) {
577 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Codec name '%s' isn't unique.", token
[0]);
578 goto err_out_print_linenum
;
581 if (!(codec
->name
= strdup(token
[0]))) {
582 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'name': %s\n", strerror(errno
));
585 } else if (!strcmp(token
[0], "info")) {
586 if (codec
->info
|| get_token(1, 1) < 0)
587 goto err_out_parse_error
;
588 if (!(codec
->info
= strdup(token
[0]))) {
589 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'info': %s\n", strerror(errno
));
592 } else if (!strcmp(token
[0], "comment")) {
593 if (get_token(1, 1) < 0)
594 goto err_out_parse_error
;
595 add_comment(token
[0], &codec
->comment
);
596 } else if (!strcmp(token
[0], "fourcc")) {
597 if (get_token(1, 2) < 0)
598 goto err_out_parse_error
;
599 if (!add_to_fourcc(token
[0], token
[1],
602 goto err_out_print_linenum
;
603 } else if (!strcmp(token
[0], "format")) {
604 if (get_token(1, 2) < 0)
605 goto err_out_parse_error
;
606 if (!add_to_format(token
[0], token
[1],
607 codec
->fourcc
,codec
->fourccmap
))
608 goto err_out_print_linenum
;
609 } else if (!strcmp(token
[0], "driver")) {
610 if (get_token(1, 1) < 0)
611 goto err_out_parse_error
;
612 if (!(codec
->drv
= strdup(token
[0]))) {
613 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'driver': %s\n", strerror(errno
));
616 } else if (!strcmp(token
[0], "dll")) {
617 if (get_token(1, 1) < 0)
618 goto err_out_parse_error
;
619 if (!(codec
->dll
= strdup(token
[0]))) {
620 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Can't strdup -> 'dll': %s", strerror(errno
));
623 } else if (!strcmp(token
[0], "guid")) {
624 if (get_token(11, 11) < 0)
625 goto err_out_parse_error
;
626 codec
->guid
.f1
=strtoul(token
[0],&endptr
,0);
627 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
629 goto err_out_parse_error
;
630 codec
->guid
.f2
=strtoul(token
[1],&endptr
,0);
631 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
633 goto err_out_parse_error
;
634 codec
->guid
.f3
=strtoul(token
[2],&endptr
,0);
635 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
637 goto err_out_parse_error
;
638 for (i
= 0; i
< 8; i
++) {
639 codec
->guid
.f4
[i
]=strtoul(token
[i
+ 3],&endptr
,0);
640 if ((*endptr
!= ',' || *(endptr
+ 1) != '\0') &&
642 goto err_out_parse_error
;
644 } else if (!strcmp(token
[0], "out")) {
645 if (get_token(1, 2) < 0)
646 goto err_out_parse_error
;
647 if (!add_to_inout(token
[0], token
[1], codec
->outfmt
,
649 goto err_out_print_linenum
;
650 } else if (!strcmp(token
[0], "in")) {
651 if (get_token(1, 2) < 0)
652 goto err_out_parse_error
;
653 if (!add_to_inout(token
[0], token
[1], codec
->infmt
,
655 goto err_out_print_linenum
;
656 } else if (!strcmp(token
[0], "flags")) {
657 if (get_token(1, 1) < 0)
658 goto err_out_parse_error
;
659 if (!strcmp(token
[0], "seekable"))
660 codec
->flags
|= CODECS_FLAG_SEEKABLE
;
661 else if (!strcmp(token
[0], "align16"))
662 codec
->flags
|= CODECS_FLAG_ALIGN16
;
664 goto err_out_parse_error
;
665 } else if (!strcmp(token
[0], "status")) {
666 if (get_token(1, 1) < 0)
667 goto err_out_parse_error
;
668 if (!strcasecmp(token
[0], "working"))
669 codec
->status
= CODECS_STATUS_WORKING
;
670 else if (!strcasecmp(token
[0], "crashing"))
671 codec
->status
= CODECS_STATUS_NOT_WORKING
;
672 else if (!strcasecmp(token
[0], "untested"))
673 codec
->status
= CODECS_STATUS_UNTESTED
;
674 else if (!strcasecmp(token
[0], "buggy"))
675 codec
->status
= CODECS_STATUS_PROBLEMS
;
677 goto err_out_parse_error
;
678 } else if (!strcmp(token
[0], "cpuflags")) {
679 if (get_token(1, 1) < 0)
680 goto err_out_parse_error
;
681 if (!(codec
->cpuflags
= get_cpuflags(token
[0])))
682 goto err_out_parse_error
;
684 goto err_out_parse_error
;
686 if (!validate_codec(codec
, codec_type
))
687 goto err_out_not_valid
;
688 mp_tmsg(MSGT_CODECCFG
,MSGL_INFO
,"%d audio & %d video codecs\n", nr_acodecs
, nr_vcodecs
);
689 if(video_codecs
) video_codecs
[nr_vcodecs
].name
= NULL
;
690 if(audio_codecs
) audio_codecs
[nr_acodecs
].name
= NULL
;
698 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"parse error");
699 err_out_print_linenum
:
702 codecs_uninit_free();
710 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"Codec is not defined correctly.");
711 goto err_out_print_linenum
;
713 mp_tmsg(MSGT_CODECCFG
,MSGL_ERR
,"This codecs.conf is too old and incompatible with this MPlayer release!");
714 goto err_out_print_linenum
;
717 static void codecs_free(codecs_t
* codecs
,int count
) {
719 for ( i
= 0; i
< count
; i
++)
720 if ( codecs
[i
].name
) {
721 free(codecs
[i
].name
);
722 free(codecs
[i
].info
);
723 free(codecs
[i
].comment
);
730 void codecs_uninit_free(void) {
732 codecs_free(video_codecs
,nr_vcodecs
);
735 codecs_free(audio_codecs
,nr_acodecs
);
739 codecs_t
*find_audio_codec(unsigned int fourcc
, unsigned int *fourccmap
,
740 codecs_t
*start
, int force
)
742 return find_codec(fourcc
, fourccmap
, start
, 1, force
);
745 codecs_t
*find_video_codec(unsigned int fourcc
, unsigned int *fourccmap
,
746 codecs_t
*start
, int force
)
748 return find_codec(fourcc
, fourccmap
, start
, 0, force
);
751 codecs_t
* find_codec(unsigned int fourcc
,unsigned int *fourccmap
,
752 codecs_t
*start
, int audioflag
, int force
)
759 for (/* NOTHING */; start
->name
; start
++) {
760 for (j
= 0; j
< CODECS_MAX_FOURCC
; j
++) {
761 if (start
->fourcc
[j
] == fourcc
) {
763 *fourccmap
= start
->fourccmap
[j
];
779 for (/* NOTHING */; i
--; c
++) {
780 if(start
&& c
<=start
) continue;
781 for (j
= 0; j
< CODECS_MAX_FOURCC
; j
++) {
782 // FIXME: do NOT hardwire 'null' name here:
783 if (c
->fourcc
[j
]==fourcc
|| !strcmp(c
->drv
,"null")) {
785 *fourccmap
= c
->fourccmap
[j
];
795 void stringset_init(stringset_t
*set
) {
796 *set
= calloc(1, sizeof(char *));
799 void stringset_free(stringset_t
*set
) {
801 while ((*set
)[count
]) free((*set
)[count
++]);
806 void stringset_add(stringset_t
*set
, const char *str
) {
808 while ((*set
)[count
]) count
++;
810 *set
= realloc(*set
, sizeof(char *) * (count
+ 1));
811 (*set
)[count
- 1] = strdup(str
);
812 (*set
)[count
] = NULL
;
815 int stringset_test(stringset_t
*set
, const char *str
) {
817 for (s
= *set
; *s
; s
++)
818 if (strcmp(*s
, str
) == 0)
823 void list_codecs(int audioflag
){
830 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"ac: afm: status: info: [lib/dll]\n");
834 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"vc: vfm: status: info: [lib/dll]\n");
837 for (/* NOTHING */; i
--; c
++) {
840 case CODECS_STATUS_WORKING
: s
="working ";break;
841 case CODECS_STATUS_PROBLEMS
: s
="problems";break;
842 case CODECS_STATUS_NOT_WORKING
: s
="crashing";break;
843 case CODECS_STATUS_UNTESTED
: s
="untested";break;
846 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"%-11s %-9s %s %s [%s]\n",c
->name
,c
->drv
,s
,c
->info
,c
->dll
);
848 mp_msg(MSGT_CODECCFG
,MSGL_INFO
,"%-11s %-9s %s %s\n",c
->name
,c
->drv
,s
,c
->info
);
854 static void wrapline(FILE *f2
,char *s
){
861 if(c
==',') fprintf(f2
,"<br>"); else fputc(c
,f2
);
865 static void parsehtml(FILE *f1
,FILE *f2
,codecs_t
*codec
){
867 while((c
=fgetc(f1
))>=0){
876 return; // end of section
878 wrapline(f2
,codec
->name
); break;
880 wrapline(f2
,codec
->info
); break;
882 wrapline(f2
,codec
->comment
); break;
884 wrapline(f2
,codec
->dll
); break;
886 fprintf(f2
,"%c",!strcmp(codec
->drv
,"dshow")?'+':'-'); break;
888 for(d
=0;d
<CODECS_MAX_FOURCC
;d
++)
889 if(!d
|| codec
->fourcc
[d
]!=0xFFFFFFFF)
890 fprintf(f2
,"%s%.4s",d
?"<br>":"",(codec
->fourcc
[d
]==0xFFFFFFFF || codec
->fourcc
[d
]<0x20202020)?!d
?"-":"":(char*) &codec
->fourcc
[d
]);
893 for(d
=0;d
<CODECS_MAX_FOURCC
;d
++)
894 if(codec
->fourcc
[d
]!=0xFFFFFFFF)
895 fprintf(f2
,"%s0x%X",d
?"<br>":"",codec
->fourcc
[d
]);
898 for(d
=0;d
<CODECS_MAX_OUTFMT
;d
++)
899 if(codec
->outfmt
[d
]!=0xFFFFFFFF){
900 for (c
=0; fmt_table
[c
].name
; c
++)
901 if(fmt_table
[c
].num
==codec
->outfmt
[d
]) break;
902 if(fmt_table
[c
].name
)
903 fprintf(f2
,"%s%s",d
?"<br>":"",fmt_table
[c
].name
);
913 void skiphtml(FILE *f1
){
915 while((c
=fgetc(f1
))>=0){
920 if(d
=='.') return; // end of section
924 static void print_int_array(const unsigned int* a
, int size
)
929 printf("%d%s", *a
++, size
?", ":"");
931 printf("0x%X%s", *a
++, size
?", ":"");
935 static void print_char_array(const unsigned char* a
, int size
)
940 printf("%d%s", *a
++, size
?", ":"");
942 printf("0x%02x%s", *a
++, size
?", ":"");
946 static void print_string(const char* s
)
948 if (!s
) printf("NULL");
949 else printf("\"%s\"", s
);
952 int main(int argc
, char* argv
[])
966 * Take path to codecs.conf from command line, or fall back on
969 if (!(nr_codecs
= parse_codec_cfg((argc
>1)?argv
[1]:"etc/codecs.conf")))
971 if (codecs_conf_release
< CODEC_CFG_MIN
)
980 nm
[0] = "builtin_video_codecs";
981 cod
[0] = video_codecs
;
984 nm
[1] = "builtin_audio_codecs";
985 cod
[1] = audio_codecs
;
988 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv
[1]);
989 printf("#include <stddef.h>\n");
990 printf("#include \"codec-cfg.h\"\n\n");
991 printf("#define CODEC_CFG_MIN %i\n\n", codecs_conf_release
);
993 for (i
=0; i
<2; i
++) {
994 printf("const codecs_t %s[] = {\n", nm
[i
]);
995 for (j
= 0; j
< nr
[i
]; j
++) {
998 print_int_array(cod
[i
][j
].fourcc
, CODECS_MAX_FOURCC
);
999 printf(", /* fourcc */\n");
1001 print_int_array(cod
[i
][j
].fourccmap
, CODECS_MAX_FOURCC
);
1002 printf(", /* fourccmap */\n");
1004 print_int_array(cod
[i
][j
].outfmt
, CODECS_MAX_OUTFMT
);
1005 printf(", /* outfmt */\n");
1007 print_char_array(cod
[i
][j
].outflags
, CODECS_MAX_OUTFMT
);
1008 printf(", /* outflags */\n");
1010 print_int_array(cod
[i
][j
].infmt
, CODECS_MAX_INFMT
);
1011 printf(", /* infmt */\n");
1013 print_char_array(cod
[i
][j
].inflags
, CODECS_MAX_INFMT
);
1014 printf(", /* inflags */\n");
1016 print_string(cod
[i
][j
].name
); printf(", /* name */\n");
1017 print_string(cod
[i
][j
].info
); printf(", /* info */\n");
1018 print_string(cod
[i
][j
].comment
); printf(", /* comment */\n");
1019 print_string(cod
[i
][j
].dll
); printf(", /* dll */\n");
1020 print_string(cod
[i
][j
].drv
); printf(", /* drv */\n");
1022 printf("{ 0x%08lx, %hu, %hu,",
1026 print_char_array(cod
[i
][j
].guid
.f4
, sizeof(cod
[i
][j
].guid
.f4
));
1027 printf(" }, /* GUID */\n");
1028 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1031 cod
[i
][j
].cpuflags
);
1032 if (j
< nr
[i
]) printf(",\n");
1039 f1
=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1
) exit(1);
1040 f2
=fopen("DOCS/codecs-status.html","wb"); if(!f2
) exit(1);
1042 while((c
=fgetc(f1
))>=0){
1048 if(d
>='0' && d
<='9'){
1051 //printf("BEGIN %d\n",section);
1055 nr_codecs
= nr_acodecs
;
1060 nr_codecs
= nr_vcodecs
;
1061 dshow
=4;win32
=2;win32ex
=6;
1064 for(i
=0;i
<nr_codecs
;i
++){
1065 fseek(f1
,pos
,SEEK_SET
);
1069 if(cl
[i
].status
==CODECS_STATUS_WORKING
)
1070 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1071 parsehtml(f1
,f2
,&cl
[i
]);
1076 if(cl
[i
].status
==CODECS_STATUS_WORKING
)
1077 if((!strcmp(cl
[i
].drv
,"vfw") || !strcmp(cl
[i
].drv
,"dshow") || !strcmp(cl
[i
].drv
,"vfwex") || !strcmp(cl
[i
].drv
,"acm")))
1078 parsehtml(f1
,f2
,&cl
[i
]);
1083 if(cl
[i
].status
==CODECS_STATUS_PROBLEMS
)
1084 parsehtml(f1
,f2
,&cl
[i
]);
1088 if(cl
[i
].status
==CODECS_STATUS_NOT_WORKING
)
1089 parsehtml(f1
,f2
,&cl
[i
]);
1093 if(cl
[i
].status
==CODECS_STATUS_UNTESTED
)
1094 parsehtml(f1
,f2
,&cl
[i
]);
1097 printf("Warning! unimplemented section: %d\n",section
);
1100 fseek(f1
,pos
,SEEK_SET
);
1120 int i
,j
, nr_codecs
, state
;
1122 if (!(parse_codec_cfg("etc/codecs.conf")))
1125 printf("no videoconfig.\n");
1127 printf("no audioconfig.\n");
1129 printf("videocodecs:\n");
1131 nr_codecs
= nr_vcodecs
;
1135 printf("number of %scodecs: %d\n", state
==0?"video":"audio",
1137 for(i
=0;i
<nr_codecs
;i
++, c
++){
1138 printf("\n============== %scodec %02d ===============\n",
1139 state
==0?"video":"audio",i
);
1140 printf("name='%s'\n",c
->name
);
1141 printf("info='%s'\n",c
->info
);
1142 printf("comment='%s'\n",c
->comment
);
1143 printf("dll='%s'\n",c
->dll
);
1144 /* printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1145 c->flags, c->driver, c->status, c->cpuflags); */
1146 printf("flags=%X status=%d cpuflags=%d\n",
1147 c
->flags
, c
->status
, c
->cpuflags
);
1149 for(j
=0;j
<CODECS_MAX_FOURCC
;j
++){
1150 if(c
->fourcc
[j
]!=0xFFFFFFFF){
1151 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j
,c
->fourcc
[j
],(char *) &c
->fourcc
[j
],c
->fourccmap
[j
],(char *) &c
->fourccmap
[j
]);
1155 for(j
=0;j
<CODECS_MAX_OUTFMT
;j
++){
1156 if(c
->outfmt
[j
]!=0xFFFFFFFF){
1157 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j
,c
->outfmt
[j
],(char *) &c
->outfmt
[j
],c
->outflags
[j
]);
1161 for(j
=0;j
<CODECS_MAX_INFMT
;j
++){
1162 if(c
->infmt
[j
]!=0xFFFFFFFF){
1163 printf("infmt %02d: %08X (%.4s) flags: %d\n",j
,c
->infmt
[j
],(char *) &c
->infmt
[j
],c
->inflags
[j
]);
1167 printf("GUID: %08lX %04X %04X",c
->guid
.f1
,c
->guid
.f2
,c
->guid
.f3
);
1168 for(j
=0;j
<8;j
++) printf(" %02X",c
->guid
.f4
[j
]);
1175 printf("audiocodecs:\n");
1177 nr_codecs
= nr_acodecs
;