Make "Menu" button of AppleIR remote call OSD Menu instead
[mplayer/greg.git] / codec-cfg.c
blob1ffd22c2f7853fed4d989b909e971b20cb8fb9fe
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>
28 #include "config.h"
29 #include "mp_msg.h"
30 #ifdef CODECS2HTML
31 #ifdef __GNUC__
32 #define mp_msg(t, l, m, args...) fprintf(stderr, m, ##args)
33 #else
34 #define mp_msg(t, l, ...) fprintf(stderr, __VA_ARGS__)
35 #endif
36 #endif
38 #include "help_mp.h"
40 // for mmioFOURCC:
41 #include "libmpdemux/aviheader.h"
43 #include "libmpcodecs/img_format.h"
44 #include "codec-cfg.h"
46 #ifndef CODECS2HTML
47 #include "codecs.conf.h"
48 #endif
50 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
52 #define MAX_NR_TOKEN 16
54 #define MAX_LINE_LEN 1000
56 #define RET_EOF -1
57 #define RET_EOL -2
59 #define TYPE_VIDEO 0
60 #define TYPE_AUDIO 1
62 char * codecs_file = NULL;
64 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
65 unsigned int *map)
67 int i, j, freeslots;
68 unsigned int tmp;
70 /* find first unused slot */
71 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
72 /* NOTHING */;
73 freeslots = CODECS_MAX_FOURCC - i;
74 if (!freeslots)
75 goto err_out_too_many;
77 do {
78 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
79 for (j = 0; j < i; j++)
80 if (tmp == fourcc[j])
81 goto err_out_duplicated;
82 fourcc[i] = tmp;
83 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
84 s += 4;
85 i++;
86 } while ((*(s++) == ',') && --freeslots);
88 if (!freeslots)
89 goto err_out_too_many;
90 if (*(--s) != '\0')
91 goto err_out_parse_error;
92 return 1;
93 err_out_duplicated:
94 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFourcc);
95 return 0;
96 err_out_too_many:
97 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
98 return 0;
99 err_out_parse_error:
100 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
101 return 0;
104 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
106 int i, j;
107 char *endptr;
109 /* find first unused slot */
110 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
111 /* NOTHING */;
112 if (i == CODECS_MAX_FOURCC) {
113 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
114 return 0;
117 fourcc[i]=strtoul(s,&endptr,0);
118 if (*endptr != '\0') {
119 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDNotNumber);
120 return 0;
123 if(alias){
124 fourccmap[i]=strtoul(alias,&endptr,0);
125 if (*endptr != '\0') {
126 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDAliasNotNumber);
127 return 0;
129 } else
130 fourccmap[i]=fourcc[i];
132 for (j = 0; j < i; j++)
133 if (fourcc[j] == fourcc[i]) {
134 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFID);
135 return 0;
138 return 1;
141 static struct {
142 const char *name;
143 const unsigned int num;
144 } fmt_table[] = {
145 {"YV12", IMGFMT_YV12},
146 {"I420", IMGFMT_I420},
147 {"IYUV", IMGFMT_IYUV},
148 {"NV12", IMGFMT_NV12},
149 {"NV21", IMGFMT_NV21},
150 {"YVU9", IMGFMT_YVU9},
151 {"IF09", IMGFMT_IF09},
152 {"444P", IMGFMT_444P},
153 {"422P", IMGFMT_422P},
154 {"411P", IMGFMT_411P},
155 {"Y800", IMGFMT_Y800},
156 {"Y8", IMGFMT_Y8},
158 {"YUY2", IMGFMT_YUY2},
159 {"UYVY", IMGFMT_UYVY},
160 {"YVYU", IMGFMT_YVYU},
162 {"RGB4", IMGFMT_RGB|4},
163 {"RGB8", IMGFMT_RGB|8},
164 {"RGB15", IMGFMT_RGB|15},
165 {"RGB16", IMGFMT_RGB|16},
166 {"RGB24", IMGFMT_RGB|24},
167 {"RGB32", IMGFMT_RGB|32},
168 {"BGR4", IMGFMT_BGR|4},
169 {"BGR8", IMGFMT_BGR|8},
170 {"BGR15", IMGFMT_BGR|15},
171 {"BGR16", IMGFMT_BGR|16},
172 {"BGR24", IMGFMT_BGR|24},
173 {"BGR32", IMGFMT_BGR|32},
174 {"RGB1", IMGFMT_RGB|1},
175 {"BGR1", IMGFMT_BGR|1},
177 {"MPES", IMGFMT_MPEGPES},
178 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
179 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
180 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
182 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
183 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
185 {NULL, 0}
189 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
190 unsigned char *outflags)
193 static char *flagstr[] = {
194 "flip",
195 "noflip",
196 "yuvhack",
197 "query",
198 "static",
199 NULL
202 int i, j, freeslots;
203 unsigned char flags;
205 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
206 /* NOTHING */;
207 freeslots = CODECS_MAX_OUTFMT - i;
208 if (!freeslots)
209 goto err_out_too_many;
211 flags = 0;
212 if(sflags) {
213 do {
214 for (j = 0; flagstr[j] != NULL; j++)
215 if (!strncmp(sflags, flagstr[j],
216 strlen(flagstr[j])))
217 break;
218 if (flagstr[j] == NULL)
219 goto err_out_parse_error;
220 flags|=(1<<j);
221 sflags+=strlen(flagstr[j]);
222 } while (*(sflags++) == ',');
224 if (*(--sflags) != '\0')
225 goto err_out_parse_error;
228 do {
229 for (j = 0; fmt_table[j].name != NULL; j++)
230 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
231 break;
232 if (fmt_table[j].name == NULL)
233 goto err_out_parse_error;
234 outfmt[i] = fmt_table[j].num;
235 outflags[i] = flags;
236 ++i;
237 sfmt+=strlen(fmt_table[j].name);
238 } while ((*(sfmt++) == ',') && --freeslots);
240 if (!freeslots)
241 goto err_out_too_many;
243 if (*(--sfmt) != '\0')
244 goto err_out_parse_error;
246 return 1;
247 err_out_too_many:
248 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyOut);
249 return 0;
250 err_out_parse_error:
251 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
252 return 0;
255 #if 0
256 static short get_driver(char *s,int audioflag)
258 static char *audiodrv[] = {
259 "null",
260 "mp3lib",
261 "pcm",
262 "libac3",
263 "acm",
264 "alaw",
265 "msgsm",
266 "dshow",
267 "dvdpcm",
268 "hwac3",
269 "libvorbis",
270 "ffmpeg",
271 "libmad",
272 "msadpcm",
273 "liba52",
274 "g72x",
275 "imaadpcm",
276 "dk4adpcm",
277 "dk3adpcm",
278 "roqaudio",
279 "faad",
280 "realaud",
281 "libdv",
282 NULL
284 static char *videodrv[] = {
285 "null",
286 "libmpeg2",
287 "vfw",
288 "dshow",
289 "ffmpeg",
290 "vfwex",
291 "raw",
292 "msrle",
293 "xanim",
294 "msvidc",
295 "fli",
296 "cinepak",
297 "qtrle",
298 "nuv",
299 "cyuv",
300 "qtsmc",
301 "ducktm1",
302 "roqvideo",
303 "qtrpza",
304 "mpng",
305 "ijpg",
306 "zlib",
307 "mpegpes",
308 "zrmjpeg",
309 "realvid",
310 "xvid",
311 "libdv",
312 NULL
314 char **drv=audioflag?audiodrv:videodrv;
315 int i;
317 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
319 return -1;
321 #endif
323 static int validate_codec(codecs_t *c, int type)
325 unsigned int i;
326 char *tmp_name = c->name;
328 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
329 /* NOTHING */;
331 if (i < strlen(tmp_name)) {
332 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_InvalidCodecName, c->name);
333 return 0;
336 if (!c->info)
337 c->info = strdup(c->name);
339 #if 0
340 if (c->fourcc[0] == 0xffffffff) {
341 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksFourcc, c->name);
342 return 0;
344 #endif
346 if (!c->drv) {
347 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksDriver, c->name);
348 return 0;
351 #if 0
352 #warning codec->driver == 4;... <- this should not be put in here...
353 #warning Where are they defined ????????????
354 if (!c->dll && (c->driver == 4 ||
355 (c->driver == 2 && type == TYPE_VIDEO))) {
356 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsDLL, c->name);
357 return 0;
359 #warning Can guid.f1 be 0? How does one know that it was not given?
360 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
362 if (type == TYPE_VIDEO)
363 if (c->outfmt[0] == 0xffffffff) {
364 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsOutfmt, c->name);
365 return 0;
367 #endif
368 return 1;
371 static int add_comment(char *s, char **d)
373 int pos;
375 if (!*d)
376 pos = 0;
377 else {
378 pos = strlen(*d);
379 (*d)[pos++] = '\n';
381 if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
382 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantAllocateComment);
383 return 0;
385 strcpy(*d + pos, s);
386 return 1;
389 static short get_cpuflags(char *s)
391 static char *flagstr[] = {
392 "mmx",
393 "sse",
394 "3dnow",
395 NULL
397 int i;
398 short flags = 0;
400 do {
401 for (i = 0; flagstr[i]; i++)
402 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
403 break;
404 if (!flagstr[i])
405 goto err_out_parse_error;
406 flags |= 1<<i;
407 s += strlen(flagstr[i]);
408 } while (*(s++) == ',');
410 if (*(--s) != '\0')
411 goto err_out_parse_error;
413 return flags;
414 err_out_parse_error:
415 return 0;
418 static FILE *fp;
419 static int line_num = 0;
420 static char *line;
421 static char *token[MAX_NR_TOKEN];
422 static int read_nextline = 1;
424 static int get_token(int min, int max)
426 static int line_pos;
427 int i;
428 char c;
430 if (max >= MAX_NR_TOKEN) {
431 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN);
432 goto out_eof;
435 memset(token, 0x00, sizeof(*token) * max);
437 if (read_nextline) {
438 if (!fgets(line, MAX_LINE_LEN, fp))
439 goto out_eof;
440 line_pos = 0;
441 ++line_num;
442 read_nextline = 0;
444 for (i = 0; i < max; i++) {
445 while (isspace(line[line_pos]))
446 ++line_pos;
447 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
448 line[line_pos] == ';') {
449 read_nextline = 1;
450 if (i >= min)
451 goto out_ok;
452 goto out_eol;
454 token[i] = line + line_pos;
455 c = line[line_pos];
456 if (c == '"' || c == '\'') {
457 token[i]++;
458 while (line[++line_pos] != c && line[line_pos])
459 /* NOTHING */;
460 } else {
461 for (/* NOTHING */; !isspace(line[line_pos]) &&
462 line[line_pos]; line_pos++)
463 /* NOTHING */;
465 if (!line[line_pos]) {
466 read_nextline = 1;
467 if (i >= min - 1)
468 goto out_ok;
469 goto out_eol;
471 line[line_pos] = '\0';
472 line_pos++;
474 out_ok:
475 return i;
476 out_eof:
477 read_nextline = 1;
478 return RET_EOF;
479 out_eol:
480 return RET_EOL;
483 static codecs_t *video_codecs=NULL;
484 static codecs_t *audio_codecs=NULL;
485 static int nr_vcodecs = 0;
486 static int nr_acodecs = 0;
488 int parse_codec_cfg(const char *cfgfile)
490 codecs_t *codec = NULL; // current codec
491 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
492 char *endptr; // strtoul()...
493 int *nr_codecsp;
494 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
495 int tmp, i;
497 // in case we call it a second time
498 codecs_uninit_free();
500 nr_vcodecs = 0;
501 nr_acodecs = 0;
503 if(cfgfile==NULL) {
504 #ifdef CODECS2HTML
505 return 0;
506 #else
507 video_codecs = builtin_video_codecs;
508 audio_codecs = builtin_audio_codecs;
509 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
510 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
511 return 1;
512 #endif
515 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_ReadingFile, cfgfile);
517 if ((fp = fopen(cfgfile, "r")) == NULL) {
518 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_CantOpenFileError, cfgfile, strerror(errno));
519 return 0;
522 if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) {
523 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantGetMemoryForLine, strerror(errno));
524 return 0;
526 read_nextline = 1;
529 * this only catches release lines at the start of
530 * codecs.conf, before audiocodecs and videocodecs.
532 while ((tmp = get_token(1, 1)) == RET_EOL)
533 /* NOTHING */;
534 if (tmp == RET_EOF)
535 goto out;
536 if (!strcmp(token[0], "release")) {
537 if (get_token(1, 2) < 0)
538 goto err_out_parse_error;
539 tmp = atoi(token[0]);
540 if (tmp < CODEC_CFG_MIN)
541 goto err_out_release_num;
542 while ((tmp = get_token(1, 1)) == RET_EOL)
543 /* NOTHING */;
544 if (tmp == RET_EOF)
545 goto out;
546 } else
547 goto err_out_release_num;
550 * check if the next block starts with 'audiocodec' or
551 * with 'videocodec'
553 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
554 goto loop_enter;
555 goto err_out_parse_error;
557 while ((tmp = get_token(1, 1)) != RET_EOF) {
558 if (tmp == RET_EOL)
559 continue;
560 if (!strcmp(token[0], "audiocodec") ||
561 !strcmp(token[0], "videocodec")) {
562 if (!validate_codec(codec, codec_type))
563 goto err_out_not_valid;
564 loop_enter:
565 if (*token[0] == 'v') {
566 codec_type = TYPE_VIDEO;
567 nr_codecsp = &nr_vcodecs;
568 codecsp = &video_codecs;
569 } else if (*token[0] == 'a') {
570 codec_type = TYPE_AUDIO;
571 nr_codecsp = &nr_acodecs;
572 codecsp = &audio_codecs;
573 #ifdef DEBUG
574 } else {
575 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
576 goto err_out;
577 #endif
579 if (!(*codecsp = realloc(*codecsp,
580 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
581 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantReallocCodecsp, strerror(errno));
582 goto err_out;
584 codec=*codecsp + *nr_codecsp;
585 ++*nr_codecsp;
586 memset(codec,0,sizeof(codecs_t));
587 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
588 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
589 memset(codec->infmt, 0xff, sizeof(codec->infmt));
591 if (get_token(1, 1) < 0)
592 goto err_out_parse_error;
593 for (i = 0; i < *nr_codecsp - 1; i++) {
594 if(( (*codecsp)[i].name!=NULL) &&
595 (!strcmp(token[0], (*codecsp)[i].name)) ) {
596 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNameNotUnique, token[0]);
597 goto err_out_print_linenum;
600 if (!(codec->name = strdup(token[0]))) {
601 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupName, strerror(errno));
602 goto err_out;
604 } else if (!strcmp(token[0], "info")) {
605 if (codec->info || get_token(1, 1) < 0)
606 goto err_out_parse_error;
607 if (!(codec->info = strdup(token[0]))) {
608 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupInfo, strerror(errno));
609 goto err_out;
611 } else if (!strcmp(token[0], "comment")) {
612 if (get_token(1, 1) < 0)
613 goto err_out_parse_error;
614 add_comment(token[0], &codec->comment);
615 } else if (!strcmp(token[0], "fourcc")) {
616 if (get_token(1, 2) < 0)
617 goto err_out_parse_error;
618 if (!add_to_fourcc(token[0], token[1],
619 codec->fourcc,
620 codec->fourccmap))
621 goto err_out_print_linenum;
622 } else if (!strcmp(token[0], "format")) {
623 if (get_token(1, 2) < 0)
624 goto err_out_parse_error;
625 if (!add_to_format(token[0], token[1],
626 codec->fourcc,codec->fourccmap))
627 goto err_out_print_linenum;
628 } else if (!strcmp(token[0], "driver")) {
629 if (get_token(1, 1) < 0)
630 goto err_out_parse_error;
631 if (!(codec->drv = strdup(token[0]))) {
632 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDriver, strerror(errno));
633 goto err_out;
635 } else if (!strcmp(token[0], "dll")) {
636 if (get_token(1, 1) < 0)
637 goto err_out_parse_error;
638 if (!(codec->dll = strdup(token[0]))) {
639 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDLL, strerror(errno));
640 goto err_out;
642 } else if (!strcmp(token[0], "guid")) {
643 if (get_token(11, 11) < 0)
644 goto err_out_parse_error;
645 codec->guid.f1=strtoul(token[0],&endptr,0);
646 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
647 *endptr != '\0')
648 goto err_out_parse_error;
649 codec->guid.f2=strtoul(token[1],&endptr,0);
650 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
651 *endptr != '\0')
652 goto err_out_parse_error;
653 codec->guid.f3=strtoul(token[2],&endptr,0);
654 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
655 *endptr != '\0')
656 goto err_out_parse_error;
657 for (i = 0; i < 8; i++) {
658 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
659 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
660 *endptr != '\0')
661 goto err_out_parse_error;
663 } else if (!strcmp(token[0], "out")) {
664 if (get_token(1, 2) < 0)
665 goto err_out_parse_error;
666 if (!add_to_inout(token[0], token[1], codec->outfmt,
667 codec->outflags))
668 goto err_out_print_linenum;
669 } else if (!strcmp(token[0], "in")) {
670 if (get_token(1, 2) < 0)
671 goto err_out_parse_error;
672 if (!add_to_inout(token[0], token[1], codec->infmt,
673 codec->inflags))
674 goto err_out_print_linenum;
675 } else if (!strcmp(token[0], "flags")) {
676 if (get_token(1, 1) < 0)
677 goto err_out_parse_error;
678 if (!strcmp(token[0], "seekable"))
679 codec->flags |= CODECS_FLAG_SEEKABLE;
680 else
681 if (!strcmp(token[0], "align16"))
682 codec->flags |= CODECS_FLAG_ALIGN16;
683 else
684 goto err_out_parse_error;
685 } else if (!strcmp(token[0], "status")) {
686 if (get_token(1, 1) < 0)
687 goto err_out_parse_error;
688 if (!strcasecmp(token[0], "working"))
689 codec->status = CODECS_STATUS_WORKING;
690 else if (!strcasecmp(token[0], "crashing"))
691 codec->status = CODECS_STATUS_NOT_WORKING;
692 else if (!strcasecmp(token[0], "untested"))
693 codec->status = CODECS_STATUS_UNTESTED;
694 else if (!strcasecmp(token[0], "buggy"))
695 codec->status = CODECS_STATUS_PROBLEMS;
696 else
697 goto err_out_parse_error;
698 } else if (!strcmp(token[0], "cpuflags")) {
699 if (get_token(1, 1) < 0)
700 goto err_out_parse_error;
701 if (!(codec->cpuflags = get_cpuflags(token[0])))
702 goto err_out_parse_error;
703 } else
704 goto err_out_parse_error;
706 if (!validate_codec(codec, codec_type))
707 goto err_out_not_valid;
708 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_AudioVideoCodecTotals, nr_acodecs, nr_vcodecs);
709 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
710 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
711 out:
712 free(line);
713 line=NULL;
714 fclose(fp);
715 return 1;
717 err_out_parse_error:
718 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
719 err_out_print_linenum:
720 PRINT_LINENUM;
721 err_out:
722 codecs_uninit_free();
724 free(line);
725 line=NULL;
726 line_num = 0;
727 fclose(fp);
728 return 0;
729 err_out_not_valid:
730 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecDefinitionIncorrect);
731 goto err_out_print_linenum;
732 err_out_release_num:
733 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_OutdatedCodecsConf);
734 goto err_out_print_linenum;
737 static void codecs_free(codecs_t* codecs,int count) {
738 int i;
739 for ( i = 0; i < count; i++)
740 if ( codecs[i].name ) {
741 if( codecs[i].name )
742 free(codecs[i].name);
743 if( codecs[i].info )
744 free(codecs[i].info);
745 if( codecs[i].comment )
746 free(codecs[i].comment);
747 if( codecs[i].dll )
748 free(codecs[i].dll);
749 if( codecs[i].drv )
750 free(codecs[i].drv);
752 if (codecs)
753 free(codecs);
756 void codecs_uninit_free(void) {
757 if (video_codecs)
758 codecs_free(video_codecs,nr_vcodecs);
759 video_codecs=NULL;
760 if (audio_codecs)
761 codecs_free(audio_codecs,nr_acodecs);
762 audio_codecs=NULL;
765 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
766 codecs_t *start, int force)
768 return find_codec(fourcc, fourccmap, start, 1, force);
771 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
772 codecs_t *start, int force)
774 return find_codec(fourcc, fourccmap, start, 0, force);
777 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
778 codecs_t *start, int audioflag, int force)
780 int i, j;
781 codecs_t *c;
783 #if 0
784 if (start) {
785 for (/* NOTHING */; start->name; start++) {
786 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
787 if (start->fourcc[j] == fourcc) {
788 if (fourccmap)
789 *fourccmap = start->fourccmap[j];
790 return start;
794 } else
795 #endif
797 if (audioflag) {
798 i = nr_acodecs;
799 c = audio_codecs;
800 } else {
801 i = nr_vcodecs;
802 c = video_codecs;
804 if(!i) return NULL;
805 for (/* NOTHING */; i--; c++) {
806 if(start && c<=start) continue;
807 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
808 // FIXME: do NOT hardwire 'null' name here:
809 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
810 if (fourccmap)
811 *fourccmap = c->fourccmap[j];
812 return c;
815 if (force) return c;
818 return NULL;
821 void stringset_init(stringset_t *set) {
822 *set = calloc(1, sizeof(char *));
825 void stringset_free(stringset_t *set) {
826 int count = 0;
827 while ((*set)[count]) free((*set)[count++]);
828 free(*set);
829 *set = NULL;
832 void stringset_add(stringset_t *set, const char *str) {
833 int count = 0;
834 while ((*set)[count]) count++;
835 count++;
836 *set = realloc(*set, sizeof(char *) * (count + 1));
837 (*set)[count - 1] = strdup(str);
838 (*set)[count] = NULL;
841 int stringset_test(stringset_t *set, const char *str) {
842 stringset_t s;
843 for (s = *set; *s; s++)
844 if (strcmp(*s, str) == 0)
845 return 1;
846 return 0;
849 void list_codecs(int audioflag){
850 int i;
851 codecs_t *c;
853 if (audioflag) {
854 i = nr_acodecs;
855 c = audio_codecs;
856 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
857 } else {
858 i = nr_vcodecs;
859 c = video_codecs;
860 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
862 if(!i) return;
863 for (/* NOTHING */; i--; c++) {
864 char* s="unknown ";
865 switch(c->status){
866 case CODECS_STATUS_WORKING: s="working ";break;
867 case CODECS_STATUS_PROBLEMS: s="problems";break;
868 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
869 case CODECS_STATUS_UNTESTED: s="untested";break;
871 if(c->dll)
872 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
873 else
874 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
882 #ifdef CODECS2HTML
884 * Fake out GUI references when building the codecs2html utility.
886 #ifdef HAVE_NEW_GUI
887 void gtkMessageBox( int type,char * str ) { return; }
888 int use_gui = 0;
889 #endif
891 void wrapline(FILE *f2,char *s){
892 int c;
893 if(!s){
894 fprintf(f2,"-");
895 return;
897 while((c=*s++)){
898 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
902 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
903 int c,d;
904 while((c=fgetc(f1))>=0){
905 if(c!='%'){
906 fputc(c,f2);
907 continue;
909 d=fgetc(f1);
911 switch(d){
912 case '.':
913 return; // end of section
914 case 'n':
915 wrapline(f2,codec->name); break;
916 case 'i':
917 wrapline(f2,codec->info); break;
918 case 'c':
919 wrapline(f2,codec->comment); break;
920 case 'd':
921 wrapline(f2,codec->dll); break;
922 case 'D':
923 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
924 case 'F':
925 for(d=0;d<CODECS_MAX_FOURCC;d++)
926 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
927 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
928 break;
929 case 'f':
930 for(d=0;d<CODECS_MAX_FOURCC;d++)
931 if(codec->fourcc[d]!=0xFFFFFFFF)
932 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
933 break;
934 case 'Y':
935 for(d=0;d<CODECS_MAX_OUTFMT;d++)
936 if(codec->outfmt[d]!=0xFFFFFFFF){
937 for (c=0; fmt_table[c].name; c++)
938 if(fmt_table[c].num==codec->outfmt[d]) break;
939 if(fmt_table[c].name)
940 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
942 break;
943 default:
944 fputc(c,f2);
945 fputc(d,f2);
951 void skiphtml(FILE *f1){
952 int c,d;
953 while((c=fgetc(f1))>=0){
954 if(c!='%'){
955 continue;
957 d=fgetc(f1);
958 if(d=='.') return; // end of section
962 static void print_int_array(const int* a, int size)
964 printf("{ ");
965 while (size--)
966 if(abs(*a)<256)
967 printf("%d%s", *a++, size?", ":"");
968 else
969 printf("0x%X%s", *a++, size?", ":"");
970 printf(" }");
973 static void print_char_array(const unsigned char* a, int size)
975 printf("{ ");
976 while (size--)
977 if((*a)<10)
978 printf("%d%s", *a++, size?", ":"");
979 else
980 printf("0x%02x%s", *a++, size?", ":"");
981 printf(" }");
984 static void print_string(const char* s)
986 if (!s) printf("NULL");
987 else printf("\"%s\"", s);
990 int main(int argc, char* argv[])
992 codecs_t *cl;
993 FILE *f1;
994 FILE *f2;
995 int c,d,i;
996 int pos;
997 int section=-1;
998 int nr_codecs;
999 int win32=-1;
1000 int dshow=-1;
1001 int win32ex=-1;
1004 * Take path to codecs.conf from command line, or fall back on
1005 * etc/codecs.conf
1007 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1008 exit(1);
1010 if (argc > 1) {
1011 int i, j;
1012 const char* nm[2];
1013 codecs_t* cod[2];
1014 int nr[2];
1016 nm[0] = "builtin_video_codecs";
1017 cod[0] = video_codecs;
1018 nr[0] = nr_vcodecs;
1020 nm[1] = "builtin_audio_codecs";
1021 cod[1] = audio_codecs;
1022 nr[1] = nr_acodecs;
1024 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1025 printf("#include <stddef.h>\n",argv[1]);
1026 printf("#include \"codec-cfg.h\"\n\n",argv[1]);
1028 for (i=0; i<2; i++) {
1029 printf("const codecs_t %s[] = {\n", nm[i]);
1030 for (j = 0; j < nr[i]; j++) {
1031 printf("{");
1033 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1034 printf(", /* fourcc */\n");
1036 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1037 printf(", /* fourccmap */\n");
1039 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1040 printf(", /* outfmt */\n");
1042 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1043 printf(", /* outflags */\n");
1045 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1046 printf(", /* infmt */\n");
1048 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1049 printf(", /* inflags */\n");
1051 print_string(cod[i][j].name); printf(", /* name */\n");
1052 print_string(cod[i][j].info); printf(", /* info */\n");
1053 print_string(cod[i][j].comment); printf(", /* comment */\n");
1054 print_string(cod[i][j].dll); printf(", /* dll */\n");
1055 print_string(cod[i][j].drv); printf(", /* drv */\n");
1057 printf("{ 0x%08lx, %hu, %hu,",
1058 cod[i][j].guid.f1,
1059 cod[i][j].guid.f2,
1060 cod[i][j].guid.f3);
1061 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1062 printf(" }, /* GUID */\n");
1063 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1064 cod[i][j].flags,
1065 cod[i][j].status,
1066 cod[i][j].cpuflags);
1067 if (j < nr[i]) printf(",\n");
1069 printf("};\n\n");
1071 exit(0);
1074 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1075 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1077 while((c=fgetc(f1))>=0){
1078 if(c!='%'){
1079 fputc(c,f2);
1080 continue;
1082 d=fgetc(f1);
1083 if(d>='0' && d<='9'){
1084 // begin section
1085 section=d-'0';
1086 //printf("BEGIN %d\n",section);
1087 if(section>=5){
1088 // audio
1089 cl = audio_codecs;
1090 nr_codecs = nr_acodecs;
1091 dshow=7;win32=4;
1092 } else {
1093 // video
1094 cl = video_codecs;
1095 nr_codecs = nr_vcodecs;
1096 dshow=4;win32=2;win32ex=6;
1098 pos=ftell(f1);
1099 for(i=0;i<nr_codecs;i++){
1100 fseek(f1,pos,SEEK_SET);
1101 switch(section){
1102 case 0:
1103 case 5:
1104 if(cl[i].status==CODECS_STATUS_WORKING)
1105 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1106 parsehtml(f1,f2,&cl[i],section,dshow);
1107 break;
1108 #if 0
1109 case 1:
1110 case 6:
1111 if(cl[i].status==CODECS_STATUS_WORKING)
1112 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1113 parsehtml(f1,f2,&cl[i],section,dshow);
1114 break;
1115 #endif
1116 case 2:
1117 case 7:
1118 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1119 parsehtml(f1,f2,&cl[i],section,dshow);
1120 break;
1121 case 3:
1122 case 8:
1123 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1124 parsehtml(f1,f2,&cl[i],section,dshow);
1125 break;
1126 case 4:
1127 case 9:
1128 if(cl[i].status==CODECS_STATUS_UNTESTED)
1129 parsehtml(f1,f2,&cl[i],section,dshow);
1130 break;
1131 default:
1132 printf("Warning! unimplemented section: %d\n",section);
1135 fseek(f1,pos,SEEK_SET);
1136 skiphtml(f1);
1137 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1139 continue;
1141 fputc(c,f2);
1142 fputc(d,f2);
1145 fclose(f2);
1146 fclose(f1);
1147 return 0;
1150 #endif
1152 #ifdef TESTING
1153 int main(void)
1155 codecs_t *c;
1156 int i,j, nr_codecs, state;
1158 if (!(parse_codec_cfg("etc/codecs.conf")))
1159 return 0;
1160 if (!video_codecs)
1161 printf("no videoconfig.\n");
1162 if (!audio_codecs)
1163 printf("no audioconfig.\n");
1165 printf("videocodecs:\n");
1166 c = video_codecs;
1167 nr_codecs = nr_vcodecs;
1168 state = 0;
1169 next:
1170 if (c) {
1171 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1172 nr_codecs);
1173 for(i=0;i<nr_codecs;i++, c++){
1174 printf("\n============== %scodec %02d ===============\n",
1175 state==0?"video":"audio",i);
1176 printf("name='%s'\n",c->name);
1177 printf("info='%s'\n",c->info);
1178 printf("comment='%s'\n",c->comment);
1179 printf("dll='%s'\n",c->dll);
1180 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1181 c->flags, c->driver, c->status, c->cpuflags);
1183 for(j=0;j<CODECS_MAX_FOURCC;j++){
1184 if(c->fourcc[j]!=0xFFFFFFFF){
1185 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1189 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1190 if(c->outfmt[j]!=0xFFFFFFFF){
1191 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1195 for(j=0;j<CODECS_MAX_INFMT;j++){
1196 if(c->infmt[j]!=0xFFFFFFFF){
1197 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1201 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1202 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1203 printf("\n");
1208 if (!state) {
1209 printf("audiocodecs:\n");
1210 c = audio_codecs;
1211 nr_codecs = nr_acodecs;
1212 state = 1;
1213 goto next;
1215 return 0;
1218 #endif