sync with en/mplayer.1 r30075
[mplayer/glamo.git] / codec-cfg.c
blobb36ecfc50f38607162f0941436fe077ce473a668
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 const struct {
142 const char *name;
143 const unsigned int num;
144 } fmt_table[] = {
145 // note: due to parser deficiencies/simplicity, if one format
146 // name matches the beginning of another, the longer one _must_
147 // come first in this list.
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 {"RGB48LE", IMGFMT_RGB48LE},
166 {"RGB48BE", IMGFMT_RGB48BE},
167 {"RGB4", IMGFMT_RGB4},
168 {"RGB8", IMGFMT_RGB8},
169 {"RGB15", IMGFMT_RGB15},
170 {"RGB16", IMGFMT_RGB16},
171 {"RGB24", IMGFMT_RGB24},
172 {"RGB32", IMGFMT_RGB32},
173 {"BGR4", IMGFMT_BGR4},
174 {"BGR8", IMGFMT_BGR8},
175 {"BGR15", IMGFMT_BGR15},
176 {"BGR16", IMGFMT_BGR16},
177 {"BGR24", IMGFMT_BGR24},
178 {"BGR32", IMGFMT_BGR32},
179 {"RGB1", IMGFMT_RGB1},
180 {"BGR1", IMGFMT_BGR1},
182 {"MPES", IMGFMT_MPEGPES},
183 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
184 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
185 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
187 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
188 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
190 {"VDPAU_MPEG1",IMGFMT_VDPAU_MPEG1},
191 {"VDPAU_MPEG2",IMGFMT_VDPAU_MPEG2},
192 {"VDPAU_H264",IMGFMT_VDPAU_H264},
193 {"VDPAU_WMV3",IMGFMT_VDPAU_WMV3},
194 {"VDPAU_VC1",IMGFMT_VDPAU_VC1},
195 {"VDPAU_MPEG4",IMGFMT_VDPAU_MPEG4},
197 {NULL, 0}
201 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
202 unsigned char *outflags)
205 static char *flagstr[] = {
206 "flip",
207 "noflip",
208 "yuvhack",
209 "query",
210 "static",
211 NULL
214 int i, j, freeslots;
215 unsigned char flags;
217 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
218 /* NOTHING */;
219 freeslots = CODECS_MAX_OUTFMT - i;
220 if (!freeslots)
221 goto err_out_too_many;
223 flags = 0;
224 if(sflags) {
225 do {
226 for (j = 0; flagstr[j] != NULL; j++)
227 if (!strncmp(sflags, flagstr[j],
228 strlen(flagstr[j])))
229 break;
230 if (flagstr[j] == NULL)
231 goto err_out_parse_error;
232 flags|=(1<<j);
233 sflags+=strlen(flagstr[j]);
234 } while (*(sflags++) == ',');
236 if (*(--sflags) != '\0')
237 goto err_out_parse_error;
240 do {
241 for (j = 0; fmt_table[j].name != NULL; j++)
242 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
243 break;
244 if (fmt_table[j].name == NULL)
245 goto err_out_parse_error;
246 outfmt[i] = fmt_table[j].num;
247 outflags[i] = flags;
248 ++i;
249 sfmt+=strlen(fmt_table[j].name);
250 } while ((*(sfmt++) == ',') && --freeslots);
252 if (!freeslots)
253 goto err_out_too_many;
255 if (*(--sfmt) != '\0')
256 goto err_out_parse_error;
258 return 1;
259 err_out_too_many:
260 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyOut);
261 return 0;
262 err_out_parse_error:
263 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
264 return 0;
267 #if 0
268 static short get_driver(char *s,int audioflag)
270 static char *audiodrv[] = {
271 "null",
272 "mp3lib",
273 "pcm",
274 "libac3",
275 "acm",
276 "alaw",
277 "msgsm",
278 "dshow",
279 "dvdpcm",
280 "hwac3",
281 "libvorbis",
282 "ffmpeg",
283 "libmad",
284 "msadpcm",
285 "liba52",
286 "g72x",
287 "imaadpcm",
288 "dk4adpcm",
289 "dk3adpcm",
290 "roqaudio",
291 "faad",
292 "realaud",
293 "libdv",
294 NULL
296 static char *videodrv[] = {
297 "null",
298 "libmpeg2",
299 "vfw",
300 "dshow",
301 "ffmpeg",
302 "vfwex",
303 "raw",
304 "msrle",
305 "xanim",
306 "msvidc",
307 "fli",
308 "cinepak",
309 "qtrle",
310 "nuv",
311 "cyuv",
312 "qtsmc",
313 "ducktm1",
314 "roqvideo",
315 "qtrpza",
316 "mpng",
317 "ijpg",
318 "zlib",
319 "mpegpes",
320 "zrmjpeg",
321 "realvid",
322 "xvid",
323 "libdv",
324 NULL
326 char **drv=audioflag?audiodrv:videodrv;
327 int i;
329 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
331 return -1;
333 #endif
335 static int validate_codec(codecs_t *c, int type)
337 unsigned int i;
338 char *tmp_name = c->name;
340 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
341 /* NOTHING */;
343 if (i < strlen(tmp_name)) {
344 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_InvalidCodecName, c->name);
345 return 0;
348 if (!c->info)
349 c->info = strdup(c->name);
351 #if 0
352 if (c->fourcc[0] == 0xffffffff) {
353 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksFourcc, c->name);
354 return 0;
356 #endif
358 if (!c->drv) {
359 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksDriver, c->name);
360 return 0;
363 #if 0
364 #warning codec->driver == 4;... <- this should not be put in here...
365 #warning Where are they defined ????????????
366 if (!c->dll && (c->driver == 4 ||
367 (c->driver == 2 && type == TYPE_VIDEO))) {
368 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsDLL, c->name);
369 return 0;
371 #warning Can guid.f1 be 0? How does one know that it was not given?
372 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
374 if (type == TYPE_VIDEO)
375 if (c->outfmt[0] == 0xffffffff) {
376 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsOutfmt, c->name);
377 return 0;
379 #endif
380 return 1;
383 static int add_comment(char *s, char **d)
385 int pos;
387 if (!*d)
388 pos = 0;
389 else {
390 pos = strlen(*d);
391 (*d)[pos++] = '\n';
393 if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
394 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantAllocateComment);
395 return 0;
397 strcpy(*d + pos, s);
398 return 1;
401 static short get_cpuflags(char *s)
403 static char *flagstr[] = {
404 "mmx",
405 "sse",
406 "3dnow",
407 NULL
409 int i;
410 short flags = 0;
412 do {
413 for (i = 0; flagstr[i]; i++)
414 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
415 break;
416 if (!flagstr[i])
417 goto err_out_parse_error;
418 flags |= 1<<i;
419 s += strlen(flagstr[i]);
420 } while (*(s++) == ',');
422 if (*(--s) != '\0')
423 goto err_out_parse_error;
425 return flags;
426 err_out_parse_error:
427 return 0;
430 static FILE *fp;
431 static int line_num = 0;
432 static char *line;
433 static char *token[MAX_NR_TOKEN];
434 static int read_nextline = 1;
436 static int get_token(int min, int max)
438 static int line_pos;
439 int i;
440 char c;
442 if (max >= MAX_NR_TOKEN) {
443 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN);
444 goto out_eof;
447 memset(token, 0x00, sizeof(*token) * max);
449 if (read_nextline) {
450 if (!fgets(line, MAX_LINE_LEN, fp))
451 goto out_eof;
452 line_pos = 0;
453 ++line_num;
454 read_nextline = 0;
456 for (i = 0; i < max; i++) {
457 while (isspace(line[line_pos]))
458 ++line_pos;
459 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
460 line[line_pos] == ';') {
461 read_nextline = 1;
462 if (i >= min)
463 goto out_ok;
464 goto out_eol;
466 token[i] = line + line_pos;
467 c = line[line_pos];
468 if (c == '"' || c == '\'') {
469 token[i]++;
470 while (line[++line_pos] != c && line[line_pos])
471 /* NOTHING */;
472 } else {
473 for (/* NOTHING */; !isspace(line[line_pos]) &&
474 line[line_pos]; line_pos++)
475 /* NOTHING */;
477 if (!line[line_pos]) {
478 read_nextline = 1;
479 if (i >= min - 1)
480 goto out_ok;
481 goto out_eol;
483 line[line_pos] = '\0';
484 line_pos++;
486 out_ok:
487 return i;
488 out_eof:
489 read_nextline = 1;
490 return RET_EOF;
491 out_eol:
492 return RET_EOL;
495 static codecs_t *video_codecs=NULL;
496 static codecs_t *audio_codecs=NULL;
497 static int nr_vcodecs = 0;
498 static int nr_acodecs = 0;
500 int parse_codec_cfg(const char *cfgfile)
502 codecs_t *codec = NULL; // current codec
503 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
504 char *endptr; // strtoul()...
505 int *nr_codecsp;
506 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
507 int tmp, i;
509 // in case we call it a second time
510 codecs_uninit_free();
512 nr_vcodecs = 0;
513 nr_acodecs = 0;
515 if(cfgfile==NULL) {
516 #ifdef CODECS2HTML
517 return 0;
518 #else
519 video_codecs = builtin_video_codecs;
520 audio_codecs = builtin_audio_codecs;
521 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
522 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
523 return 1;
524 #endif
527 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_ReadingFile, cfgfile);
529 if ((fp = fopen(cfgfile, "r")) == NULL) {
530 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_CantOpenFileError, cfgfile, strerror(errno));
531 return 0;
534 if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) {
535 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantGetMemoryForLine, strerror(errno));
536 return 0;
538 read_nextline = 1;
541 * this only catches release lines at the start of
542 * codecs.conf, before audiocodecs and videocodecs.
544 while ((tmp = get_token(1, 1)) == RET_EOL)
545 /* NOTHING */;
546 if (tmp == RET_EOF)
547 goto out;
548 if (!strcmp(token[0], "release")) {
549 if (get_token(1, 2) < 0)
550 goto err_out_parse_error;
551 tmp = atoi(token[0]);
552 if (tmp < CODEC_CFG_MIN)
553 goto err_out_release_num;
554 while ((tmp = get_token(1, 1)) == RET_EOL)
555 /* NOTHING */;
556 if (tmp == RET_EOF)
557 goto out;
558 } else
559 goto err_out_release_num;
562 * check if the next block starts with 'audiocodec' or
563 * with 'videocodec'
565 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
566 goto loop_enter;
567 goto err_out_parse_error;
569 while ((tmp = get_token(1, 1)) != RET_EOF) {
570 if (tmp == RET_EOL)
571 continue;
572 if (!strcmp(token[0], "audiocodec") ||
573 !strcmp(token[0], "videocodec")) {
574 if (!validate_codec(codec, codec_type))
575 goto err_out_not_valid;
576 loop_enter:
577 if (*token[0] == 'v') {
578 codec_type = TYPE_VIDEO;
579 nr_codecsp = &nr_vcodecs;
580 codecsp = &video_codecs;
581 } else if (*token[0] == 'a') {
582 codec_type = TYPE_AUDIO;
583 nr_codecsp = &nr_acodecs;
584 codecsp = &audio_codecs;
585 #ifdef DEBUG
586 } else {
587 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
588 goto err_out;
589 #endif
591 if (!(*codecsp = realloc(*codecsp,
592 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
593 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantReallocCodecsp, strerror(errno));
594 goto err_out;
596 codec=*codecsp + *nr_codecsp;
597 ++*nr_codecsp;
598 memset(codec,0,sizeof(codecs_t));
599 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
600 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
601 memset(codec->infmt, 0xff, sizeof(codec->infmt));
603 if (get_token(1, 1) < 0)
604 goto err_out_parse_error;
605 for (i = 0; i < *nr_codecsp - 1; i++) {
606 if(( (*codecsp)[i].name!=NULL) &&
607 (!strcmp(token[0], (*codecsp)[i].name)) ) {
608 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNameNotUnique, token[0]);
609 goto err_out_print_linenum;
612 if (!(codec->name = strdup(token[0]))) {
613 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupName, strerror(errno));
614 goto err_out;
616 } else if (!strcmp(token[0], "info")) {
617 if (codec->info || get_token(1, 1) < 0)
618 goto err_out_parse_error;
619 if (!(codec->info = strdup(token[0]))) {
620 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupInfo, strerror(errno));
621 goto err_out;
623 } else if (!strcmp(token[0], "comment")) {
624 if (get_token(1, 1) < 0)
625 goto err_out_parse_error;
626 add_comment(token[0], &codec->comment);
627 } else if (!strcmp(token[0], "fourcc")) {
628 if (get_token(1, 2) < 0)
629 goto err_out_parse_error;
630 if (!add_to_fourcc(token[0], token[1],
631 codec->fourcc,
632 codec->fourccmap))
633 goto err_out_print_linenum;
634 } else if (!strcmp(token[0], "format")) {
635 if (get_token(1, 2) < 0)
636 goto err_out_parse_error;
637 if (!add_to_format(token[0], token[1],
638 codec->fourcc,codec->fourccmap))
639 goto err_out_print_linenum;
640 } else if (!strcmp(token[0], "driver")) {
641 if (get_token(1, 1) < 0)
642 goto err_out_parse_error;
643 if (!(codec->drv = strdup(token[0]))) {
644 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDriver, strerror(errno));
645 goto err_out;
647 } else if (!strcmp(token[0], "dll")) {
648 if (get_token(1, 1) < 0)
649 goto err_out_parse_error;
650 if (!(codec->dll = strdup(token[0]))) {
651 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDLL, strerror(errno));
652 goto err_out;
654 } else if (!strcmp(token[0], "guid")) {
655 if (get_token(11, 11) < 0)
656 goto err_out_parse_error;
657 codec->guid.f1=strtoul(token[0],&endptr,0);
658 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
659 *endptr != '\0')
660 goto err_out_parse_error;
661 codec->guid.f2=strtoul(token[1],&endptr,0);
662 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
663 *endptr != '\0')
664 goto err_out_parse_error;
665 codec->guid.f3=strtoul(token[2],&endptr,0);
666 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
667 *endptr != '\0')
668 goto err_out_parse_error;
669 for (i = 0; i < 8; i++) {
670 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
671 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
672 *endptr != '\0')
673 goto err_out_parse_error;
675 } else if (!strcmp(token[0], "out")) {
676 if (get_token(1, 2) < 0)
677 goto err_out_parse_error;
678 if (!add_to_inout(token[0], token[1], codec->outfmt,
679 codec->outflags))
680 goto err_out_print_linenum;
681 } else if (!strcmp(token[0], "in")) {
682 if (get_token(1, 2) < 0)
683 goto err_out_parse_error;
684 if (!add_to_inout(token[0], token[1], codec->infmt,
685 codec->inflags))
686 goto err_out_print_linenum;
687 } else if (!strcmp(token[0], "flags")) {
688 if (get_token(1, 1) < 0)
689 goto err_out_parse_error;
690 if (!strcmp(token[0], "seekable"))
691 codec->flags |= CODECS_FLAG_SEEKABLE;
692 else
693 if (!strcmp(token[0], "align16"))
694 codec->flags |= CODECS_FLAG_ALIGN16;
695 else
696 goto err_out_parse_error;
697 } else if (!strcmp(token[0], "status")) {
698 if (get_token(1, 1) < 0)
699 goto err_out_parse_error;
700 if (!strcasecmp(token[0], "working"))
701 codec->status = CODECS_STATUS_WORKING;
702 else if (!strcasecmp(token[0], "crashing"))
703 codec->status = CODECS_STATUS_NOT_WORKING;
704 else if (!strcasecmp(token[0], "untested"))
705 codec->status = CODECS_STATUS_UNTESTED;
706 else if (!strcasecmp(token[0], "buggy"))
707 codec->status = CODECS_STATUS_PROBLEMS;
708 else
709 goto err_out_parse_error;
710 } else if (!strcmp(token[0], "cpuflags")) {
711 if (get_token(1, 1) < 0)
712 goto err_out_parse_error;
713 if (!(codec->cpuflags = get_cpuflags(token[0])))
714 goto err_out_parse_error;
715 } else
716 goto err_out_parse_error;
718 if (!validate_codec(codec, codec_type))
719 goto err_out_not_valid;
720 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_AudioVideoCodecTotals, nr_acodecs, nr_vcodecs);
721 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
722 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
723 out:
724 free(line);
725 line=NULL;
726 fclose(fp);
727 return 1;
729 err_out_parse_error:
730 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
731 err_out_print_linenum:
732 PRINT_LINENUM;
733 err_out:
734 codecs_uninit_free();
736 free(line);
737 line=NULL;
738 line_num = 0;
739 fclose(fp);
740 return 0;
741 err_out_not_valid:
742 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecDefinitionIncorrect);
743 goto err_out_print_linenum;
744 err_out_release_num:
745 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_OutdatedCodecsConf);
746 goto err_out_print_linenum;
749 static void codecs_free(codecs_t* codecs,int count) {
750 int i;
751 for ( i = 0; i < count; i++)
752 if ( codecs[i].name ) {
753 if( codecs[i].name )
754 free(codecs[i].name);
755 if( codecs[i].info )
756 free(codecs[i].info);
757 if( codecs[i].comment )
758 free(codecs[i].comment);
759 if( codecs[i].dll )
760 free(codecs[i].dll);
761 if( codecs[i].drv )
762 free(codecs[i].drv);
764 if (codecs)
765 free(codecs);
768 void codecs_uninit_free(void) {
769 if (video_codecs)
770 codecs_free(video_codecs,nr_vcodecs);
771 video_codecs=NULL;
772 if (audio_codecs)
773 codecs_free(audio_codecs,nr_acodecs);
774 audio_codecs=NULL;
777 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
778 codecs_t *start, int force)
780 return find_codec(fourcc, fourccmap, start, 1, force);
783 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
784 codecs_t *start, int force)
786 return find_codec(fourcc, fourccmap, start, 0, force);
789 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
790 codecs_t *start, int audioflag, int force)
792 int i, j;
793 codecs_t *c;
795 #if 0
796 if (start) {
797 for (/* NOTHING */; start->name; start++) {
798 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
799 if (start->fourcc[j] == fourcc) {
800 if (fourccmap)
801 *fourccmap = start->fourccmap[j];
802 return start;
806 } else
807 #endif
809 if (audioflag) {
810 i = nr_acodecs;
811 c = audio_codecs;
812 } else {
813 i = nr_vcodecs;
814 c = video_codecs;
816 if(!i) return NULL;
817 for (/* NOTHING */; i--; c++) {
818 if(start && c<=start) continue;
819 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
820 // FIXME: do NOT hardwire 'null' name here:
821 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
822 if (fourccmap)
823 *fourccmap = c->fourccmap[j];
824 return c;
827 if (force) return c;
830 return NULL;
833 void stringset_init(stringset_t *set) {
834 *set = calloc(1, sizeof(char *));
837 void stringset_free(stringset_t *set) {
838 int count = 0;
839 while ((*set)[count]) free((*set)[count++]);
840 free(*set);
841 *set = NULL;
844 void stringset_add(stringset_t *set, const char *str) {
845 int count = 0;
846 while ((*set)[count]) count++;
847 count++;
848 *set = realloc(*set, sizeof(char *) * (count + 1));
849 (*set)[count - 1] = strdup(str);
850 (*set)[count] = NULL;
853 int stringset_test(stringset_t *set, const char *str) {
854 stringset_t s;
855 for (s = *set; *s; s++)
856 if (strcmp(*s, str) == 0)
857 return 1;
858 return 0;
861 void list_codecs(int audioflag){
862 int i;
863 codecs_t *c;
865 if (audioflag) {
866 i = nr_acodecs;
867 c = audio_codecs;
868 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
869 } else {
870 i = nr_vcodecs;
871 c = video_codecs;
872 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
874 if(!i) return;
875 for (/* NOTHING */; i--; c++) {
876 char* s="unknown ";
877 switch(c->status){
878 case CODECS_STATUS_WORKING: s="working ";break;
879 case CODECS_STATUS_PROBLEMS: s="problems";break;
880 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
881 case CODECS_STATUS_UNTESTED: s="untested";break;
883 if(c->dll)
884 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
885 else
886 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
894 #ifdef CODECS2HTML
895 void wrapline(FILE *f2,char *s){
896 int c;
897 if(!s){
898 fprintf(f2,"-");
899 return;
901 while((c=*s++)){
902 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
906 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
907 int c,d;
908 while((c=fgetc(f1))>=0){
909 if(c!='%'){
910 fputc(c,f2);
911 continue;
913 d=fgetc(f1);
915 switch(d){
916 case '.':
917 return; // end of section
918 case 'n':
919 wrapline(f2,codec->name); break;
920 case 'i':
921 wrapline(f2,codec->info); break;
922 case 'c':
923 wrapline(f2,codec->comment); break;
924 case 'd':
925 wrapline(f2,codec->dll); break;
926 case 'D':
927 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
928 case 'F':
929 for(d=0;d<CODECS_MAX_FOURCC;d++)
930 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
931 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
932 break;
933 case 'f':
934 for(d=0;d<CODECS_MAX_FOURCC;d++)
935 if(codec->fourcc[d]!=0xFFFFFFFF)
936 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
937 break;
938 case 'Y':
939 for(d=0;d<CODECS_MAX_OUTFMT;d++)
940 if(codec->outfmt[d]!=0xFFFFFFFF){
941 for (c=0; fmt_table[c].name; c++)
942 if(fmt_table[c].num==codec->outfmt[d]) break;
943 if(fmt_table[c].name)
944 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
946 break;
947 default:
948 fputc(c,f2);
949 fputc(d,f2);
955 void skiphtml(FILE *f1){
956 int c,d;
957 while((c=fgetc(f1))>=0){
958 if(c!='%'){
959 continue;
961 d=fgetc(f1);
962 if(d=='.') return; // end of section
966 static void print_int_array(const unsigned int* a, int size)
968 printf("{ ");
969 while (size--)
970 if(abs(*a)<256)
971 printf("%d%s", *a++, size?", ":"");
972 else
973 printf("0x%X%s", *a++, size?", ":"");
974 printf(" }");
977 static void print_char_array(const unsigned char* a, int size)
979 printf("{ ");
980 while (size--)
981 if((*a)<10)
982 printf("%d%s", *a++, size?", ":"");
983 else
984 printf("0x%02x%s", *a++, size?", ":"");
985 printf(" }");
988 static void print_string(const char* s)
990 if (!s) printf("NULL");
991 else printf("\"%s\"", s);
994 int main(int argc, char* argv[])
996 codecs_t *cl;
997 FILE *f1;
998 FILE *f2;
999 int c,d,i;
1000 int pos;
1001 int section=-1;
1002 int nr_codecs;
1003 int win32=-1;
1004 int dshow=-1;
1005 int win32ex=-1;
1008 * Take path to codecs.conf from command line, or fall back on
1009 * etc/codecs.conf
1011 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1012 exit(1);
1014 if (argc > 1) {
1015 int i, j;
1016 const char* nm[2];
1017 codecs_t* cod[2];
1018 int nr[2];
1020 nm[0] = "builtin_video_codecs";
1021 cod[0] = video_codecs;
1022 nr[0] = nr_vcodecs;
1024 nm[1] = "builtin_audio_codecs";
1025 cod[1] = audio_codecs;
1026 nr[1] = nr_acodecs;
1028 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1029 printf("#include <stddef.h>\n",argv[1]);
1030 printf("#include \"codec-cfg.h\"\n\n",argv[1]);
1032 for (i=0; i<2; i++) {
1033 printf("const codecs_t %s[] = {\n", nm[i]);
1034 for (j = 0; j < nr[i]; j++) {
1035 printf("{");
1037 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1038 printf(", /* fourcc */\n");
1040 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1041 printf(", /* fourccmap */\n");
1043 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1044 printf(", /* outfmt */\n");
1046 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1047 printf(", /* outflags */\n");
1049 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1050 printf(", /* infmt */\n");
1052 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1053 printf(", /* inflags */\n");
1055 print_string(cod[i][j].name); printf(", /* name */\n");
1056 print_string(cod[i][j].info); printf(", /* info */\n");
1057 print_string(cod[i][j].comment); printf(", /* comment */\n");
1058 print_string(cod[i][j].dll); printf(", /* dll */\n");
1059 print_string(cod[i][j].drv); printf(", /* drv */\n");
1061 printf("{ 0x%08lx, %hu, %hu,",
1062 cod[i][j].guid.f1,
1063 cod[i][j].guid.f2,
1064 cod[i][j].guid.f3);
1065 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1066 printf(" }, /* GUID */\n");
1067 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1068 cod[i][j].flags,
1069 cod[i][j].status,
1070 cod[i][j].cpuflags);
1071 if (j < nr[i]) printf(",\n");
1073 printf("};\n\n");
1075 exit(0);
1078 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1079 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1081 while((c=fgetc(f1))>=0){
1082 if(c!='%'){
1083 fputc(c,f2);
1084 continue;
1086 d=fgetc(f1);
1087 if(d>='0' && d<='9'){
1088 // begin section
1089 section=d-'0';
1090 //printf("BEGIN %d\n",section);
1091 if(section>=5){
1092 // audio
1093 cl = audio_codecs;
1094 nr_codecs = nr_acodecs;
1095 dshow=7;win32=4;
1096 } else {
1097 // video
1098 cl = video_codecs;
1099 nr_codecs = nr_vcodecs;
1100 dshow=4;win32=2;win32ex=6;
1102 pos=ftell(f1);
1103 for(i=0;i<nr_codecs;i++){
1104 fseek(f1,pos,SEEK_SET);
1105 switch(section){
1106 case 0:
1107 case 5:
1108 if(cl[i].status==CODECS_STATUS_WORKING)
1109 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1110 parsehtml(f1,f2,&cl[i],section,dshow);
1111 break;
1112 #if 0
1113 case 1:
1114 case 6:
1115 if(cl[i].status==CODECS_STATUS_WORKING)
1116 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1117 parsehtml(f1,f2,&cl[i],section,dshow);
1118 break;
1119 #endif
1120 case 2:
1121 case 7:
1122 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1123 parsehtml(f1,f2,&cl[i],section,dshow);
1124 break;
1125 case 3:
1126 case 8:
1127 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1128 parsehtml(f1,f2,&cl[i],section,dshow);
1129 break;
1130 case 4:
1131 case 9:
1132 if(cl[i].status==CODECS_STATUS_UNTESTED)
1133 parsehtml(f1,f2,&cl[i],section,dshow);
1134 break;
1135 default:
1136 printf("Warning! unimplemented section: %d\n",section);
1139 fseek(f1,pos,SEEK_SET);
1140 skiphtml(f1);
1141 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1143 continue;
1145 fputc(c,f2);
1146 fputc(d,f2);
1149 fclose(f2);
1150 fclose(f1);
1151 return 0;
1154 #endif
1156 #ifdef TESTING
1157 int main(void)
1159 codecs_t *c;
1160 int i,j, nr_codecs, state;
1162 if (!(parse_codec_cfg("etc/codecs.conf")))
1163 return 0;
1164 if (!video_codecs)
1165 printf("no videoconfig.\n");
1166 if (!audio_codecs)
1167 printf("no audioconfig.\n");
1169 printf("videocodecs:\n");
1170 c = video_codecs;
1171 nr_codecs = nr_vcodecs;
1172 state = 0;
1173 next:
1174 if (c) {
1175 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1176 nr_codecs);
1177 for(i=0;i<nr_codecs;i++, c++){
1178 printf("\n============== %scodec %02d ===============\n",
1179 state==0?"video":"audio",i);
1180 printf("name='%s'\n",c->name);
1181 printf("info='%s'\n",c->info);
1182 printf("comment='%s'\n",c->comment);
1183 printf("dll='%s'\n",c->dll);
1184 /* printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1185 c->flags, c->driver, c->status, c->cpuflags); */
1186 printf("flags=%X status=%d cpuflags=%d\n",
1187 c->flags, c->status, c->cpuflags);
1189 for(j=0;j<CODECS_MAX_FOURCC;j++){
1190 if(c->fourcc[j]!=0xFFFFFFFF){
1191 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1195 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1196 if(c->outfmt[j]!=0xFFFFFFFF){
1197 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1201 for(j=0;j<CODECS_MAX_INFMT;j++){
1202 if(c->infmt[j]!=0xFFFFFFFF){
1203 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1207 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1208 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1209 printf("\n");
1214 if (!state) {
1215 printf("audiocodecs:\n");
1216 c = audio_codecs;
1217 nr_codecs = nr_acodecs;
1218 state = 1;
1219 goto next;
1221 return 0;
1224 #endif