get some new maintainers
[mplayer/glamo.git] / codec-cfg.c
blob52b7b7c7b48849e744a06f703ba6e93ae7bd73a7
1 /*
2 * codec.conf parser
3 * by Szabolcs Berecz <szabi@inf.elte.hu>
4 * (C) 2001
6 * to compile tester app: gcc -Iloader/ -DTESTING -o codec-cfg codec-cfg.c
7 * to compile CODECS2HTML: gcc -Iloader/ -DCODECS2HTML -o codecs2html codecs-cfg.c
9 * TODO: implement informat in CODECS2HTML too
12 #define DEBUG
14 //disable asserts
15 #define NDEBUG
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <ctype.h>
23 #include <assert.h>
24 #include <string.h>
26 #include "config.h"
27 #include "mp_msg.h"
29 // for mmioFOURCC:
30 #include "wine/avifmt.h"
32 #include "libvo/img_format.h"
33 #include "codec-cfg.h"
35 #ifndef CODECS2HTML
36 #include "codecs.conf.h"
37 #endif
39 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
41 #define MAX_NR_TOKEN 16
43 #define MAX_LINE_LEN 1000
45 #define RET_EOF -1
46 #define RET_EOL -2
48 #define TYPE_VIDEO 0
49 #define TYPE_AUDIO 1
51 char * codecs_file = NULL;
53 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
54 unsigned int *map)
56 int i, j, freeslots;
57 unsigned int tmp;
59 /* find first unused slot */
60 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
61 /* NOTHING */;
62 freeslots = CODECS_MAX_FOURCC - i;
63 if (!freeslots)
64 goto err_out_too_many;
66 do {
67 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
68 for (j = 0; j < i; j++)
69 if (tmp == fourcc[j])
70 goto err_out_duplicated;
71 fourcc[i] = tmp;
72 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
73 s += 4;
74 i++;
75 } while ((*(s++) == ',') && --freeslots);
77 if (!freeslots)
78 goto err_out_too_many;
79 if (*(--s) != '\0')
80 goto err_out_parse_error;
81 return 1;
82 err_out_duplicated:
83 mp_msg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
84 return 0;
85 err_out_too_many:
86 mp_msg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
87 return 0;
88 err_out_parse_error:
89 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error");
90 return 0;
93 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
95 int i, j;
96 char *endptr;
98 /* find first unused slot */
99 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
100 /* NOTHING */;
101 if (i == CODECS_MAX_FOURCC) {
102 mp_msg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
103 return 0;
106 fourcc[i]=strtoul(s,&endptr,0);
107 if (*endptr != '\0') {
108 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
109 return 0;
112 if(alias){
113 fourccmap[i]=strtoul(alias,&endptr,0);
114 if (*endptr != '\0') {
115 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
116 return 0;
118 } else
119 fourccmap[i]=fourcc[i];
121 for (j = 0; j < i; j++)
122 if (fourcc[j] == fourcc[i]) {
123 mp_msg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
124 return 0;
127 return 1;
130 static struct {
131 const char *name;
132 const unsigned int num;
133 } fmt_table[] = {
134 {"YV12", IMGFMT_YV12},
135 {"I420", IMGFMT_I420},
136 {"IYUV", IMGFMT_IYUV},
137 {"NV12", IMGFMT_NV12},
138 {"NV21", IMGFMT_NV21},
139 {"YVU9", IMGFMT_YVU9},
140 {"IF09", IMGFMT_IF09},
141 {"444P", IMGFMT_444P},
142 {"422P", IMGFMT_422P},
143 {"411P", IMGFMT_411P},
145 {"YUY2", IMGFMT_YUY2},
146 {"UYVY", IMGFMT_UYVY},
147 {"YVYU", IMGFMT_YVYU},
149 {"RGB4", IMGFMT_RGB|4},
150 {"RGB8", IMGFMT_RGB|8},
151 {"RGB15", IMGFMT_RGB|15},
152 {"RGB16", IMGFMT_RGB|16},
153 {"RGB24", IMGFMT_RGB|24},
154 {"RGB32", IMGFMT_RGB|32},
155 {"BGR4", IMGFMT_BGR|4},
156 {"BGR8", IMGFMT_BGR|8},
157 {"BGR15", IMGFMT_BGR|15},
158 {"BGR16", IMGFMT_BGR|16},
159 {"BGR24", IMGFMT_BGR|24},
160 {"BGR32", IMGFMT_BGR|32},
161 {"RGB1", IMGFMT_RGB|1},
162 {"BGR1", IMGFMT_BGR|1},
164 {"MPES", IMGFMT_MPEGPES},
165 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
166 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
167 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
169 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
170 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
172 {NULL, 0}
176 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
177 unsigned char *outflags)
180 static char *flagstr[] = {
181 "flip",
182 "noflip",
183 "yuvhack",
184 "query",
185 "static",
186 NULL
189 int i, j, freeslots;
190 unsigned char flags;
192 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
193 /* NOTHING */;
194 freeslots = CODECS_MAX_OUTFMT - i;
195 if (!freeslots)
196 goto err_out_too_many;
198 flags = 0;
199 if(sflags) {
200 do {
201 for (j = 0; flagstr[j] != NULL; j++)
202 if (!strncmp(sflags, flagstr[j],
203 strlen(flagstr[j])))
204 break;
205 if (flagstr[j] == NULL)
206 goto err_out_parse_error;
207 flags|=(1<<j);
208 sflags+=strlen(flagstr[j]);
209 } while (*(sflags++) == ',');
211 if (*(--sflags) != '\0')
212 goto err_out_parse_error;
215 do {
216 for (j = 0; fmt_table[j].name != NULL; j++)
217 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
218 break;
219 if (fmt_table[j].name == NULL)
220 goto err_out_parse_error;
221 outfmt[i] = fmt_table[j].num;
222 outflags[i] = flags;
223 ++i;
224 sfmt+=strlen(fmt_table[j].name);
225 } while ((*(sfmt++) == ',') && --freeslots);
227 if (!freeslots)
228 goto err_out_too_many;
230 if (*(--sfmt) != '\0')
231 goto err_out_parse_error;
233 return 1;
234 err_out_too_many:
235 mp_msg(MSGT_CODECCFG,MSGL_ERR,"too many out...");
236 return 0;
237 err_out_parse_error:
238 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error");
239 return 0;
242 #if 0
243 static short get_driver(char *s,int audioflag)
245 static char *audiodrv[] = {
246 "null",
247 "mp3lib",
248 "pcm",
249 "libac3",
250 "acm",
251 "alaw",
252 "msgsm",
253 "dshow",
254 "dvdpcm",
255 "hwac3",
256 "libvorbis",
257 "ffmpeg",
258 "libmad",
259 "msadpcm",
260 "liba52",
261 "g72x",
262 "imaadpcm",
263 "dk4adpcm",
264 "dk3adpcm",
265 "roqaudio",
266 "faad",
267 "realaud",
268 "libdv",
269 NULL
271 static char *videodrv[] = {
272 "null",
273 "libmpeg2",
274 "vfw",
275 "odivx",
276 "dshow",
277 "ffmpeg",
278 "vfwex",
279 "divx4",
280 "raw",
281 "msrle",
282 "xanim",
283 "msvidc",
284 "fli",
285 "cinepak",
286 "qtrle",
287 "nuv",
288 "cyuv",
289 "qtsmc",
290 "ducktm1",
291 "roqvideo",
292 "qtrpza",
293 "mpng",
294 "ijpg",
295 "zlib",
296 "mpegpes",
297 "zrmjpeg",
298 "realvid",
299 "xvid",
300 "libdv",
301 NULL
303 char **drv=audioflag?audiodrv:videodrv;
304 int i;
306 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
308 return -1;
310 #endif
312 static int validate_codec(codecs_t *c, int type)
314 unsigned int i;
315 char *tmp_name = c->name;
317 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
318 /* NOTHING */;
320 if (i < strlen(tmp_name)) {
321 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
322 return 0;
325 if (!c->info)
326 c->info = strdup(c->name);
328 #if 0
329 if (c->fourcc[0] == 0xffffffff) {
330 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have FourCC/format!\n", c->name);
331 return 0;
334 /* XXX fix this: shitty with 'null' codec */
335 if (!c->driver) {
336 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
337 return 0;
339 #endif
341 #if 0
342 #warning codec->driver == 4;... <- ezt nem kellene belehegeszteni...
343 #warning HOL VANNAK DEFINIALVA????????????
344 if (!c->dll && (c->driver == 4 ||
345 (c->driver == 2 && type == TYPE_VIDEO))) {
346 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs a 'dll'!\n", c->name);
347 return 0;
349 #warning guid.f1 lehet 0? honnan lehet tudni, hogy nem adtak meg?
350 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
352 if (type == TYPE_VIDEO)
353 if (c->outfmt[0] == 0xffffffff) {
354 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs an 'outfmt'!\n", c->name);
355 return 0;
357 #endif
358 return 1;
361 static int add_comment(char *s, char **d)
363 int pos;
365 if (!*d)
366 pos = 0;
367 else {
368 pos = strlen(*d);
369 (*d)[pos++] = '\n';
371 if (!(*d = (char *) realloc(*d, pos + strlen(s) + 1))) {
372 mp_msg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
373 return 0;
375 strcpy(*d + pos, s);
376 return 1;
379 static short get_cpuflags(char *s)
381 static char *flagstr[] = {
382 "mmx",
383 "sse",
384 "3dnow",
385 NULL
387 int i;
388 short flags = 0;
390 do {
391 for (i = 0; flagstr[i]; i++)
392 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
393 break;
394 if (!flagstr[i])
395 goto err_out_parse_error;
396 flags |= 1<<i;
397 s += strlen(flagstr[i]);
398 } while (*(s++) == ',');
400 if (*(--s) != '\0')
401 goto err_out_parse_error;
403 return flags;
404 err_out_parse_error:
405 return 0;
408 static FILE *fp;
409 static int line_num = 0;
410 static char *line;
411 static char *token[MAX_NR_TOKEN];
412 static int read_nextline = 1;
414 static int get_token(int min, int max)
416 static int line_pos;
417 int i;
418 char c;
420 if (max >= MAX_NR_TOKEN) {
421 mp_msg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_NR_TOKEN!");
422 goto out_eof;
425 memset(token, 0x00, sizeof(*token) * max);
427 if (read_nextline) {
428 if (!fgets(line, MAX_LINE_LEN, fp))
429 goto out_eof;
430 line_pos = 0;
431 ++line_num;
432 read_nextline = 0;
434 for (i = 0; i < max; i++) {
435 while (isspace(line[line_pos]))
436 ++line_pos;
437 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
438 line[line_pos] == ';') {
439 read_nextline = 1;
440 if (i >= min)
441 goto out_ok;
442 goto out_eol;
444 token[i] = line + line_pos;
445 c = line[line_pos];
446 if (c == '"' || c == '\'') {
447 token[i]++;
448 while (line[++line_pos] != c && line[line_pos])
449 /* NOTHING */;
450 } else {
451 for (/* NOTHING */; !isspace(line[line_pos]) &&
452 line[line_pos]; line_pos++)
453 /* NOTHING */;
455 if (!line[line_pos]) {
456 read_nextline = 1;
457 if (i >= min - 1)
458 goto out_ok;
459 goto out_eol;
461 line[line_pos] = '\0';
462 line_pos++;
464 out_ok:
465 return i;
466 out_eof:
467 read_nextline = 1;
468 return RET_EOF;
469 out_eol:
470 return RET_EOL;
473 static codecs_t *video_codecs=NULL;
474 static codecs_t *audio_codecs=NULL;
475 static int nr_vcodecs = 0;
476 static int nr_acodecs = 0;
478 int parse_codec_cfg(char *cfgfile)
480 codecs_t *codec = NULL; // current codec
481 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
482 char *endptr; // strtoul()...
483 int *nr_codecsp;
484 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
485 int tmp, i;
487 // in case we call it a second time
488 if(video_codecs!=NULL)free(video_codecs);
489 video_codecs=NULL;
491 if(audio_codecs!=NULL)free(audio_codecs);
492 audio_codecs=NULL;
494 nr_vcodecs = 0;
495 nr_acodecs = 0;
497 if(cfgfile==NULL) {
498 #ifdef CODECS2HTML
499 return 0;
500 #else
501 video_codecs = builtin_video_codecs;
502 audio_codecs = builtin_audio_codecs;
503 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
504 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
505 return 1;
506 #endif
509 mp_msg(MSGT_CODECCFG,MSGL_INFO,"Reading %s: ", cfgfile);
511 if ((fp = fopen(cfgfile, "r")) == NULL) {
512 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't open '%s': %s\n", cfgfile, strerror(errno));
513 return 0;
516 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
517 mp_msg(MSGT_CODECCFG,MSGL_FATAL,"Can't get memory for 'line': %s\n", strerror(errno));
518 return 0;
520 read_nextline = 1;
523 * this only catches release lines at the start of
524 * codecs.conf, before audiocodecs and videocodecs.
526 while ((tmp = get_token(1, 1)) == RET_EOL)
527 /* NOTHING */;
528 if (tmp == RET_EOF)
529 goto out;
530 if (!strcmp(token[0], "release")) {
531 if (get_token(1, 2) < 0)
532 goto err_out_parse_error;
533 tmp = atoi(token[0]);
534 if (tmp < CODEC_CFG_MIN)
535 goto err_out_release_num;
536 while ((tmp = get_token(1, 1)) == RET_EOL)
537 /* NOTHING */;
538 if (tmp == RET_EOF)
539 goto out;
540 } else
541 goto err_out_release_num;
544 * check if the next block starts with 'audiocodec' or
545 * with 'videocodec'
547 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
548 goto loop_enter;
549 goto err_out_parse_error;
551 while ((tmp = get_token(1, 1)) != RET_EOF) {
552 if (tmp == RET_EOL)
553 continue;
554 if (!strcmp(token[0], "audiocodec") ||
555 !strcmp(token[0], "videocodec")) {
556 if (!validate_codec(codec, codec_type))
557 goto err_out_not_valid;
558 loop_enter:
559 if (*token[0] == 'v') {
560 codec_type = TYPE_VIDEO;
561 nr_codecsp = &nr_vcodecs;
562 codecsp = &video_codecs;
563 } else if (*token[0] == 'a') {
564 codec_type = TYPE_AUDIO;
565 nr_codecsp = &nr_acodecs;
566 codecsp = &audio_codecs;
567 #ifdef DEBUG
568 } else {
569 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
570 goto err_out;
571 #endif
573 if (!(*codecsp = (codecs_t *) realloc(*codecsp,
574 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
575 mp_msg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
576 goto err_out;
578 codec=*codecsp + *nr_codecsp;
579 ++*nr_codecsp;
580 memset(codec,0,sizeof(codecs_t));
581 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
582 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
583 memset(codec->infmt, 0xff, sizeof(codec->infmt));
585 if (get_token(1, 1) < 0)
586 goto err_out_parse_error;
587 for (i = 0; i < *nr_codecsp - 1; i++) {
588 if(( (*codecsp)[i].name!=NULL) &&
589 (!strcmp(token[0], (*codecsp)[i].name)) ) {
590 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
591 goto err_out_print_linenum;
594 if (!(codec->name = strdup(token[0]))) {
595 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
596 goto err_out;
598 } else if (!strcmp(token[0], "info")) {
599 if (codec->info || get_token(1, 1) < 0)
600 goto err_out_parse_error;
601 if (!(codec->info = strdup(token[0]))) {
602 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
603 goto err_out;
605 } else if (!strcmp(token[0], "comment")) {
606 if (get_token(1, 1) < 0)
607 goto err_out_parse_error;
608 add_comment(token[0], &codec->comment);
609 } else if (!strcmp(token[0], "fourcc")) {
610 if (get_token(1, 2) < 0)
611 goto err_out_parse_error;
612 if (!add_to_fourcc(token[0], token[1],
613 codec->fourcc,
614 codec->fourccmap))
615 goto err_out_print_linenum;
616 } else if (!strcmp(token[0], "format")) {
617 if (get_token(1, 2) < 0)
618 goto err_out_parse_error;
619 if (!add_to_format(token[0], token[1],
620 codec->fourcc,codec->fourccmap))
621 goto err_out_print_linenum;
622 } else if (!strcmp(token[0], "driver")) {
623 if (get_token(1, 1) < 0)
624 goto err_out_parse_error;
625 if (!(codec->drv = strdup(token[0]))) {
626 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
627 goto err_out;
629 } else if (!strcmp(token[0], "dll")) {
630 if (get_token(1, 1) < 0)
631 goto err_out_parse_error;
632 if (!(codec->dll = strdup(token[0]))) {
633 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s\n", strerror(errno));
634 goto err_out;
636 } else if (!strcmp(token[0], "guid")) {
637 if (get_token(11, 11) < 0)
638 goto err_out_parse_error;
639 codec->guid.f1=strtoul(token[0],&endptr,0);
640 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
641 *endptr != '\0')
642 goto err_out_parse_error;
643 codec->guid.f2=strtoul(token[1],&endptr,0);
644 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
645 *endptr != '\0')
646 goto err_out_parse_error;
647 codec->guid.f3=strtoul(token[2],&endptr,0);
648 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
649 *endptr != '\0')
650 goto err_out_parse_error;
651 for (i = 0; i < 8; i++) {
652 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
653 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
654 *endptr != '\0')
655 goto err_out_parse_error;
657 } else if (!strcmp(token[0], "out")) {
658 if (get_token(1, 2) < 0)
659 goto err_out_parse_error;
660 if (!add_to_inout(token[0], token[1], codec->outfmt,
661 codec->outflags))
662 goto err_out_print_linenum;
663 } else if (!strcmp(token[0], "in")) {
664 if (get_token(1, 2) < 0)
665 goto err_out_parse_error;
666 if (!add_to_inout(token[0], token[1], codec->infmt,
667 codec->inflags))
668 goto err_out_print_linenum;
669 } else if (!strcmp(token[0], "flags")) {
670 if (get_token(1, 1) < 0)
671 goto err_out_parse_error;
672 if (!strcmp(token[0], "seekable"))
673 codec->flags |= CODECS_FLAG_SEEKABLE;
674 else
675 if (!strcmp(token[0], "align16"))
676 codec->flags |= CODECS_FLAG_ALIGN16;
677 else
678 goto err_out_parse_error;
679 } else if (!strcmp(token[0], "status")) {
680 if (get_token(1, 1) < 0)
681 goto err_out_parse_error;
682 if (!strcasecmp(token[0], "working"))
683 codec->status = CODECS_STATUS_WORKING;
684 else if (!strcasecmp(token[0], "crashing"))
685 codec->status = CODECS_STATUS_NOT_WORKING;
686 else if (!strcasecmp(token[0], "untested"))
687 codec->status = CODECS_STATUS_UNTESTED;
688 else if (!strcasecmp(token[0], "buggy"))
689 codec->status = CODECS_STATUS_PROBLEMS;
690 else
691 goto err_out_parse_error;
692 } else if (!strcmp(token[0], "cpuflags")) {
693 if (get_token(1, 1) < 0)
694 goto err_out_parse_error;
695 if (!(codec->cpuflags = get_cpuflags(token[0])))
696 goto err_out_parse_error;
697 } else
698 goto err_out_parse_error;
700 if (!validate_codec(codec, codec_type))
701 goto err_out_not_valid;
702 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%d audio & %d video codecs\n", nr_acodecs, nr_vcodecs);
703 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
704 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
705 out:
706 free(line);
707 line=NULL;
708 fclose(fp);
709 return 1;
711 err_out_parse_error:
712 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error");
713 err_out_print_linenum:
714 PRINT_LINENUM;
715 err_out:
716 if (audio_codecs)
717 free(audio_codecs);
718 if (video_codecs)
719 free(video_codecs);
720 video_codecs=NULL;
721 audio_codecs=NULL;
723 free(line);
724 line=NULL;
725 line_num = 0;
726 fclose(fp);
727 return 0;
728 err_out_not_valid:
729 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
730 goto err_out_print_linenum;
731 err_out_release_num:
732 mp_msg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
733 goto err_out_print_linenum;
736 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
737 codecs_t *start)
739 return find_codec(fourcc, fourccmap, start, 1);
742 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
743 codecs_t *start)
745 return find_codec(fourcc, fourccmap, start, 0);
748 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
749 codecs_t *start, int audioflag)
751 int i, j;
752 codecs_t *c;
754 #if 0
755 if (start) {
756 for (/* NOTHING */; start->name; start++) {
757 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
758 if (start->fourcc[j] == fourcc) {
759 if (fourccmap)
760 *fourccmap = start->fourccmap[j];
761 return start;
765 } else
766 #endif
768 if (audioflag) {
769 i = nr_acodecs;
770 c = audio_codecs;
771 } else {
772 i = nr_vcodecs;
773 c = video_codecs;
775 if(!i) return NULL;
776 for (/* NOTHING */; i--; c++) {
777 if(start && c<=start) continue;
778 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
779 // FIXME: do NOT hardwire 'null' name here:
780 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
781 if (fourccmap)
782 *fourccmap = c->fourccmap[j];
783 return c;
788 return NULL;
791 void select_codec(char* codecname,int audioflag){
792 int i;
793 codecs_t *c;
794 // printf("select_codec('%s')\n",codecname);
795 if (audioflag) {
796 i = nr_acodecs;
797 c = audio_codecs;
798 } else {
799 i = nr_vcodecs;
800 c = video_codecs;
802 if(i)
803 for (/* NOTHING */; i--; c++)
804 if(!strcmp(c->name,codecname))
805 c->flags|=CODECS_FLAG_SELECTED;
808 void codecs_reset_selection(int audioflag){
809 int i;
810 codecs_t *c;
811 if (audioflag) {
812 i = nr_acodecs;
813 c = audio_codecs;
814 } else {
815 i = nr_vcodecs;
816 c = video_codecs;
818 if(i)
819 for (/* NOTHING */; i--; c++)
820 c->flags&=(~CODECS_FLAG_SELECTED);
823 void list_codecs(int audioflag){
824 int i;
825 codecs_t *c;
827 if (audioflag) {
828 i = nr_acodecs;
829 c = audio_codecs;
830 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
831 } else {
832 i = nr_vcodecs;
833 c = video_codecs;
834 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
836 if(!i) return;
837 for (/* NOTHING */; i--; c++) {
838 char* s="unknown ";
839 switch(c->status){
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;
845 if(c->dll)
846 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
847 else
848 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
856 #ifdef CODECS2HTML
858 * Fake out GUI references when building the codecs2html utility.
860 #ifdef HAVE_NEW_GUI
861 void gtkMessageBox( int type,char * str ) { return; }
862 int use_gui = 0;
863 #endif
865 void wrapline(FILE *f2,char *s){
866 int c;
867 if(!s){
868 fprintf(f2,"-");
869 return;
871 while((c=*s++)){
872 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
876 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
877 int c,d;
878 while((c=fgetc(f1))>=0){
879 if(c!='%'){
880 fputc(c,f2);
881 continue;
883 d=fgetc(f1);
885 switch(d){
886 case '.':
887 return; // end of section
888 case 'n':
889 wrapline(f2,codec->name); break;
890 case 'i':
891 wrapline(f2,codec->info); break;
892 case 'c':
893 wrapline(f2,codec->comment); break;
894 case 'd':
895 wrapline(f2,codec->dll); break;
896 case 'D':
897 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
898 case 'F':
899 for(d=0;d<CODECS_MAX_FOURCC;d++)
900 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
901 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
902 break;
903 case 'f':
904 for(d=0;d<CODECS_MAX_FOURCC;d++)
905 if(codec->fourcc[d]!=0xFFFFFFFF)
906 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
907 break;
908 case 'Y':
909 for(d=0;d<CODECS_MAX_OUTFMT;d++)
910 if(codec->outfmt[d]!=0xFFFFFFFF){
911 for (c=0; fmt_table[c].name; c++)
912 if(fmt_table[c].num==codec->outfmt[d]) break;
913 if(fmt_table[c].name)
914 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
916 break;
917 default:
918 fputc(c,f2);
919 fputc(d,f2);
925 void skiphtml(FILE *f1){
926 int c,d;
927 while((c=fgetc(f1))>=0){
928 if(c!='%'){
929 continue;
931 d=fgetc(f1);
932 if(d=='.') return; // end of section
936 static void print_int_array(const int* a, int size)
938 printf("{ ");
939 while (size--)
940 if(abs(*a)<256)
941 printf("%d%s", *a++, size?", ":"");
942 else
943 printf("0x%X%s", *a++, size?", ":"");
944 printf(" }");
947 static void print_char_array(const unsigned char* a, int size)
949 printf("{ ");
950 while (size--)
951 if((*a)<10)
952 printf("%d%s", *a++, size?", ":"");
953 else
954 printf("0x%02x%s", *a++, size?", ":"");
955 printf(" }");
958 static void print_string(const char* s)
960 if (!s) printf("NULL");
961 else printf("\"%s\"", s);
964 int main(int argc, char* argv[])
966 codecs_t *cl;
967 FILE *f1;
968 FILE *f2;
969 int c,d,i;
970 int pos;
971 int section=-1;
972 int nr_codecs;
973 int win32=-1;
974 int dshow=-1;
975 int win32ex=-1;
978 * Take path to codecs.conf from command line, or fall back on
979 * etc/codecs.conf
981 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
982 exit(1);
984 if (argc > 1) {
985 int i, j;
986 const char* nm[2];
987 codecs_t* cod[2];
988 int nr[2];
990 nm[0] = "builtin_video_codecs";
991 cod[0] = video_codecs;
992 nr[0] = nr_vcodecs;
994 nm[1] = "builtin_audio_codecs";
995 cod[1] = audio_codecs;
996 nr[1] = nr_acodecs;
998 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1000 for (i=0; i<2; i++) {
1001 printf("codecs_t %s[] = {\n", nm[i]);
1002 for (j = 0; j < nr[i]; j++) {
1003 printf("{");
1005 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1006 printf(", /* fourcc */\n");
1008 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1009 printf(", /* fourccmap */\n");
1011 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1012 printf(", /* outfmt */\n");
1014 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1015 printf(", /* outflags */\n");
1017 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1018 printf(", /* infmt */\n");
1020 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1021 printf(", /* inflags */\n");
1023 print_string(cod[i][j].name); printf(", /* name */\n");
1024 print_string(cod[i][j].info); printf(", /* info */\n");
1025 print_string(cod[i][j].comment); printf(", /* comment */\n");
1026 print_string(cod[i][j].dll); printf(", /* dll */\n");
1027 print_string(cod[i][j].drv); printf(", /* drv */\n");
1029 printf("{ 0x%08lx, %hu, %hu,",
1030 cod[i][j].guid.f1,
1031 cod[i][j].guid.f2,
1032 cod[i][j].guid.f3);
1033 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1034 printf(" }, /* GUID */\n");
1035 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1036 cod[i][j].flags,
1037 cod[i][j].status,
1038 cod[i][j].cpuflags);
1039 if (j < nr[i]) printf(",\n");
1041 printf("};\n\n");
1043 exit(0);
1046 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1047 f2=fopen("DOCS/en/codecs-status.html","wb"); if(!f2) exit(1);
1049 while((c=fgetc(f1))>=0){
1050 if(c!='%'){
1051 fputc(c,f2);
1052 continue;
1054 d=fgetc(f1);
1055 if(d>='0' && d<='9'){
1056 // begin section
1057 section=d-'0';
1058 printf("BEGIN %d\n",section);
1059 if(section>=5){
1060 // audio
1061 cl = audio_codecs;
1062 nr_codecs = nr_acodecs;
1063 dshow=7;win32=4;
1064 } else {
1065 // video
1066 cl = video_codecs;
1067 nr_codecs = nr_vcodecs;
1068 dshow=4;win32=2;win32ex=6;
1070 pos=ftell(f1);
1071 for(i=0;i<nr_codecs;i++){
1072 fseek(f1,pos,SEEK_SET);
1073 switch(section){
1074 case 0:
1075 case 5:
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],section,dshow);
1079 break;
1080 #if 0
1081 case 1:
1082 case 6:
1083 if(cl[i].status==CODECS_STATUS_WORKING)
1084 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1085 parsehtml(f1,f2,&cl[i],section,dshow);
1086 break;
1087 #endif
1088 case 2:
1089 case 7:
1090 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1091 parsehtml(f1,f2,&cl[i],section,dshow);
1092 break;
1093 case 3:
1094 case 8:
1095 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1096 parsehtml(f1,f2,&cl[i],section,dshow);
1097 break;
1098 case 4:
1099 case 9:
1100 if(cl[i].status==CODECS_STATUS_UNTESTED)
1101 parsehtml(f1,f2,&cl[i],section,dshow);
1102 break;
1103 default:
1104 printf("Warning! unimplemented section: %d\n",section);
1107 fseek(f1,pos,SEEK_SET);
1108 skiphtml(f1);
1109 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1111 continue;
1113 fputc(c,f2);
1114 fputc(d,f2);
1117 fclose(f2);
1118 fclose(f1);
1119 return 0;
1122 #endif
1124 #ifdef TESTING
1125 int main(void)
1127 codecs_t *c;
1128 int i,j, nr_codecs, state;
1130 if (!(parse_codec_cfg("etc/codecs.conf")))
1131 return 0;
1132 if (!video_codecs)
1133 printf("no videoconfig.\n");
1134 if (!audio_codecs)
1135 printf("no audioconfig.\n");
1137 printf("videocodecs:\n");
1138 c = video_codecs;
1139 nr_codecs = nr_vcodecs;
1140 state = 0;
1141 next:
1142 if (c) {
1143 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1144 nr_codecs);
1145 for(i=0;i<nr_codecs;i++, c++){
1146 printf("\n============== %scodec %02d ===============\n",
1147 state==0?"video":"audio",i);
1148 printf("name='%s'\n",c->name);
1149 printf("info='%s'\n",c->info);
1150 printf("comment='%s'\n",c->comment);
1151 printf("dll='%s'\n",c->dll);
1152 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1153 c->flags, c->driver, c->status, c->cpuflags);
1155 for(j=0;j<CODECS_MAX_FOURCC;j++){
1156 if(c->fourcc[j]!=0xFFFFFFFF){
1157 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1161 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1162 if(c->outfmt[j]!=0xFFFFFFFF){
1163 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1167 for(j=0;j<CODECS_MAX_INFMT;j++){
1168 if(c->infmt[j]!=0xFFFFFFFF){
1169 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1173 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1174 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1175 printf("\n");
1180 if (!state) {
1181 printf("audiocodecs:\n");
1182 c = audio_codecs;
1183 nr_codecs = nr_acodecs;
1184 state = 1;
1185 goto next;
1187 return 0;
1190 #endif