Updated ffmpeg
[mplayer/kovensky.git] / codec-cfg.c
blob6e90c06fa8fde46f0ea7fd958aaa0eb4b3cc9b63
1 /*
2 * codec.conf parser
3 * by Szabolcs Berecz <szabi@inf.elte.hu>
4 * (C) 2001
6 * to compile test application:
7 * cc -I. -DTESTING -o codec-cfg-test codec-cfg.c mp_msg.o osdep/getch2.o -ltermcap
8 * to compile CODECS2HTML:
9 * gcc -DCODECS2HTML -o codecs2html codec-cfg.c mp_msg.o
11 * TODO: implement informat in CODECS2HTML too
14 #define DEBUG
16 //disable asserts
17 #define NDEBUG
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <ctype.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <stdint.h>
29 #include "config.h"
30 #include "mp_msg.h"
31 #ifdef CODECS2HTML
32 #define mp_tmsg mp_msg
33 #ifdef __GNUC__
34 #define mp_msg(t, l, m, args...) fprintf(stderr, m, ##args)
35 #else
36 #define mp_msg(t, l, ...) fprintf(stderr, __VA_ARGS__)
37 #endif
38 #endif
40 #include "help_mp.h"
42 #include "libmpcodecs/img_format.h"
43 #include "codec-cfg.h"
45 #ifndef CODECS2HTML
46 #include "codecs.conf.h"
47 #endif
49 #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
50 ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
51 ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
53 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
55 #define MAX_NR_TOKEN 16
57 #define MAX_LINE_LEN 1000
59 #define RET_EOF -1
60 #define RET_EOL -2
62 #define TYPE_VIDEO 0
63 #define TYPE_AUDIO 1
65 char * codecs_file = NULL;
67 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
68 unsigned int *map)
70 int i, j, freeslots;
71 unsigned int tmp;
73 /* find first unused slot */
74 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
75 /* NOTHING */;
76 freeslots = CODECS_MAX_FOURCC - i;
77 if (!freeslots)
78 goto err_out_too_many;
80 do {
81 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
82 for (j = 0; j < i; j++)
83 if (tmp == fourcc[j])
84 goto err_out_duplicated;
85 fourcc[i] = tmp;
86 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
87 s += 4;
88 i++;
89 } while ((*(s++) == ',') && --freeslots);
91 if (!freeslots)
92 goto err_out_too_many;
93 if (*(--s) != '\0')
94 goto err_out_parse_error;
95 return 1;
96 err_out_duplicated:
97 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
98 return 0;
99 err_out_too_many:
100 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
101 return 0;
102 err_out_parse_error:
103 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
104 return 0;
107 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
109 int i, j;
110 char *endptr;
112 /* find first unused slot */
113 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
114 /* NOTHING */;
115 if (i == CODECS_MAX_FOURCC) {
116 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
117 return 0;
120 fourcc[i]=strtoul(s,&endptr,0);
121 if (*endptr != '\0') {
122 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
123 return 0;
126 if(alias){
127 fourccmap[i]=strtoul(alias,&endptr,0);
128 if (*endptr != '\0') {
129 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
130 return 0;
132 } else
133 fourccmap[i]=fourcc[i];
135 for (j = 0; j < i; j++)
136 if (fourcc[j] == fourcc[i]) {
137 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
138 return 0;
141 return 1;
144 static const struct {
145 const char *name;
146 const unsigned int num;
147 } fmt_table[] = {
148 // note: due to parser deficiencies/simplicity, if one format
149 // name matches the beginning of another, the longer one _must_
150 // come first in this list.
151 {"YV12", IMGFMT_YV12},
152 {"I420", IMGFMT_I420},
153 {"IYUV", IMGFMT_IYUV},
154 {"NV12", IMGFMT_NV12},
155 {"NV21", IMGFMT_NV21},
156 {"YVU9", IMGFMT_YVU9},
157 {"IF09", IMGFMT_IF09},
158 {"444P", IMGFMT_444P},
159 {"422P", IMGFMT_422P},
160 {"411P", IMGFMT_411P},
161 {"Y800", IMGFMT_Y800},
162 {"Y8", IMGFMT_Y8},
164 {"YUY2", IMGFMT_YUY2},
165 {"UYVY", IMGFMT_UYVY},
166 {"YVYU", IMGFMT_YVYU},
168 {"RGB48LE", IMGFMT_RGB48LE},
169 {"RGB48BE", IMGFMT_RGB48BE},
170 {"RGB4", IMGFMT_RGB4},
171 {"RGB8", IMGFMT_RGB8},
172 {"RGB15", IMGFMT_RGB15},
173 {"RGB16", IMGFMT_RGB16},
174 {"RGB24", IMGFMT_RGB24},
175 {"RGB32", IMGFMT_RGB32},
176 {"BGR4", IMGFMT_BGR4},
177 {"BGR8", IMGFMT_BGR8},
178 {"BGR15", IMGFMT_BGR15},
179 {"BGR16", IMGFMT_BGR16},
180 {"BGR24", IMGFMT_BGR24},
181 {"BGR32", IMGFMT_BGR32},
182 {"RGB1", IMGFMT_RGB1},
183 {"BGR1", IMGFMT_BGR1},
185 {"MPES", IMGFMT_MPEGPES},
186 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
187 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
188 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
190 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
191 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
193 {"VDPAU_MPEG1",IMGFMT_VDPAU_MPEG1},
194 {"VDPAU_MPEG2",IMGFMT_VDPAU_MPEG2},
195 {"VDPAU_H264",IMGFMT_VDPAU_H264},
196 {"VDPAU_WMV3",IMGFMT_VDPAU_WMV3},
197 {"VDPAU_VC1",IMGFMT_VDPAU_VC1},
199 {NULL, 0}
203 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
204 unsigned char *outflags)
207 static char *flagstr[] = {
208 "flip",
209 "noflip",
210 "yuvhack",
211 "query",
212 "static",
213 NULL
216 int i, j, freeslots;
217 unsigned char flags;
219 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
220 /* NOTHING */;
221 freeslots = CODECS_MAX_OUTFMT - i;
222 if (!freeslots)
223 goto err_out_too_many;
225 flags = 0;
226 if(sflags) {
227 do {
228 for (j = 0; flagstr[j] != NULL; j++)
229 if (!strncmp(sflags, flagstr[j],
230 strlen(flagstr[j])))
231 break;
232 if (flagstr[j] == NULL)
233 goto err_out_parse_error;
234 flags|=(1<<j);
235 sflags+=strlen(flagstr[j]);
236 } while (*(sflags++) == ',');
238 if (*(--sflags) != '\0')
239 goto err_out_parse_error;
242 do {
243 for (j = 0; fmt_table[j].name != NULL; j++)
244 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
245 break;
246 if (fmt_table[j].name == NULL)
247 goto err_out_parse_error;
248 outfmt[i] = fmt_table[j].num;
249 outflags[i] = flags;
250 ++i;
251 sfmt+=strlen(fmt_table[j].name);
252 } while ((*(sfmt++) == ',') && --freeslots);
254 if (!freeslots)
255 goto err_out_too_many;
257 if (*(--sfmt) != '\0')
258 goto err_out_parse_error;
260 return 1;
261 err_out_too_many:
262 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many out...");
263 return 0;
264 err_out_parse_error:
265 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
266 return 0;
269 #if 0
270 static short get_driver(char *s,int audioflag)
272 static char *audiodrv[] = {
273 "null",
274 "mp3lib",
275 "pcm",
276 "libac3",
277 "acm",
278 "alaw",
279 "msgsm",
280 "dshow",
281 "dvdpcm",
282 "hwac3",
283 "libvorbis",
284 "ffmpeg",
285 "libmad",
286 "msadpcm",
287 "liba52",
288 "g72x",
289 "imaadpcm",
290 "dk4adpcm",
291 "dk3adpcm",
292 "roqaudio",
293 "faad",
294 "realaud",
295 "libdv",
296 NULL
298 static char *videodrv[] = {
299 "null",
300 "libmpeg2",
301 "vfw",
302 "dshow",
303 "ffmpeg",
304 "vfwex",
305 "raw",
306 "msrle",
307 "xanim",
308 "msvidc",
309 "fli",
310 "cinepak",
311 "qtrle",
312 "nuv",
313 "cyuv",
314 "qtsmc",
315 "ducktm1",
316 "roqvideo",
317 "qtrpza",
318 "mpng",
319 "ijpg",
320 "zlib",
321 "mpegpes",
322 "zrmjpeg",
323 "realvid",
324 "xvid",
325 "libdv",
326 NULL
328 char **drv=audioflag?audiodrv:videodrv;
329 int i;
331 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
333 return -1;
335 #endif
337 static int validate_codec(codecs_t *c, int type)
339 unsigned int i;
340 char *tmp_name = c->name;
342 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
343 /* NOTHING */;
345 if (i < strlen(tmp_name)) {
346 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
347 return 0;
350 if (!c->info)
351 c->info = strdup(c->name);
353 #if 0
354 if (c->fourcc[0] == 0xffffffff) {
355 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have FourCC/format!\n", c->name);
356 return 0;
358 #endif
360 if (!c->drv) {
361 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
362 return 0;
365 #if 0
366 #warning codec->driver == 4;... <- this should not be put in here...
367 #warning Where are they defined ????????????
368 if (!c->dll && (c->driver == 4 ||
369 (c->driver == 2 && type == TYPE_VIDEO))) {
370 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs a 'dll'!\n", c->name);
371 return 0;
373 #warning Can guid.f1 be 0? How does one know that it was not given?
374 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
376 if (type == TYPE_VIDEO)
377 if (c->outfmt[0] == 0xffffffff) {
378 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs an 'outfmt'!\n", c->name);
379 return 0;
381 #endif
382 return 1;
385 static int add_comment(char *s, char **d)
387 int pos;
389 if (!*d)
390 pos = 0;
391 else {
392 pos = strlen(*d);
393 (*d)[pos++] = '\n';
395 if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
396 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
397 return 0;
399 strcpy(*d + pos, s);
400 return 1;
403 static short get_cpuflags(char *s)
405 static char *flagstr[] = {
406 "mmx",
407 "sse",
408 "3dnow",
409 NULL
411 int i;
412 short flags = 0;
414 do {
415 for (i = 0; flagstr[i]; i++)
416 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
417 break;
418 if (!flagstr[i])
419 goto err_out_parse_error;
420 flags |= 1<<i;
421 s += strlen(flagstr[i]);
422 } while (*(s++) == ',');
424 if (*(--s) != '\0')
425 goto err_out_parse_error;
427 return flags;
428 err_out_parse_error:
429 return 0;
432 static FILE *fp;
433 static int line_num = 0;
434 static char *line;
435 static char *token[MAX_NR_TOKEN];
436 static int read_nextline = 1;
438 static int get_token(int min, int max)
440 static int line_pos;
441 int i;
442 char c;
444 if (max >= MAX_NR_TOKEN) {
445 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_MR_TOKEN!");
446 goto out_eof;
449 memset(token, 0x00, sizeof(*token) * max);
451 if (read_nextline) {
452 if (!fgets(line, MAX_LINE_LEN, fp))
453 goto out_eof;
454 line_pos = 0;
455 ++line_num;
456 read_nextline = 0;
458 for (i = 0; i < max; i++) {
459 while (isspace(line[line_pos]))
460 ++line_pos;
461 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
462 line[line_pos] == ';') {
463 read_nextline = 1;
464 if (i >= min)
465 goto out_ok;
466 goto out_eol;
468 token[i] = line + line_pos;
469 c = line[line_pos];
470 if (c == '"' || c == '\'') {
471 token[i]++;
472 while (line[++line_pos] != c && line[line_pos])
473 /* NOTHING */;
474 } else {
475 for (/* NOTHING */; !isspace(line[line_pos]) &&
476 line[line_pos]; line_pos++)
477 /* NOTHING */;
479 if (!line[line_pos]) {
480 read_nextline = 1;
481 if (i >= min - 1)
482 goto out_ok;
483 goto out_eol;
485 line[line_pos] = '\0';
486 line_pos++;
488 out_ok:
489 return i;
490 out_eof:
491 read_nextline = 1;
492 return RET_EOF;
493 out_eol:
494 return RET_EOL;
497 static codecs_t *video_codecs=NULL;
498 static codecs_t *audio_codecs=NULL;
499 static int nr_vcodecs = 0;
500 static int nr_acodecs = 0;
502 int parse_codec_cfg(const char *cfgfile)
504 codecs_t *codec = NULL; // current codec
505 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
506 char *endptr; // strtoul()...
507 int *nr_codecsp;
508 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
509 int tmp, i;
511 // in case we call it a second time
512 codecs_uninit_free();
514 nr_vcodecs = 0;
515 nr_acodecs = 0;
517 if(cfgfile==NULL) {
518 #ifdef CODECS2HTML
519 return 0;
520 #else
521 video_codecs = builtin_video_codecs;
522 audio_codecs = builtin_audio_codecs;
523 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
524 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
525 return 1;
526 #endif
529 mp_tmsg(MSGT_CODECCFG,MSGL_V,"Reading %s: ", cfgfile);
531 if ((fp = fopen(cfgfile, "r")) == NULL) {
532 mp_tmsg(MSGT_CODECCFG,MSGL_V,"Can't open '%s': %s\n", cfgfile, strerror(errno));
533 return 0;
536 if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) {
537 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't get memory for 'line': %s\n", strerror(errno));
538 return 0;
540 read_nextline = 1;
543 * this only catches release lines at the start of
544 * codecs.conf, before audiocodecs and videocodecs.
546 while ((tmp = get_token(1, 1)) == RET_EOL)
547 /* NOTHING */;
548 if (tmp == RET_EOF)
549 goto out;
550 if (!strcmp(token[0], "release")) {
551 if (get_token(1, 2) < 0)
552 goto err_out_parse_error;
553 tmp = atoi(token[0]);
554 if (tmp < CODEC_CFG_MIN)
555 goto err_out_release_num;
556 while ((tmp = get_token(1, 1)) == RET_EOL)
557 /* NOTHING */;
558 if (tmp == RET_EOF)
559 goto out;
560 } else
561 goto err_out_release_num;
564 * check if the next block starts with 'audiocodec' or
565 * with 'videocodec'
567 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
568 goto loop_enter;
569 goto err_out_parse_error;
571 while ((tmp = get_token(1, 1)) != RET_EOF) {
572 if (tmp == RET_EOL)
573 continue;
574 if (!strcmp(token[0], "audiocodec") ||
575 !strcmp(token[0], "videocodec")) {
576 if (!validate_codec(codec, codec_type))
577 goto err_out_not_valid;
578 loop_enter:
579 if (*token[0] == 'v') {
580 codec_type = TYPE_VIDEO;
581 nr_codecsp = &nr_vcodecs;
582 codecsp = &video_codecs;
583 } else if (*token[0] == 'a') {
584 codec_type = TYPE_AUDIO;
585 nr_codecsp = &nr_acodecs;
586 codecsp = &audio_codecs;
587 #ifdef DEBUG
588 } else {
589 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
590 goto err_out;
591 #endif
593 if (!(*codecsp = realloc(*codecsp,
594 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
595 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
596 goto err_out;
598 codec=*codecsp + *nr_codecsp;
599 ++*nr_codecsp;
600 memset(codec,0,sizeof(codecs_t));
601 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
602 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
603 memset(codec->infmt, 0xff, sizeof(codec->infmt));
605 if (get_token(1, 1) < 0)
606 goto err_out_parse_error;
607 for (i = 0; i < *nr_codecsp - 1; i++) {
608 if(( (*codecsp)[i].name!=NULL) &&
609 (!strcmp(token[0], (*codecsp)[i].name)) ) {
610 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
611 goto err_out_print_linenum;
614 if (!(codec->name = strdup(token[0]))) {
615 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
616 goto err_out;
618 } else if (!strcmp(token[0], "info")) {
619 if (codec->info || get_token(1, 1) < 0)
620 goto err_out_parse_error;
621 if (!(codec->info = strdup(token[0]))) {
622 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
623 goto err_out;
625 } else if (!strcmp(token[0], "comment")) {
626 if (get_token(1, 1) < 0)
627 goto err_out_parse_error;
628 add_comment(token[0], &codec->comment);
629 } else if (!strcmp(token[0], "fourcc")) {
630 if (get_token(1, 2) < 0)
631 goto err_out_parse_error;
632 if (!add_to_fourcc(token[0], token[1],
633 codec->fourcc,
634 codec->fourccmap))
635 goto err_out_print_linenum;
636 } else if (!strcmp(token[0], "format")) {
637 if (get_token(1, 2) < 0)
638 goto err_out_parse_error;
639 if (!add_to_format(token[0], token[1],
640 codec->fourcc,codec->fourccmap))
641 goto err_out_print_linenum;
642 } else if (!strcmp(token[0], "driver")) {
643 if (get_token(1, 1) < 0)
644 goto err_out_parse_error;
645 if (!(codec->drv = strdup(token[0]))) {
646 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
647 goto err_out;
649 } else if (!strcmp(token[0], "dll")) {
650 if (get_token(1, 1) < 0)
651 goto err_out_parse_error;
652 if (!(codec->dll = strdup(token[0]))) {
653 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s", strerror(errno));
654 goto err_out;
656 } else if (!strcmp(token[0], "guid")) {
657 if (get_token(11, 11) < 0)
658 goto err_out_parse_error;
659 codec->guid.f1=strtoul(token[0],&endptr,0);
660 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
661 *endptr != '\0')
662 goto err_out_parse_error;
663 codec->guid.f2=strtoul(token[1],&endptr,0);
664 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
665 *endptr != '\0')
666 goto err_out_parse_error;
667 codec->guid.f3=strtoul(token[2],&endptr,0);
668 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
669 *endptr != '\0')
670 goto err_out_parse_error;
671 for (i = 0; i < 8; i++) {
672 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
673 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
674 *endptr != '\0')
675 goto err_out_parse_error;
677 } else if (!strcmp(token[0], "out")) {
678 if (get_token(1, 2) < 0)
679 goto err_out_parse_error;
680 if (!add_to_inout(token[0], token[1], codec->outfmt,
681 codec->outflags))
682 goto err_out_print_linenum;
683 } else if (!strcmp(token[0], "in")) {
684 if (get_token(1, 2) < 0)
685 goto err_out_parse_error;
686 if (!add_to_inout(token[0], token[1], codec->infmt,
687 codec->inflags))
688 goto err_out_print_linenum;
689 } else if (!strcmp(token[0], "flags")) {
690 if (get_token(1, 1) < 0)
691 goto err_out_parse_error;
692 if (!strcmp(token[0], "seekable"))
693 codec->flags |= CODECS_FLAG_SEEKABLE;
694 else
695 if (!strcmp(token[0], "align16"))
696 codec->flags |= CODECS_FLAG_ALIGN16;
697 else
698 goto err_out_parse_error;
699 } else if (!strcmp(token[0], "status")) {
700 if (get_token(1, 1) < 0)
701 goto err_out_parse_error;
702 if (!strcasecmp(token[0], "working"))
703 codec->status = CODECS_STATUS_WORKING;
704 else if (!strcasecmp(token[0], "crashing"))
705 codec->status = CODECS_STATUS_NOT_WORKING;
706 else if (!strcasecmp(token[0], "untested"))
707 codec->status = CODECS_STATUS_UNTESTED;
708 else if (!strcasecmp(token[0], "buggy"))
709 codec->status = CODECS_STATUS_PROBLEMS;
710 else
711 goto err_out_parse_error;
712 } else if (!strcmp(token[0], "cpuflags")) {
713 if (get_token(1, 1) < 0)
714 goto err_out_parse_error;
715 if (!(codec->cpuflags = get_cpuflags(token[0])))
716 goto err_out_parse_error;
717 } else
718 goto err_out_parse_error;
720 if (!validate_codec(codec, codec_type))
721 goto err_out_not_valid;
722 mp_tmsg(MSGT_CODECCFG,MSGL_INFO,"%d audio & %d video codecs\n", nr_acodecs, nr_vcodecs);
723 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
724 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
725 out:
726 free(line);
727 line=NULL;
728 fclose(fp);
729 return 1;
731 err_out_parse_error:
732 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
733 err_out_print_linenum:
734 PRINT_LINENUM;
735 err_out:
736 codecs_uninit_free();
738 free(line);
739 line=NULL;
740 line_num = 0;
741 fclose(fp);
742 return 0;
743 err_out_not_valid:
744 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
745 goto err_out_print_linenum;
746 err_out_release_num:
747 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
748 goto err_out_print_linenum;
751 static void codecs_free(codecs_t* codecs,int count) {
752 int i;
753 for ( i = 0; i < count; i++)
754 if ( codecs[i].name ) {
755 if( codecs[i].name )
756 free(codecs[i].name);
757 if( codecs[i].info )
758 free(codecs[i].info);
759 if( codecs[i].comment )
760 free(codecs[i].comment);
761 if( codecs[i].dll )
762 free(codecs[i].dll);
763 if( codecs[i].drv )
764 free(codecs[i].drv);
766 if (codecs)
767 free(codecs);
770 void codecs_uninit_free(void) {
771 if (video_codecs)
772 codecs_free(video_codecs,nr_vcodecs);
773 video_codecs=NULL;
774 if (audio_codecs)
775 codecs_free(audio_codecs,nr_acodecs);
776 audio_codecs=NULL;
779 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
780 codecs_t *start, int force)
782 return find_codec(fourcc, fourccmap, start, 1, force);
785 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
786 codecs_t *start, int force)
788 return find_codec(fourcc, fourccmap, start, 0, force);
791 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
792 codecs_t *start, int audioflag, int force)
794 int i, j;
795 codecs_t *c;
797 #if 0
798 if (start) {
799 for (/* NOTHING */; start->name; start++) {
800 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
801 if (start->fourcc[j] == fourcc) {
802 if (fourccmap)
803 *fourccmap = start->fourccmap[j];
804 return start;
808 } else
809 #endif
811 if (audioflag) {
812 i = nr_acodecs;
813 c = audio_codecs;
814 } else {
815 i = nr_vcodecs;
816 c = video_codecs;
818 if(!i) return NULL;
819 for (/* NOTHING */; i--; c++) {
820 if(start && c<=start) continue;
821 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
822 // FIXME: do NOT hardwire 'null' name here:
823 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
824 if (fourccmap)
825 *fourccmap = c->fourccmap[j];
826 return c;
829 if (force) return c;
832 return NULL;
835 void stringset_init(stringset_t *set) {
836 *set = calloc(1, sizeof(char *));
839 void stringset_free(stringset_t *set) {
840 int count = 0;
841 while ((*set)[count]) free((*set)[count++]);
842 free(*set);
843 *set = NULL;
846 void stringset_add(stringset_t *set, const char *str) {
847 int count = 0;
848 while ((*set)[count]) count++;
849 count++;
850 *set = realloc(*set, sizeof(char *) * (count + 1));
851 (*set)[count - 1] = strdup(str);
852 (*set)[count] = NULL;
855 int stringset_test(stringset_t *set, const char *str) {
856 stringset_t s;
857 for (s = *set; *s; s++)
858 if (strcmp(*s, str) == 0)
859 return 1;
860 return 0;
863 void list_codecs(int audioflag){
864 int i;
865 codecs_t *c;
867 if (audioflag) {
868 i = nr_acodecs;
869 c = audio_codecs;
870 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
871 } else {
872 i = nr_vcodecs;
873 c = video_codecs;
874 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
876 if(!i) return;
877 for (/* NOTHING */; i--; c++) {
878 char* s="unknown ";
879 switch(c->status){
880 case CODECS_STATUS_WORKING: s="working ";break;
881 case CODECS_STATUS_PROBLEMS: s="problems";break;
882 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
883 case CODECS_STATUS_UNTESTED: s="untested";break;
885 if(c->dll)
886 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
887 else
888 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
896 #ifdef CODECS2HTML
897 void wrapline(FILE *f2,char *s){
898 int c;
899 if(!s){
900 fprintf(f2,"-");
901 return;
903 while((c=*s++)){
904 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
908 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
909 int c,d;
910 while((c=fgetc(f1))>=0){
911 if(c!='%'){
912 fputc(c,f2);
913 continue;
915 d=fgetc(f1);
917 switch(d){
918 case '.':
919 return; // end of section
920 case 'n':
921 wrapline(f2,codec->name); break;
922 case 'i':
923 wrapline(f2,codec->info); break;
924 case 'c':
925 wrapline(f2,codec->comment); break;
926 case 'd':
927 wrapline(f2,codec->dll); break;
928 case 'D':
929 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
930 case 'F':
931 for(d=0;d<CODECS_MAX_FOURCC;d++)
932 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
933 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
934 break;
935 case 'f':
936 for(d=0;d<CODECS_MAX_FOURCC;d++)
937 if(codec->fourcc[d]!=0xFFFFFFFF)
938 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
939 break;
940 case 'Y':
941 for(d=0;d<CODECS_MAX_OUTFMT;d++)
942 if(codec->outfmt[d]!=0xFFFFFFFF){
943 for (c=0; fmt_table[c].name; c++)
944 if(fmt_table[c].num==codec->outfmt[d]) break;
945 if(fmt_table[c].name)
946 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
948 break;
949 default:
950 fputc(c,f2);
951 fputc(d,f2);
957 void skiphtml(FILE *f1){
958 int c,d;
959 while((c=fgetc(f1))>=0){
960 if(c!='%'){
961 continue;
963 d=fgetc(f1);
964 if(d=='.') return; // end of section
968 static void print_int_array(const unsigned int* a, int size)
970 printf("{ ");
971 while (size--)
972 if(abs(*a)<256)
973 printf("%d%s", *a++, size?", ":"");
974 else
975 printf("0x%X%s", *a++, size?", ":"");
976 printf(" }");
979 static void print_char_array(const unsigned char* a, int size)
981 printf("{ ");
982 while (size--)
983 if((*a)<10)
984 printf("%d%s", *a++, size?", ":"");
985 else
986 printf("0x%02x%s", *a++, size?", ":"");
987 printf(" }");
990 static void print_string(const char* s)
992 if (!s) printf("NULL");
993 else printf("\"%s\"", s);
996 int main(int argc, char* argv[])
998 codecs_t *cl;
999 FILE *f1;
1000 FILE *f2;
1001 int c,d,i;
1002 int pos;
1003 int section=-1;
1004 int nr_codecs;
1005 int win32=-1;
1006 int dshow=-1;
1007 int win32ex=-1;
1010 * Take path to codecs.conf from command line, or fall back on
1011 * etc/codecs.conf
1013 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1014 exit(1);
1016 if (argc > 1) {
1017 int i, j;
1018 const char* nm[2];
1019 codecs_t* cod[2];
1020 int nr[2];
1022 nm[0] = "builtin_video_codecs";
1023 cod[0] = video_codecs;
1024 nr[0] = nr_vcodecs;
1026 nm[1] = "builtin_audio_codecs";
1027 cod[1] = audio_codecs;
1028 nr[1] = nr_acodecs;
1030 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1031 printf("#include <stddef.h>\n");
1032 printf("#include \"codec-cfg.h\"\n\n");
1034 for (i=0; i<2; i++) {
1035 printf("const codecs_t %s[] = {\n", nm[i]);
1036 for (j = 0; j < nr[i]; j++) {
1037 printf("{");
1039 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1040 printf(", /* fourcc */\n");
1042 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1043 printf(", /* fourccmap */\n");
1045 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1046 printf(", /* outfmt */\n");
1048 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1049 printf(", /* outflags */\n");
1051 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1052 printf(", /* infmt */\n");
1054 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1055 printf(", /* inflags */\n");
1057 print_string(cod[i][j].name); printf(", /* name */\n");
1058 print_string(cod[i][j].info); printf(", /* info */\n");
1059 print_string(cod[i][j].comment); printf(", /* comment */\n");
1060 print_string(cod[i][j].dll); printf(", /* dll */\n");
1061 print_string(cod[i][j].drv); printf(", /* drv */\n");
1063 printf("{ 0x%08lx, %hu, %hu,",
1064 cod[i][j].guid.f1,
1065 cod[i][j].guid.f2,
1066 cod[i][j].guid.f3);
1067 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1068 printf(" }, /* GUID */\n");
1069 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1070 cod[i][j].flags,
1071 cod[i][j].status,
1072 cod[i][j].cpuflags);
1073 if (j < nr[i]) printf(",\n");
1075 printf("};\n\n");
1077 exit(0);
1080 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1081 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1083 while((c=fgetc(f1))>=0){
1084 if(c!='%'){
1085 fputc(c,f2);
1086 continue;
1088 d=fgetc(f1);
1089 if(d>='0' && d<='9'){
1090 // begin section
1091 section=d-'0';
1092 //printf("BEGIN %d\n",section);
1093 if(section>=5){
1094 // audio
1095 cl = audio_codecs;
1096 nr_codecs = nr_acodecs;
1097 dshow=7;win32=4;
1098 } else {
1099 // video
1100 cl = video_codecs;
1101 nr_codecs = nr_vcodecs;
1102 dshow=4;win32=2;win32ex=6;
1104 pos=ftell(f1);
1105 for(i=0;i<nr_codecs;i++){
1106 fseek(f1,pos,SEEK_SET);
1107 switch(section){
1108 case 0:
1109 case 5:
1110 if(cl[i].status==CODECS_STATUS_WORKING)
1111 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1112 parsehtml(f1,f2,&cl[i],section,dshow);
1113 break;
1114 #if 0
1115 case 1:
1116 case 6:
1117 if(cl[i].status==CODECS_STATUS_WORKING)
1118 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1119 parsehtml(f1,f2,&cl[i],section,dshow);
1120 break;
1121 #endif
1122 case 2:
1123 case 7:
1124 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1125 parsehtml(f1,f2,&cl[i],section,dshow);
1126 break;
1127 case 3:
1128 case 8:
1129 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1130 parsehtml(f1,f2,&cl[i],section,dshow);
1131 break;
1132 case 4:
1133 case 9:
1134 if(cl[i].status==CODECS_STATUS_UNTESTED)
1135 parsehtml(f1,f2,&cl[i],section,dshow);
1136 break;
1137 default:
1138 printf("Warning! unimplemented section: %d\n",section);
1141 fseek(f1,pos,SEEK_SET);
1142 skiphtml(f1);
1143 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1145 continue;
1147 fputc(c,f2);
1148 fputc(d,f2);
1151 fclose(f2);
1152 fclose(f1);
1153 return 0;
1156 #endif
1158 #ifdef TESTING
1159 int main(void)
1161 codecs_t *c;
1162 int i,j, nr_codecs, state;
1164 if (!(parse_codec_cfg("etc/codecs.conf")))
1165 return 0;
1166 if (!video_codecs)
1167 printf("no videoconfig.\n");
1168 if (!audio_codecs)
1169 printf("no audioconfig.\n");
1171 printf("videocodecs:\n");
1172 c = video_codecs;
1173 nr_codecs = nr_vcodecs;
1174 state = 0;
1175 next:
1176 if (c) {
1177 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1178 nr_codecs);
1179 for(i=0;i<nr_codecs;i++, c++){
1180 printf("\n============== %scodec %02d ===============\n",
1181 state==0?"video":"audio",i);
1182 printf("name='%s'\n",c->name);
1183 printf("info='%s'\n",c->info);
1184 printf("comment='%s'\n",c->comment);
1185 printf("dll='%s'\n",c->dll);
1186 /* printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1187 c->flags, c->driver, c->status, c->cpuflags); */
1188 printf("flags=%X status=%d cpuflags=%d\n",
1189 c->flags, c->status, c->cpuflags);
1191 for(j=0;j<CODECS_MAX_FOURCC;j++){
1192 if(c->fourcc[j]!=0xFFFFFFFF){
1193 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1197 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1198 if(c->outfmt[j]!=0xFFFFFFFF){
1199 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1203 for(j=0;j<CODECS_MAX_INFMT;j++){
1204 if(c->infmt[j]!=0xFFFFFFFF){
1205 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1209 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1210 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1211 printf("\n");
1216 if (!state) {
1217 printf("audiocodecs:\n");
1218 c = audio_codecs;
1219 nr_codecs = nr_acodecs;
1220 state = 1;
1221 goto next;
1223 return 0;
1226 #endif