fix smb libs inclusion when using --enable-smb.
[mplayer/glamo.git] / codec-cfg.c
blob13071675d7e5b74945c63642a42cf0bd55fd1841
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 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
52 unsigned int *map)
54 int i, j, freeslots;
55 unsigned int tmp;
57 /* find first unused slot */
58 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
59 /* NOTHING */;
60 freeslots = CODECS_MAX_FOURCC - i;
61 if (!freeslots)
62 goto err_out_too_many;
64 do {
65 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
66 for (j = 0; j < i; j++)
67 if (tmp == fourcc[j])
68 goto err_out_duplicated;
69 fourcc[i] = tmp;
70 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
71 s += 4;
72 i++;
73 } while ((*(s++) == ',') && --freeslots);
75 if (!freeslots)
76 goto err_out_too_many;
77 if (*(--s) != '\0')
78 goto err_out_parse_error;
79 return 1;
80 err_out_duplicated:
81 mp_msg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
82 return 0;
83 err_out_too_many:
84 mp_msg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
85 return 0;
86 err_out_parse_error:
87 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error");
88 return 0;
91 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
93 int i, j;
94 char *endptr;
96 /* find first unused slot */
97 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
98 /* NOTHING */;
99 if (i == CODECS_MAX_FOURCC) {
100 mp_msg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
101 return 0;
104 fourcc[i]=strtoul(s,&endptr,0);
105 if (*endptr != '\0') {
106 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
107 return 0;
110 if(alias){
111 fourccmap[i]=strtoul(alias,&endptr,0);
112 if (*endptr != '\0') {
113 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
114 return 0;
116 } else
117 fourccmap[i]=fourcc[i];
119 for (j = 0; j < i; j++)
120 if (fourcc[j] == fourcc[i]) {
121 mp_msg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
122 return 0;
125 return 1;
128 static struct {
129 const char *name;
130 const unsigned int num;
131 } fmt_table[] = {
132 {"YV12", IMGFMT_YV12},
133 {"I420", IMGFMT_I420},
134 {"IYUV", IMGFMT_IYUV},
135 {"NV12", IMGFMT_NV12},
136 {"NV21", IMGFMT_NV21},
137 {"YVU9", IMGFMT_YVU9},
138 {"IF09", IMGFMT_IF09},
139 {"444P", IMGFMT_444P},
140 {"422P", IMGFMT_422P},
141 {"411P", IMGFMT_411P},
143 {"YUY2", IMGFMT_YUY2},
144 {"UYVY", IMGFMT_UYVY},
145 {"YVYU", IMGFMT_YVYU},
147 {"RGB4", IMGFMT_RGB|4},
148 {"RGB8", IMGFMT_RGB|8},
149 {"RGB15", IMGFMT_RGB|15},
150 {"RGB16", IMGFMT_RGB|16},
151 {"RGB24", IMGFMT_RGB|24},
152 {"RGB32", IMGFMT_RGB|32},
153 {"BGR4", IMGFMT_BGR|4},
154 {"BGR8", IMGFMT_BGR|8},
155 {"BGR15", IMGFMT_BGR|15},
156 {"BGR16", IMGFMT_BGR|16},
157 {"BGR24", IMGFMT_BGR|24},
158 {"BGR32", IMGFMT_BGR|32},
159 {"RGB1", IMGFMT_RGB|1},
160 {"BGR1", IMGFMT_BGR|1},
162 {"MPES", IMGFMT_MPEGPES},
163 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
164 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
165 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
167 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
168 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
170 {NULL, 0}
174 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
175 unsigned char *outflags)
178 static char *flagstr[] = {
179 "flip",
180 "noflip",
181 "yuvhack",
182 "query",
183 "static",
184 NULL
187 int i, j, freeslots;
188 unsigned char flags;
190 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
191 /* NOTHING */;
192 freeslots = CODECS_MAX_OUTFMT - i;
193 if (!freeslots)
194 goto err_out_too_many;
196 flags = 0;
197 if(sflags) {
198 do {
199 for (j = 0; flagstr[j] != NULL; j++)
200 if (!strncmp(sflags, flagstr[j],
201 strlen(flagstr[j])))
202 break;
203 if (flagstr[j] == NULL)
204 goto err_out_parse_error;
205 flags|=(1<<j);
206 sflags+=strlen(flagstr[j]);
207 } while (*(sflags++) == ',');
209 if (*(--sflags) != '\0')
210 goto err_out_parse_error;
213 do {
214 for (j = 0; fmt_table[j].name != NULL; j++)
215 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
216 break;
217 if (fmt_table[j].name == NULL)
218 goto err_out_parse_error;
219 outfmt[i] = fmt_table[j].num;
220 outflags[i] = flags;
221 ++i;
222 sfmt+=strlen(fmt_table[j].name);
223 } while ((*(sfmt++) == ',') && --freeslots);
225 if (!freeslots)
226 goto err_out_too_many;
228 if (*(--sfmt) != '\0')
229 goto err_out_parse_error;
231 return 1;
232 err_out_too_many:
233 mp_msg(MSGT_CODECCFG,MSGL_ERR,"too many out...");
234 return 0;
235 err_out_parse_error:
236 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error");
237 return 0;
240 #if 0
241 static short get_driver(char *s,int audioflag)
243 static char *audiodrv[] = {
244 "null",
245 "mp3lib",
246 "pcm",
247 "libac3",
248 "acm",
249 "alaw",
250 "msgsm",
251 "dshow",
252 "dvdpcm",
253 "hwac3",
254 "libvorbis",
255 "ffmpeg",
256 "libmad",
257 "msadpcm",
258 "liba52",
259 "g72x",
260 "imaadpcm",
261 "dk4adpcm",
262 "dk3adpcm",
263 "roqaudio",
264 "faad",
265 "realaud",
266 "libdv",
267 NULL
269 static char *videodrv[] = {
270 "null",
271 "libmpeg2",
272 "vfw",
273 "odivx",
274 "dshow",
275 "ffmpeg",
276 "vfwex",
277 "divx4",
278 "raw",
279 "msrle",
280 "xanim",
281 "msvidc",
282 "fli",
283 "cinepak",
284 "qtrle",
285 "nuv",
286 "cyuv",
287 "qtsmc",
288 "ducktm1",
289 "roqvideo",
290 "qtrpza",
291 "mpng",
292 "ijpg",
293 "zlib",
294 "mpegpes",
295 "zrmjpeg",
296 "realvid",
297 "xvid",
298 "libdv",
299 NULL
301 char **drv=audioflag?audiodrv:videodrv;
302 int i;
304 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
306 return -1;
308 #endif
310 static int validate_codec(codecs_t *c, int type)
312 unsigned int i;
313 char *tmp_name = c->name;
315 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
316 /* NOTHING */;
318 if (i < strlen(tmp_name)) {
319 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
320 return 0;
323 if (!c->info)
324 c->info = strdup(c->name);
326 #if 0
327 if (c->fourcc[0] == 0xffffffff) {
328 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have FourCC/format!\n", c->name);
329 return 0;
332 /* XXX fix this: shitty with 'null' codec */
333 if (!c->driver) {
334 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
335 return 0;
337 #endif
339 #if 0
340 #warning codec->driver == 4;... <- ezt nem kellene belehegeszteni...
341 #warning HOL VANNAK DEFINIALVA????????????
342 if (!c->dll && (c->driver == 4 ||
343 (c->driver == 2 && type == TYPE_VIDEO))) {
344 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs a 'dll'!\n", c->name);
345 return 0;
347 #warning guid.f1 lehet 0? honnan lehet tudni, hogy nem adtak meg?
348 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
350 if (type == TYPE_VIDEO)
351 if (c->outfmt[0] == 0xffffffff) {
352 mp_msg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs an 'outfmt'!\n", c->name);
353 return 0;
355 #endif
356 return 1;
359 static int add_comment(char *s, char **d)
361 int pos;
363 if (!*d)
364 pos = 0;
365 else {
366 pos = strlen(*d);
367 (*d)[pos++] = '\n';
369 if (!(*d = (char *) realloc(*d, pos + strlen(s) + 1))) {
370 mp_msg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
371 return 0;
373 strcpy(*d + pos, s);
374 return 1;
377 static short get_cpuflags(char *s)
379 static char *flagstr[] = {
380 "mmx",
381 "sse",
382 "3dnow",
383 NULL
385 int i;
386 short flags = 0;
388 do {
389 for (i = 0; flagstr[i]; i++)
390 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
391 break;
392 if (!flagstr[i])
393 goto err_out_parse_error;
394 flags |= 1<<i;
395 s += strlen(flagstr[i]);
396 } while (*(s++) == ',');
398 if (*(--s) != '\0')
399 goto err_out_parse_error;
401 return flags;
402 err_out_parse_error:
403 return 0;
406 static FILE *fp;
407 static int line_num = 0;
408 static char *line;
409 static char *token[MAX_NR_TOKEN];
410 static int read_nextline = 1;
412 static int get_token(int min, int max)
414 static int line_pos;
415 int i;
416 char c;
418 if (max >= MAX_NR_TOKEN) {
419 mp_msg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_NR_TOKEN!");
420 goto out_eof;
423 memset(token, 0x00, sizeof(*token) * max);
425 if (read_nextline) {
426 if (!fgets(line, MAX_LINE_LEN, fp))
427 goto out_eof;
428 line_pos = 0;
429 ++line_num;
430 read_nextline = 0;
432 for (i = 0; i < max; i++) {
433 while (isspace(line[line_pos]))
434 ++line_pos;
435 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
436 line[line_pos] == ';') {
437 read_nextline = 1;
438 if (i >= min)
439 goto out_ok;
440 goto out_eol;
442 token[i] = line + line_pos;
443 c = line[line_pos];
444 if (c == '"' || c == '\'') {
445 token[i]++;
446 while (line[++line_pos] != c && line[line_pos])
447 /* NOTHING */;
448 } else {
449 for (/* NOTHING */; !isspace(line[line_pos]) &&
450 line[line_pos]; line_pos++)
451 /* NOTHING */;
453 if (!line[line_pos]) {
454 read_nextline = 1;
455 if (i >= min - 1)
456 goto out_ok;
457 goto out_eol;
459 line[line_pos] = '\0';
460 line_pos++;
462 out_ok:
463 return i;
464 out_eof:
465 read_nextline = 1;
466 return RET_EOF;
467 out_eol:
468 return RET_EOL;
471 static codecs_t *video_codecs=NULL;
472 static codecs_t *audio_codecs=NULL;
473 static int nr_vcodecs = 0;
474 static int nr_acodecs = 0;
476 int parse_codec_cfg(char *cfgfile)
478 codecs_t *codec = NULL; // current codec
479 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
480 char *endptr; // strtoul()...
481 int *nr_codecsp;
482 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
483 int tmp, i;
485 // in case we call it a second time
486 if(video_codecs!=NULL)free(video_codecs);
487 video_codecs=NULL;
489 if(audio_codecs!=NULL)free(audio_codecs);
490 audio_codecs=NULL;
492 nr_vcodecs = 0;
493 nr_acodecs = 0;
495 if(cfgfile==NULL) {
496 #ifdef CODECS2HTML
497 return 0;
498 #else
499 video_codecs = builtin_video_codecs;
500 audio_codecs = builtin_audio_codecs;
501 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
502 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
503 return 1;
504 #endif
507 mp_msg(MSGT_CODECCFG,MSGL_INFO,"Reading %s: ", cfgfile);
509 if ((fp = fopen(cfgfile, "r")) == NULL) {
510 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't open '%s': %s\n", cfgfile, strerror(errno));
511 return 0;
514 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
515 mp_msg(MSGT_CODECCFG,MSGL_FATAL,"Can't get memory for 'line': %s\n", strerror(errno));
516 return 0;
518 read_nextline = 1;
521 * this only catches release lines at the start of
522 * codecs.conf, before audiocodecs and videocodecs.
524 while ((tmp = get_token(1, 1)) == RET_EOL)
525 /* NOTHING */;
526 if (tmp == RET_EOF)
527 goto out;
528 if (!strcmp(token[0], "release")) {
529 if (get_token(1, 2) < 0)
530 goto err_out_parse_error;
531 tmp = atoi(token[0]);
532 if (tmp < CODEC_CFG_MIN)
533 goto err_out_release_num;
534 while ((tmp = get_token(1, 1)) == RET_EOL)
535 /* NOTHING */;
536 if (tmp == RET_EOF)
537 goto out;
538 } else
539 goto err_out_release_num;
542 * check if the next block starts with 'audiocodec' or
543 * with 'videocodec'
545 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
546 goto loop_enter;
547 goto err_out_parse_error;
549 while ((tmp = get_token(1, 1)) != RET_EOF) {
550 if (tmp == RET_EOL)
551 continue;
552 if (!strcmp(token[0], "audiocodec") ||
553 !strcmp(token[0], "videocodec")) {
554 if (!validate_codec(codec, codec_type))
555 goto err_out_not_valid;
556 loop_enter:
557 if (*token[0] == 'v') {
558 codec_type = TYPE_VIDEO;
559 nr_codecsp = &nr_vcodecs;
560 codecsp = &video_codecs;
561 } else if (*token[0] == 'a') {
562 codec_type = TYPE_AUDIO;
563 nr_codecsp = &nr_acodecs;
564 codecsp = &audio_codecs;
565 #ifdef DEBUG
566 } else {
567 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
568 goto err_out;
569 #endif
571 if (!(*codecsp = (codecs_t *) realloc(*codecsp,
572 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
573 mp_msg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
574 goto err_out;
576 codec=*codecsp + *nr_codecsp;
577 ++*nr_codecsp;
578 memset(codec,0,sizeof(codecs_t));
579 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
580 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
581 memset(codec->infmt, 0xff, sizeof(codec->infmt));
583 if (get_token(1, 1) < 0)
584 goto err_out_parse_error;
585 for (i = 0; i < *nr_codecsp - 1; i++) {
586 if(( (*codecsp)[i].name!=NULL) &&
587 (!strcmp(token[0], (*codecsp)[i].name)) ) {
588 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
589 goto err_out_print_linenum;
592 if (!(codec->name = strdup(token[0]))) {
593 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
594 goto err_out;
596 } else if (!strcmp(token[0], "info")) {
597 if (codec->info || get_token(1, 1) < 0)
598 goto err_out_parse_error;
599 if (!(codec->info = strdup(token[0]))) {
600 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
601 goto err_out;
603 } else if (!strcmp(token[0], "comment")) {
604 if (get_token(1, 1) < 0)
605 goto err_out_parse_error;
606 add_comment(token[0], &codec->comment);
607 } else if (!strcmp(token[0], "fourcc")) {
608 if (get_token(1, 2) < 0)
609 goto err_out_parse_error;
610 if (!add_to_fourcc(token[0], token[1],
611 codec->fourcc,
612 codec->fourccmap))
613 goto err_out_print_linenum;
614 } else if (!strcmp(token[0], "format")) {
615 if (get_token(1, 2) < 0)
616 goto err_out_parse_error;
617 if (!add_to_format(token[0], token[1],
618 codec->fourcc,codec->fourccmap))
619 goto err_out_print_linenum;
620 } else if (!strcmp(token[0], "driver")) {
621 if (get_token(1, 1) < 0)
622 goto err_out_parse_error;
623 if (!(codec->drv = strdup(token[0]))) {
624 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
625 goto err_out;
627 } else if (!strcmp(token[0], "dll")) {
628 if (get_token(1, 1) < 0)
629 goto err_out_parse_error;
630 if (!(codec->dll = strdup(token[0]))) {
631 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s\n", strerror(errno));
632 goto err_out;
634 } else if (!strcmp(token[0], "guid")) {
635 if (get_token(11, 11) < 0)
636 goto err_out_parse_error;
637 codec->guid.f1=strtoul(token[0],&endptr,0);
638 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
639 *endptr != '\0')
640 goto err_out_parse_error;
641 codec->guid.f2=strtoul(token[1],&endptr,0);
642 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
643 *endptr != '\0')
644 goto err_out_parse_error;
645 codec->guid.f3=strtoul(token[2],&endptr,0);
646 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
647 *endptr != '\0')
648 goto err_out_parse_error;
649 for (i = 0; i < 8; i++) {
650 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
651 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
652 *endptr != '\0')
653 goto err_out_parse_error;
655 } else if (!strcmp(token[0], "out")) {
656 if (get_token(1, 2) < 0)
657 goto err_out_parse_error;
658 if (!add_to_inout(token[0], token[1], codec->outfmt,
659 codec->outflags))
660 goto err_out_print_linenum;
661 } else if (!strcmp(token[0], "in")) {
662 if (get_token(1, 2) < 0)
663 goto err_out_parse_error;
664 if (!add_to_inout(token[0], token[1], codec->infmt,
665 codec->inflags))
666 goto err_out_print_linenum;
667 } else if (!strcmp(token[0], "flags")) {
668 if (get_token(1, 1) < 0)
669 goto err_out_parse_error;
670 if (!strcmp(token[0], "seekable"))
671 codec->flags |= CODECS_FLAG_SEEKABLE;
672 else
673 if (!strcmp(token[0], "align16"))
674 codec->flags |= CODECS_FLAG_ALIGN16;
675 else
676 goto err_out_parse_error;
677 } else if (!strcmp(token[0], "status")) {
678 if (get_token(1, 1) < 0)
679 goto err_out_parse_error;
680 if (!strcasecmp(token[0], "working"))
681 codec->status = CODECS_STATUS_WORKING;
682 else if (!strcasecmp(token[0], "crashing"))
683 codec->status = CODECS_STATUS_NOT_WORKING;
684 else if (!strcasecmp(token[0], "untested"))
685 codec->status = CODECS_STATUS_UNTESTED;
686 else if (!strcasecmp(token[0], "buggy"))
687 codec->status = CODECS_STATUS_PROBLEMS;
688 else
689 goto err_out_parse_error;
690 } else if (!strcmp(token[0], "cpuflags")) {
691 if (get_token(1, 1) < 0)
692 goto err_out_parse_error;
693 if (!(codec->cpuflags = get_cpuflags(token[0])))
694 goto err_out_parse_error;
695 } else
696 goto err_out_parse_error;
698 if (!validate_codec(codec, codec_type))
699 goto err_out_not_valid;
700 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%d audio & %d video codecs\n", nr_acodecs, nr_vcodecs);
701 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
702 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
703 out:
704 free(line);
705 line=NULL;
706 fclose(fp);
707 return 1;
709 err_out_parse_error:
710 mp_msg(MSGT_CODECCFG,MSGL_ERR,"parse error");
711 err_out_print_linenum:
712 PRINT_LINENUM;
713 err_out:
714 if (audio_codecs)
715 free(audio_codecs);
716 if (video_codecs)
717 free(video_codecs);
718 video_codecs=NULL;
719 audio_codecs=NULL;
721 free(line);
722 line=NULL;
723 line_num = 0;
724 fclose(fp);
725 return 0;
726 err_out_not_valid:
727 mp_msg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
728 goto err_out_print_linenum;
729 err_out_release_num:
730 mp_msg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
731 goto err_out_print_linenum;
734 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
735 codecs_t *start)
737 return find_codec(fourcc, fourccmap, start, 1);
740 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
741 codecs_t *start)
743 return find_codec(fourcc, fourccmap, start, 0);
746 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
747 codecs_t *start, int audioflag)
749 int i, j;
750 codecs_t *c;
752 #if 0
753 if (start) {
754 for (/* NOTHING */; start->name; start++) {
755 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
756 if (start->fourcc[j] == fourcc) {
757 if (fourccmap)
758 *fourccmap = start->fourccmap[j];
759 return start;
763 } else
764 #endif
766 if (audioflag) {
767 i = nr_acodecs;
768 c = audio_codecs;
769 } else {
770 i = nr_vcodecs;
771 c = video_codecs;
773 if(!i) return NULL;
774 for (/* NOTHING */; i--; c++) {
775 if(start && c<=start) continue;
776 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
777 // FIXME: do NOT hardwire 'null' name here:
778 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
779 if (fourccmap)
780 *fourccmap = c->fourccmap[j];
781 return c;
786 return NULL;
789 void select_codec(char* codecname,int audioflag){
790 int i;
791 codecs_t *c;
792 // printf("select_codec('%s')\n",codecname);
793 if (audioflag) {
794 i = nr_acodecs;
795 c = audio_codecs;
796 } else {
797 i = nr_vcodecs;
798 c = video_codecs;
800 if(i)
801 for (/* NOTHING */; i--; c++)
802 if(!strcmp(c->name,codecname))
803 c->flags|=CODECS_FLAG_SELECTED;
806 void codecs_reset_selection(int audioflag){
807 int i;
808 codecs_t *c;
809 if (audioflag) {
810 i = nr_acodecs;
811 c = audio_codecs;
812 } else {
813 i = nr_vcodecs;
814 c = video_codecs;
816 if(i)
817 for (/* NOTHING */; i--; c++)
818 c->flags&=(~CODECS_FLAG_SELECTED);
821 void list_codecs(int audioflag){
822 int i;
823 codecs_t *c;
825 if (audioflag) {
826 i = nr_acodecs;
827 c = audio_codecs;
828 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
829 } else {
830 i = nr_vcodecs;
831 c = video_codecs;
832 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
834 if(!i) return;
835 for (/* NOTHING */; i--; c++) {
836 char* s="unknown ";
837 switch(c->status){
838 case CODECS_STATUS_WORKING: s="working ";break;
839 case CODECS_STATUS_PROBLEMS: s="problems";break;
840 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
841 case CODECS_STATUS_UNTESTED: s="untested";break;
843 if(c->dll)
844 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
845 else
846 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
854 #ifdef CODECS2HTML
856 * Fake out GUI references when building the codecs2html utility.
858 #ifdef HAVE_NEW_GUI
859 void gtkMessageBox( int type,char * str ) { return; }
860 int use_gui = 0;
861 #endif
863 void wrapline(FILE *f2,char *s){
864 int c;
865 if(!s){
866 fprintf(f2,"-");
867 return;
869 while((c=*s++)){
870 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
874 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
875 int c,d;
876 while((c=fgetc(f1))>=0){
877 if(c!='%'){
878 fputc(c,f2);
879 continue;
881 d=fgetc(f1);
883 switch(d){
884 case '.':
885 return; // end of section
886 case 'n':
887 wrapline(f2,codec->name); break;
888 case 'i':
889 wrapline(f2,codec->info); break;
890 case 'c':
891 wrapline(f2,codec->comment); break;
892 case 'd':
893 wrapline(f2,codec->dll); break;
894 case 'D':
895 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
896 case 'F':
897 for(d=0;d<CODECS_MAX_FOURCC;d++)
898 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
899 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
900 break;
901 case 'f':
902 for(d=0;d<CODECS_MAX_FOURCC;d++)
903 if(codec->fourcc[d]!=0xFFFFFFFF)
904 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
905 break;
906 case 'Y':
907 for(d=0;d<CODECS_MAX_OUTFMT;d++)
908 if(codec->outfmt[d]!=0xFFFFFFFF){
909 for (c=0; fmt_table[c].name; c++)
910 if(fmt_table[c].num==codec->outfmt[d]) break;
911 if(fmt_table[c].name)
912 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
914 break;
915 default:
916 fputc(c,f2);
917 fputc(d,f2);
923 void skiphtml(FILE *f1){
924 int c,d;
925 while((c=fgetc(f1))>=0){
926 if(c!='%'){
927 continue;
929 d=fgetc(f1);
930 if(d=='.') return; // end of section
934 static void print_int_array(const int* a, int size)
936 printf("{ ");
937 while (size--)
938 if(abs(*a)<256)
939 printf("%d%s", *a++, size?", ":"");
940 else
941 printf("0x%X%s", *a++, size?", ":"");
942 printf(" }");
945 static void print_char_array(const unsigned char* a, int size)
947 printf("{ ");
948 while (size--)
949 if((*a)<10)
950 printf("%d%s", *a++, size?", ":"");
951 else
952 printf("0x%02x%s", *a++, size?", ":"");
953 printf(" }");
956 static void print_string(const char* s)
958 if (!s) printf("NULL");
959 else printf("\"%s\"", s);
962 int main(int argc, char* argv[])
964 codecs_t *cl;
965 FILE *f1;
966 FILE *f2;
967 int c,d,i;
968 int pos;
969 int section=-1;
970 int nr_codecs;
971 int win32=-1;
972 int dshow=-1;
973 int win32ex=-1;
976 * Take path to codecs.conf from command line, or fall back on
977 * etc/codecs.conf
979 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
980 exit(1);
982 if (argc > 1) {
983 int i, j;
984 const char* nm[2];
985 codecs_t* cod[2];
986 int nr[2];
988 nm[0] = "builtin_video_codecs";
989 cod[0] = video_codecs;
990 nr[0] = nr_vcodecs;
992 nm[1] = "builtin_audio_codecs";
993 cod[1] = audio_codecs;
994 nr[1] = nr_acodecs;
996 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
998 for (i=0; i<2; i++) {
999 printf("codecs_t %s[] = {\n", nm[i]);
1000 for (j = 0; j < nr[i]; j++) {
1001 printf("{");
1003 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1004 printf(", /* fourcc */\n");
1006 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1007 printf(", /* fourccmap */\n");
1009 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1010 printf(", /* outfmt */\n");
1012 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1013 printf(", /* outflags */\n");
1015 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1016 printf(", /* infmt */\n");
1018 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1019 printf(", /* inflags */\n");
1021 print_string(cod[i][j].name); printf(", /* name */\n");
1022 print_string(cod[i][j].info); printf(", /* info */\n");
1023 print_string(cod[i][j].comment); printf(", /* comment */\n");
1024 print_string(cod[i][j].dll); printf(", /* dll */\n");
1025 print_string(cod[i][j].drv); printf(", /* drv */\n");
1027 printf("{ 0x%08lx, %hu, %hu,",
1028 cod[i][j].guid.f1,
1029 cod[i][j].guid.f2,
1030 cod[i][j].guid.f3);
1031 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1032 printf(" }, /* GUID */\n");
1033 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1034 cod[i][j].flags,
1035 cod[i][j].status,
1036 cod[i][j].cpuflags);
1037 if (j < nr[i]) printf(",\n");
1039 printf("};\n\n");
1041 exit(0);
1044 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1045 f2=fopen("DOCS/en/codecs-status.html","wb"); if(!f2) exit(1);
1047 while((c=fgetc(f1))>=0){
1048 if(c!='%'){
1049 fputc(c,f2);
1050 continue;
1052 d=fgetc(f1);
1053 if(d>='0' && d<='9'){
1054 // begin section
1055 section=d-'0';
1056 printf("BEGIN %d\n",section);
1057 if(section>=5){
1058 // audio
1059 cl = audio_codecs;
1060 nr_codecs = nr_acodecs;
1061 dshow=7;win32=4;
1062 } else {
1063 // video
1064 cl = video_codecs;
1065 nr_codecs = nr_vcodecs;
1066 dshow=4;win32=2;win32ex=6;
1068 pos=ftell(f1);
1069 for(i=0;i<nr_codecs;i++){
1070 fseek(f1,pos,SEEK_SET);
1071 switch(section){
1072 case 0:
1073 case 5:
1074 if(cl[i].status==CODECS_STATUS_WORKING)
1075 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1076 parsehtml(f1,f2,&cl[i],section,dshow);
1077 break;
1078 #if 0
1079 case 1:
1080 case 6:
1081 if(cl[i].status==CODECS_STATUS_WORKING)
1082 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1083 parsehtml(f1,f2,&cl[i],section,dshow);
1084 break;
1085 #endif
1086 case 2:
1087 case 7:
1088 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1089 parsehtml(f1,f2,&cl[i],section,dshow);
1090 break;
1091 case 3:
1092 case 8:
1093 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1094 parsehtml(f1,f2,&cl[i],section,dshow);
1095 break;
1096 case 4:
1097 case 9:
1098 if(cl[i].status==CODECS_STATUS_UNTESTED)
1099 parsehtml(f1,f2,&cl[i],section,dshow);
1100 break;
1101 default:
1102 printf("Warning! unimplemented section: %d\n",section);
1105 fseek(f1,pos,SEEK_SET);
1106 skiphtml(f1);
1107 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1109 continue;
1111 fputc(c,f2);
1112 fputc(d,f2);
1115 fclose(f2);
1116 fclose(f1);
1117 return 0;
1120 #endif
1122 #ifdef TESTING
1123 int main(void)
1125 codecs_t *c;
1126 int i,j, nr_codecs, state;
1128 if (!(parse_codec_cfg("etc/codecs.conf")))
1129 return 0;
1130 if (!video_codecs)
1131 printf("no videoconfig.\n");
1132 if (!audio_codecs)
1133 printf("no audioconfig.\n");
1135 printf("videocodecs:\n");
1136 c = video_codecs;
1137 nr_codecs = nr_vcodecs;
1138 state = 0;
1139 next:
1140 if (c) {
1141 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1142 nr_codecs);
1143 for(i=0;i<nr_codecs;i++, c++){
1144 printf("\n============== %scodec %02d ===============\n",
1145 state==0?"video":"audio",i);
1146 printf("name='%s'\n",c->name);
1147 printf("info='%s'\n",c->info);
1148 printf("comment='%s'\n",c->comment);
1149 printf("dll='%s'\n",c->dll);
1150 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1151 c->flags, c->driver, c->status, c->cpuflags);
1153 for(j=0;j<CODECS_MAX_FOURCC;j++){
1154 if(c->fourcc[j]!=0xFFFFFFFF){
1155 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1159 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1160 if(c->outfmt[j]!=0xFFFFFFFF){
1161 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1165 for(j=0;j<CODECS_MAX_INFMT;j++){
1166 if(c->infmt[j]!=0xFFFFFFFF){
1167 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1171 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1172 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1173 printf("\n");
1178 if (!state) {
1179 printf("audiocodecs:\n");
1180 c = audio_codecs;
1181 nr_codecs = nr_acodecs;
1182 state = 1;
1183 goto next;
1185 return 0;
1188 #endif