Remove trailing whitespace from most files
[mplayer/glamo.git] / codec-cfg.c
blobdb26866fbe3a051ccbe4b32d3185a2f4e3edd4dd
1 /*
2 * codec.conf parser
3 * by Szabolcs Berecz <szabi@inf.elte.hu>
4 * (C) 2001
6 * to compile test application:
7 * cc -I. -DTESTING -o codec-cfg-test codec-cfg.c mp_msg.o osdep/getch2.o -ltermcap
8 * to compile CODECS2HTML:
9 * gcc -DCODECS2HTML -o codecs2html codec-cfg.c mp_msg.o
11 * TODO: implement informat in CODECS2HTML too
14 #define DEBUG
16 //disable asserts
17 #define NDEBUG
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <ctype.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <stdint.h>
29 #include "config.h"
30 #include "mp_msg.h"
31 #ifdef CODECS2HTML
32 #define mp_tmsg mp_msg
33 #ifdef __GNUC__
34 #define mp_msg(t, l, m, args...) fprintf(stderr, m, ##args)
35 #else
36 #define mp_msg(t, l, ...) fprintf(stderr, __VA_ARGS__)
37 #endif
38 #endif
40 #include "help_mp.h"
42 #include "libmpcodecs/img_format.h"
43 #include "codec-cfg.h"
45 #ifndef CODECS2HTML
46 #include "codecs.conf.h"
47 #endif
49 #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
50 ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
51 ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
53 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
55 #define MAX_NR_TOKEN 16
57 #define MAX_LINE_LEN 1000
59 #define RET_EOF -1
60 #define RET_EOL -2
62 #define TYPE_VIDEO 0
63 #define TYPE_AUDIO 1
65 char * codecs_file = NULL;
67 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
68 unsigned int *map)
70 int i, j, freeslots;
71 unsigned int tmp;
73 /* find first unused slot */
74 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
75 /* NOTHING */;
76 freeslots = CODECS_MAX_FOURCC - i;
77 if (!freeslots)
78 goto err_out_too_many;
80 do {
81 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
82 for (j = 0; j < i; j++)
83 if (tmp == fourcc[j])
84 goto err_out_duplicated;
85 fourcc[i] = tmp;
86 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
87 s += 4;
88 i++;
89 } while ((*(s++) == ',') && --freeslots);
91 if (!freeslots)
92 goto err_out_too_many;
93 if (*(--s) != '\0')
94 goto err_out_parse_error;
95 return 1;
96 err_out_duplicated:
97 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
98 return 0;
99 err_out_too_many:
100 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
101 return 0;
102 err_out_parse_error:
103 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
104 return 0;
107 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
109 int i, j;
110 char *endptr;
112 /* find first unused slot */
113 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
114 /* NOTHING */;
115 if (i == CODECS_MAX_FOURCC) {
116 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
117 return 0;
120 fourcc[i]=strtoul(s,&endptr,0);
121 if (*endptr != '\0') {
122 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
123 return 0;
126 if(alias){
127 fourccmap[i]=strtoul(alias,&endptr,0);
128 if (*endptr != '\0') {
129 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
130 return 0;
132 } else
133 fourccmap[i]=fourcc[i];
135 for (j = 0; j < i; j++)
136 if (fourcc[j] == fourcc[i]) {
137 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
138 return 0;
141 return 1;
144 static struct {
145 const char *name;
146 const unsigned int num;
147 } fmt_table[] = {
148 {"YV12", IMGFMT_YV12},
149 {"I420", IMGFMT_I420},
150 {"IYUV", IMGFMT_IYUV},
151 {"NV12", IMGFMT_NV12},
152 {"NV21", IMGFMT_NV21},
153 {"YVU9", IMGFMT_YVU9},
154 {"IF09", IMGFMT_IF09},
155 {"444P", IMGFMT_444P},
156 {"422P", IMGFMT_422P},
157 {"411P", IMGFMT_411P},
158 {"Y800", IMGFMT_Y800},
159 {"Y8", IMGFMT_Y8},
161 {"YUY2", IMGFMT_YUY2},
162 {"UYVY", IMGFMT_UYVY},
163 {"YVYU", IMGFMT_YVYU},
165 {"RGB4", IMGFMT_RGB|4},
166 {"RGB8", IMGFMT_RGB|8},
167 {"RGB15", IMGFMT_RGB|15},
168 {"RGB16", IMGFMT_RGB|16},
169 {"RGB24", IMGFMT_RGB|24},
170 {"RGB32", IMGFMT_RGB|32},
171 {"BGR4", IMGFMT_BGR|4},
172 {"BGR8", IMGFMT_BGR|8},
173 {"BGR15", IMGFMT_BGR|15},
174 {"BGR16", IMGFMT_BGR|16},
175 {"BGR24", IMGFMT_BGR|24},
176 {"BGR32", IMGFMT_BGR|32},
177 {"RGB1", IMGFMT_RGB|1},
178 {"BGR1", IMGFMT_BGR|1},
180 {"MPES", IMGFMT_MPEGPES},
181 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
182 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
183 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
185 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
186 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
188 {"VDPAU_MPEG1",IMGFMT_VDPAU_MPEG1},
189 {"VDPAU_MPEG2",IMGFMT_VDPAU_MPEG2},
190 {"VDPAU_H264",IMGFMT_VDPAU_H264},
191 {"VDPAU_WMV3",IMGFMT_VDPAU_WMV3},
192 {"VDPAU_VC1",IMGFMT_VDPAU_VC1},
194 {NULL, 0}
198 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
199 unsigned char *outflags)
202 static char *flagstr[] = {
203 "flip",
204 "noflip",
205 "yuvhack",
206 "query",
207 "static",
208 NULL
211 int i, j, freeslots;
212 unsigned char flags;
214 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
215 /* NOTHING */;
216 freeslots = CODECS_MAX_OUTFMT - i;
217 if (!freeslots)
218 goto err_out_too_many;
220 flags = 0;
221 if(sflags) {
222 do {
223 for (j = 0; flagstr[j] != NULL; j++)
224 if (!strncmp(sflags, flagstr[j],
225 strlen(flagstr[j])))
226 break;
227 if (flagstr[j] == NULL)
228 goto err_out_parse_error;
229 flags|=(1<<j);
230 sflags+=strlen(flagstr[j]);
231 } while (*(sflags++) == ',');
233 if (*(--sflags) != '\0')
234 goto err_out_parse_error;
237 do {
238 for (j = 0; fmt_table[j].name != NULL; j++)
239 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
240 break;
241 if (fmt_table[j].name == NULL)
242 goto err_out_parse_error;
243 outfmt[i] = fmt_table[j].num;
244 outflags[i] = flags;
245 ++i;
246 sfmt+=strlen(fmt_table[j].name);
247 } while ((*(sfmt++) == ',') && --freeslots);
249 if (!freeslots)
250 goto err_out_too_many;
252 if (*(--sfmt) != '\0')
253 goto err_out_parse_error;
255 return 1;
256 err_out_too_many:
257 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many out...");
258 return 0;
259 err_out_parse_error:
260 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
261 return 0;
264 #if 0
265 static short get_driver(char *s,int audioflag)
267 static char *audiodrv[] = {
268 "null",
269 "mp3lib",
270 "pcm",
271 "libac3",
272 "acm",
273 "alaw",
274 "msgsm",
275 "dshow",
276 "dvdpcm",
277 "hwac3",
278 "libvorbis",
279 "ffmpeg",
280 "libmad",
281 "msadpcm",
282 "liba52",
283 "g72x",
284 "imaadpcm",
285 "dk4adpcm",
286 "dk3adpcm",
287 "roqaudio",
288 "faad",
289 "realaud",
290 "libdv",
291 NULL
293 static char *videodrv[] = {
294 "null",
295 "libmpeg2",
296 "vfw",
297 "dshow",
298 "ffmpeg",
299 "vfwex",
300 "raw",
301 "msrle",
302 "xanim",
303 "msvidc",
304 "fli",
305 "cinepak",
306 "qtrle",
307 "nuv",
308 "cyuv",
309 "qtsmc",
310 "ducktm1",
311 "roqvideo",
312 "qtrpza",
313 "mpng",
314 "ijpg",
315 "zlib",
316 "mpegpes",
317 "zrmjpeg",
318 "realvid",
319 "xvid",
320 "libdv",
321 NULL
323 char **drv=audioflag?audiodrv:videodrv;
324 int i;
326 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
328 return -1;
330 #endif
332 static int validate_codec(codecs_t *c, int type)
334 unsigned int i;
335 char *tmp_name = c->name;
337 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
338 /* NOTHING */;
340 if (i < strlen(tmp_name)) {
341 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
342 return 0;
345 if (!c->info)
346 c->info = strdup(c->name);
348 #if 0
349 if (c->fourcc[0] == 0xffffffff) {
350 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have FourCC/format!\n", c->name);
351 return 0;
353 #endif
355 if (!c->drv) {
356 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
357 return 0;
360 #if 0
361 #warning codec->driver == 4;... <- this should not be put in here...
362 #warning Where are they defined ????????????
363 if (!c->dll && (c->driver == 4 ||
364 (c->driver == 2 && type == TYPE_VIDEO))) {
365 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs a 'dll'!\n", c->name);
366 return 0;
368 #warning Can guid.f1 be 0? How does one know that it was not given?
369 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
371 if (type == TYPE_VIDEO)
372 if (c->outfmt[0] == 0xffffffff) {
373 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs an 'outfmt'!\n", c->name);
374 return 0;
376 #endif
377 return 1;
380 static int add_comment(char *s, char **d)
382 int pos;
384 if (!*d)
385 pos = 0;
386 else {
387 pos = strlen(*d);
388 (*d)[pos++] = '\n';
390 if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
391 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
392 return 0;
394 strcpy(*d + pos, s);
395 return 1;
398 static short get_cpuflags(char *s)
400 static char *flagstr[] = {
401 "mmx",
402 "sse",
403 "3dnow",
404 NULL
406 int i;
407 short flags = 0;
409 do {
410 for (i = 0; flagstr[i]; i++)
411 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
412 break;
413 if (!flagstr[i])
414 goto err_out_parse_error;
415 flags |= 1<<i;
416 s += strlen(flagstr[i]);
417 } while (*(s++) == ',');
419 if (*(--s) != '\0')
420 goto err_out_parse_error;
422 return flags;
423 err_out_parse_error:
424 return 0;
427 static FILE *fp;
428 static int line_num = 0;
429 static char *line;
430 static char *token[MAX_NR_TOKEN];
431 static int read_nextline = 1;
433 static int get_token(int min, int max)
435 static int line_pos;
436 int i;
437 char c;
439 if (max >= MAX_NR_TOKEN) {
440 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_MR_TOKEN!");
441 goto out_eof;
444 memset(token, 0x00, sizeof(*token) * max);
446 if (read_nextline) {
447 if (!fgets(line, MAX_LINE_LEN, fp))
448 goto out_eof;
449 line_pos = 0;
450 ++line_num;
451 read_nextline = 0;
453 for (i = 0; i < max; i++) {
454 while (isspace(line[line_pos]))
455 ++line_pos;
456 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
457 line[line_pos] == ';') {
458 read_nextline = 1;
459 if (i >= min)
460 goto out_ok;
461 goto out_eol;
463 token[i] = line + line_pos;
464 c = line[line_pos];
465 if (c == '"' || c == '\'') {
466 token[i]++;
467 while (line[++line_pos] != c && line[line_pos])
468 /* NOTHING */;
469 } else {
470 for (/* NOTHING */; !isspace(line[line_pos]) &&
471 line[line_pos]; line_pos++)
472 /* NOTHING */;
474 if (!line[line_pos]) {
475 read_nextline = 1;
476 if (i >= min - 1)
477 goto out_ok;
478 goto out_eol;
480 line[line_pos] = '\0';
481 line_pos++;
483 out_ok:
484 return i;
485 out_eof:
486 read_nextline = 1;
487 return RET_EOF;
488 out_eol:
489 return RET_EOL;
492 static codecs_t *video_codecs=NULL;
493 static codecs_t *audio_codecs=NULL;
494 static int nr_vcodecs = 0;
495 static int nr_acodecs = 0;
497 int parse_codec_cfg(const char *cfgfile)
499 codecs_t *codec = NULL; // current codec
500 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
501 char *endptr; // strtoul()...
502 int *nr_codecsp;
503 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
504 int tmp, i;
506 // in case we call it a second time
507 codecs_uninit_free();
509 nr_vcodecs = 0;
510 nr_acodecs = 0;
512 if(cfgfile==NULL) {
513 #ifdef CODECS2HTML
514 return 0;
515 #else
516 video_codecs = builtin_video_codecs;
517 audio_codecs = builtin_audio_codecs;
518 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
519 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
520 return 1;
521 #endif
524 mp_tmsg(MSGT_CODECCFG,MSGL_V,"Reading %s: ", cfgfile);
526 if ((fp = fopen(cfgfile, "r")) == NULL) {
527 mp_tmsg(MSGT_CODECCFG,MSGL_V,"Can't open '%s': %s\n", cfgfile, strerror(errno));
528 return 0;
531 if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) {
532 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't get memory for 'line': %s\n", strerror(errno));
533 return 0;
535 read_nextline = 1;
538 * this only catches release lines at the start of
539 * codecs.conf, before audiocodecs and videocodecs.
541 while ((tmp = get_token(1, 1)) == RET_EOL)
542 /* NOTHING */;
543 if (tmp == RET_EOF)
544 goto out;
545 if (!strcmp(token[0], "release")) {
546 if (get_token(1, 2) < 0)
547 goto err_out_parse_error;
548 tmp = atoi(token[0]);
549 if (tmp < CODEC_CFG_MIN)
550 goto err_out_release_num;
551 while ((tmp = get_token(1, 1)) == RET_EOL)
552 /* NOTHING */;
553 if (tmp == RET_EOF)
554 goto out;
555 } else
556 goto err_out_release_num;
559 * check if the next block starts with 'audiocodec' or
560 * with 'videocodec'
562 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
563 goto loop_enter;
564 goto err_out_parse_error;
566 while ((tmp = get_token(1, 1)) != RET_EOF) {
567 if (tmp == RET_EOL)
568 continue;
569 if (!strcmp(token[0], "audiocodec") ||
570 !strcmp(token[0], "videocodec")) {
571 if (!validate_codec(codec, codec_type))
572 goto err_out_not_valid;
573 loop_enter:
574 if (*token[0] == 'v') {
575 codec_type = TYPE_VIDEO;
576 nr_codecsp = &nr_vcodecs;
577 codecsp = &video_codecs;
578 } else if (*token[0] == 'a') {
579 codec_type = TYPE_AUDIO;
580 nr_codecsp = &nr_acodecs;
581 codecsp = &audio_codecs;
582 #ifdef DEBUG
583 } else {
584 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
585 goto err_out;
586 #endif
588 if (!(*codecsp = realloc(*codecsp,
589 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
590 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
591 goto err_out;
593 codec=*codecsp + *nr_codecsp;
594 ++*nr_codecsp;
595 memset(codec,0,sizeof(codecs_t));
596 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
597 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
598 memset(codec->infmt, 0xff, sizeof(codec->infmt));
600 if (get_token(1, 1) < 0)
601 goto err_out_parse_error;
602 for (i = 0; i < *nr_codecsp - 1; i++) {
603 if(( (*codecsp)[i].name!=NULL) &&
604 (!strcmp(token[0], (*codecsp)[i].name)) ) {
605 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
606 goto err_out_print_linenum;
609 if (!(codec->name = strdup(token[0]))) {
610 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
611 goto err_out;
613 } else if (!strcmp(token[0], "info")) {
614 if (codec->info || get_token(1, 1) < 0)
615 goto err_out_parse_error;
616 if (!(codec->info = strdup(token[0]))) {
617 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
618 goto err_out;
620 } else if (!strcmp(token[0], "comment")) {
621 if (get_token(1, 1) < 0)
622 goto err_out_parse_error;
623 add_comment(token[0], &codec->comment);
624 } else if (!strcmp(token[0], "fourcc")) {
625 if (get_token(1, 2) < 0)
626 goto err_out_parse_error;
627 if (!add_to_fourcc(token[0], token[1],
628 codec->fourcc,
629 codec->fourccmap))
630 goto err_out_print_linenum;
631 } else if (!strcmp(token[0], "format")) {
632 if (get_token(1, 2) < 0)
633 goto err_out_parse_error;
634 if (!add_to_format(token[0], token[1],
635 codec->fourcc,codec->fourccmap))
636 goto err_out_print_linenum;
637 } else if (!strcmp(token[0], "driver")) {
638 if (get_token(1, 1) < 0)
639 goto err_out_parse_error;
640 if (!(codec->drv = strdup(token[0]))) {
641 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
642 goto err_out;
644 } else if (!strcmp(token[0], "dll")) {
645 if (get_token(1, 1) < 0)
646 goto err_out_parse_error;
647 if (!(codec->dll = strdup(token[0]))) {
648 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s", strerror(errno));
649 goto err_out;
651 } else if (!strcmp(token[0], "guid")) {
652 if (get_token(11, 11) < 0)
653 goto err_out_parse_error;
654 codec->guid.f1=strtoul(token[0],&endptr,0);
655 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
656 *endptr != '\0')
657 goto err_out_parse_error;
658 codec->guid.f2=strtoul(token[1],&endptr,0);
659 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
660 *endptr != '\0')
661 goto err_out_parse_error;
662 codec->guid.f3=strtoul(token[2],&endptr,0);
663 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
664 *endptr != '\0')
665 goto err_out_parse_error;
666 for (i = 0; i < 8; i++) {
667 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
668 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
669 *endptr != '\0')
670 goto err_out_parse_error;
672 } else if (!strcmp(token[0], "out")) {
673 if (get_token(1, 2) < 0)
674 goto err_out_parse_error;
675 if (!add_to_inout(token[0], token[1], codec->outfmt,
676 codec->outflags))
677 goto err_out_print_linenum;
678 } else if (!strcmp(token[0], "in")) {
679 if (get_token(1, 2) < 0)
680 goto err_out_parse_error;
681 if (!add_to_inout(token[0], token[1], codec->infmt,
682 codec->inflags))
683 goto err_out_print_linenum;
684 } else if (!strcmp(token[0], "flags")) {
685 if (get_token(1, 1) < 0)
686 goto err_out_parse_error;
687 if (!strcmp(token[0], "seekable"))
688 codec->flags |= CODECS_FLAG_SEEKABLE;
689 else
690 if (!strcmp(token[0], "align16"))
691 codec->flags |= CODECS_FLAG_ALIGN16;
692 else
693 goto err_out_parse_error;
694 } else if (!strcmp(token[0], "status")) {
695 if (get_token(1, 1) < 0)
696 goto err_out_parse_error;
697 if (!strcasecmp(token[0], "working"))
698 codec->status = CODECS_STATUS_WORKING;
699 else if (!strcasecmp(token[0], "crashing"))
700 codec->status = CODECS_STATUS_NOT_WORKING;
701 else if (!strcasecmp(token[0], "untested"))
702 codec->status = CODECS_STATUS_UNTESTED;
703 else if (!strcasecmp(token[0], "buggy"))
704 codec->status = CODECS_STATUS_PROBLEMS;
705 else
706 goto err_out_parse_error;
707 } else if (!strcmp(token[0], "cpuflags")) {
708 if (get_token(1, 1) < 0)
709 goto err_out_parse_error;
710 if (!(codec->cpuflags = get_cpuflags(token[0])))
711 goto err_out_parse_error;
712 } else
713 goto err_out_parse_error;
715 if (!validate_codec(codec, codec_type))
716 goto err_out_not_valid;
717 mp_tmsg(MSGT_CODECCFG,MSGL_INFO,"%d audio & %d video codecs\n", nr_acodecs, nr_vcodecs);
718 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
719 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
720 out:
721 free(line);
722 line=NULL;
723 fclose(fp);
724 return 1;
726 err_out_parse_error:
727 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
728 err_out_print_linenum:
729 PRINT_LINENUM;
730 err_out:
731 codecs_uninit_free();
733 free(line);
734 line=NULL;
735 line_num = 0;
736 fclose(fp);
737 return 0;
738 err_out_not_valid:
739 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
740 goto err_out_print_linenum;
741 err_out_release_num:
742 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
743 goto err_out_print_linenum;
746 static void codecs_free(codecs_t* codecs,int count) {
747 int i;
748 for ( i = 0; i < count; i++)
749 if ( codecs[i].name ) {
750 if( codecs[i].name )
751 free(codecs[i].name);
752 if( codecs[i].info )
753 free(codecs[i].info);
754 if( codecs[i].comment )
755 free(codecs[i].comment);
756 if( codecs[i].dll )
757 free(codecs[i].dll);
758 if( codecs[i].drv )
759 free(codecs[i].drv);
761 if (codecs)
762 free(codecs);
765 void codecs_uninit_free(void) {
766 if (video_codecs)
767 codecs_free(video_codecs,nr_vcodecs);
768 video_codecs=NULL;
769 if (audio_codecs)
770 codecs_free(audio_codecs,nr_acodecs);
771 audio_codecs=NULL;
774 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
775 codecs_t *start, int force)
777 return find_codec(fourcc, fourccmap, start, 1, force);
780 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
781 codecs_t *start, int force)
783 return find_codec(fourcc, fourccmap, start, 0, force);
786 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
787 codecs_t *start, int audioflag, int force)
789 int i, j;
790 codecs_t *c;
792 #if 0
793 if (start) {
794 for (/* NOTHING */; start->name; start++) {
795 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
796 if (start->fourcc[j] == fourcc) {
797 if (fourccmap)
798 *fourccmap = start->fourccmap[j];
799 return start;
803 } else
804 #endif
806 if (audioflag) {
807 i = nr_acodecs;
808 c = audio_codecs;
809 } else {
810 i = nr_vcodecs;
811 c = video_codecs;
813 if(!i) return NULL;
814 for (/* NOTHING */; i--; c++) {
815 if(start && c<=start) continue;
816 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
817 // FIXME: do NOT hardwire 'null' name here:
818 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
819 if (fourccmap)
820 *fourccmap = c->fourccmap[j];
821 return c;
824 if (force) return c;
827 return NULL;
830 void stringset_init(stringset_t *set) {
831 *set = calloc(1, sizeof(char *));
834 void stringset_free(stringset_t *set) {
835 int count = 0;
836 while ((*set)[count]) free((*set)[count++]);
837 free(*set);
838 *set = NULL;
841 void stringset_add(stringset_t *set, const char *str) {
842 int count = 0;
843 while ((*set)[count]) count++;
844 count++;
845 *set = realloc(*set, sizeof(char *) * (count + 1));
846 (*set)[count - 1] = strdup(str);
847 (*set)[count] = NULL;
850 int stringset_test(stringset_t *set, const char *str) {
851 stringset_t s;
852 for (s = *set; *s; s++)
853 if (strcmp(*s, str) == 0)
854 return 1;
855 return 0;
858 void list_codecs(int audioflag){
859 int i;
860 codecs_t *c;
862 if (audioflag) {
863 i = nr_acodecs;
864 c = audio_codecs;
865 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
866 } else {
867 i = nr_vcodecs;
868 c = video_codecs;
869 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
871 if(!i) return;
872 for (/* NOTHING */; i--; c++) {
873 char* s="unknown ";
874 switch(c->status){
875 case CODECS_STATUS_WORKING: s="working ";break;
876 case CODECS_STATUS_PROBLEMS: s="problems";break;
877 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
878 case CODECS_STATUS_UNTESTED: s="untested";break;
880 if(c->dll)
881 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
882 else
883 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
891 #ifdef CODECS2HTML
892 void wrapline(FILE *f2,char *s){
893 int c;
894 if(!s){
895 fprintf(f2,"-");
896 return;
898 while((c=*s++)){
899 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
903 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
904 int c,d;
905 while((c=fgetc(f1))>=0){
906 if(c!='%'){
907 fputc(c,f2);
908 continue;
910 d=fgetc(f1);
912 switch(d){
913 case '.':
914 return; // end of section
915 case 'n':
916 wrapline(f2,codec->name); break;
917 case 'i':
918 wrapline(f2,codec->info); break;
919 case 'c':
920 wrapline(f2,codec->comment); break;
921 case 'd':
922 wrapline(f2,codec->dll); break;
923 case 'D':
924 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
925 case 'F':
926 for(d=0;d<CODECS_MAX_FOURCC;d++)
927 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
928 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
929 break;
930 case 'f':
931 for(d=0;d<CODECS_MAX_FOURCC;d++)
932 if(codec->fourcc[d]!=0xFFFFFFFF)
933 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
934 break;
935 case 'Y':
936 for(d=0;d<CODECS_MAX_OUTFMT;d++)
937 if(codec->outfmt[d]!=0xFFFFFFFF){
938 for (c=0; fmt_table[c].name; c++)
939 if(fmt_table[c].num==codec->outfmt[d]) break;
940 if(fmt_table[c].name)
941 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
943 break;
944 default:
945 fputc(c,f2);
946 fputc(d,f2);
952 void skiphtml(FILE *f1){
953 int c,d;
954 while((c=fgetc(f1))>=0){
955 if(c!='%'){
956 continue;
958 d=fgetc(f1);
959 if(d=='.') return; // end of section
963 static void print_int_array(const unsigned int* a, int size)
965 printf("{ ");
966 while (size--)
967 if(abs(*a)<256)
968 printf("%d%s", *a++, size?", ":"");
969 else
970 printf("0x%X%s", *a++, size?", ":"");
971 printf(" }");
974 static void print_char_array(const unsigned char* a, int size)
976 printf("{ ");
977 while (size--)
978 if((*a)<10)
979 printf("%d%s", *a++, size?", ":"");
980 else
981 printf("0x%02x%s", *a++, size?", ":"");
982 printf(" }");
985 static void print_string(const char* s)
987 if (!s) printf("NULL");
988 else printf("\"%s\"", s);
991 int main(int argc, char* argv[])
993 codecs_t *cl;
994 FILE *f1;
995 FILE *f2;
996 int c,d,i;
997 int pos;
998 int section=-1;
999 int nr_codecs;
1000 int win32=-1;
1001 int dshow=-1;
1002 int win32ex=-1;
1005 * Take path to codecs.conf from command line, or fall back on
1006 * etc/codecs.conf
1008 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1009 exit(1);
1011 if (argc > 1) {
1012 int i, j;
1013 const char* nm[2];
1014 codecs_t* cod[2];
1015 int nr[2];
1017 nm[0] = "builtin_video_codecs";
1018 cod[0] = video_codecs;
1019 nr[0] = nr_vcodecs;
1021 nm[1] = "builtin_audio_codecs";
1022 cod[1] = audio_codecs;
1023 nr[1] = nr_acodecs;
1025 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1026 printf("#include <stddef.h>\n");
1027 printf("#include \"codec-cfg.h\"\n\n");
1029 for (i=0; i<2; i++) {
1030 printf("const codecs_t %s[] = {\n", nm[i]);
1031 for (j = 0; j < nr[i]; j++) {
1032 printf("{");
1034 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1035 printf(", /* fourcc */\n");
1037 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1038 printf(", /* fourccmap */\n");
1040 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1041 printf(", /* outfmt */\n");
1043 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1044 printf(", /* outflags */\n");
1046 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1047 printf(", /* infmt */\n");
1049 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1050 printf(", /* inflags */\n");
1052 print_string(cod[i][j].name); printf(", /* name */\n");
1053 print_string(cod[i][j].info); printf(", /* info */\n");
1054 print_string(cod[i][j].comment); printf(", /* comment */\n");
1055 print_string(cod[i][j].dll); printf(", /* dll */\n");
1056 print_string(cod[i][j].drv); printf(", /* drv */\n");
1058 printf("{ 0x%08lx, %hu, %hu,",
1059 cod[i][j].guid.f1,
1060 cod[i][j].guid.f2,
1061 cod[i][j].guid.f3);
1062 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1063 printf(" }, /* GUID */\n");
1064 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1065 cod[i][j].flags,
1066 cod[i][j].status,
1067 cod[i][j].cpuflags);
1068 if (j < nr[i]) printf(",\n");
1070 printf("};\n\n");
1072 exit(0);
1075 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1076 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1078 while((c=fgetc(f1))>=0){
1079 if(c!='%'){
1080 fputc(c,f2);
1081 continue;
1083 d=fgetc(f1);
1084 if(d>='0' && d<='9'){
1085 // begin section
1086 section=d-'0';
1087 //printf("BEGIN %d\n",section);
1088 if(section>=5){
1089 // audio
1090 cl = audio_codecs;
1091 nr_codecs = nr_acodecs;
1092 dshow=7;win32=4;
1093 } else {
1094 // video
1095 cl = video_codecs;
1096 nr_codecs = nr_vcodecs;
1097 dshow=4;win32=2;win32ex=6;
1099 pos=ftell(f1);
1100 for(i=0;i<nr_codecs;i++){
1101 fseek(f1,pos,SEEK_SET);
1102 switch(section){
1103 case 0:
1104 case 5:
1105 if(cl[i].status==CODECS_STATUS_WORKING)
1106 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1107 parsehtml(f1,f2,&cl[i],section,dshow);
1108 break;
1109 #if 0
1110 case 1:
1111 case 6:
1112 if(cl[i].status==CODECS_STATUS_WORKING)
1113 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1114 parsehtml(f1,f2,&cl[i],section,dshow);
1115 break;
1116 #endif
1117 case 2:
1118 case 7:
1119 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1120 parsehtml(f1,f2,&cl[i],section,dshow);
1121 break;
1122 case 3:
1123 case 8:
1124 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1125 parsehtml(f1,f2,&cl[i],section,dshow);
1126 break;
1127 case 4:
1128 case 9:
1129 if(cl[i].status==CODECS_STATUS_UNTESTED)
1130 parsehtml(f1,f2,&cl[i],section,dshow);
1131 break;
1132 default:
1133 printf("Warning! unimplemented section: %d\n",section);
1136 fseek(f1,pos,SEEK_SET);
1137 skiphtml(f1);
1138 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1140 continue;
1142 fputc(c,f2);
1143 fputc(d,f2);
1146 fclose(f2);
1147 fclose(f1);
1148 return 0;
1151 #endif
1153 #ifdef TESTING
1154 int main(void)
1156 codecs_t *c;
1157 int i,j, nr_codecs, state;
1159 if (!(parse_codec_cfg("etc/codecs.conf")))
1160 return 0;
1161 if (!video_codecs)
1162 printf("no videoconfig.\n");
1163 if (!audio_codecs)
1164 printf("no audioconfig.\n");
1166 printf("videocodecs:\n");
1167 c = video_codecs;
1168 nr_codecs = nr_vcodecs;
1169 state = 0;
1170 next:
1171 if (c) {
1172 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1173 nr_codecs);
1174 for(i=0;i<nr_codecs;i++, c++){
1175 printf("\n============== %scodec %02d ===============\n",
1176 state==0?"video":"audio",i);
1177 printf("name='%s'\n",c->name);
1178 printf("info='%s'\n",c->info);
1179 printf("comment='%s'\n",c->comment);
1180 printf("dll='%s'\n",c->dll);
1181 /* printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1182 c->flags, c->driver, c->status, c->cpuflags); */
1183 printf("flags=%X status=%d cpuflags=%d\n",
1184 c->flags, c->status, c->cpuflags);
1186 for(j=0;j<CODECS_MAX_FOURCC;j++){
1187 if(c->fourcc[j]!=0xFFFFFFFF){
1188 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1192 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1193 if(c->outfmt[j]!=0xFFFFFFFF){
1194 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1198 for(j=0;j<CODECS_MAX_INFMT;j++){
1199 if(c->infmt[j]!=0xFFFFFFFF){
1200 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1204 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1205 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1206 printf("\n");
1211 if (!state) {
1212 printf("audiocodecs:\n");
1213 c = audio_codecs;
1214 nr_codecs = nr_acodecs;
1215 state = 1;
1216 goto next;
1218 return 0;
1221 #endif