add a file saying that people should not try to compile
[mplayer/glamo.git] / codec-cfg.c
blob588baa06b00362a0238e6d9e5d0a1c759eac2f63
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:
8 * gcc -DCODECS2HTML -o codecs2html codec-cfg.c mp_msg.o
10 * TODO: implement informat in CODECS2HTML too
13 #define DEBUG
15 //disable asserts
16 #define NDEBUG
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <ctype.h>
24 #include <assert.h>
25 #include <string.h>
27 #include "config.h"
28 #include "mp_msg.h"
29 #ifdef CODECS2HTML
30 #ifdef __GNUC__
31 #define mp_msg(t, l, m, args...) fprintf(stderr, m, ##args)
32 #else
33 #define mp_msg(t, l, m, ...) fprintf(stderr, m, __VA_ARGS__)
34 #endif
35 #endif
37 #include "help_mp.h"
39 // for mmioFOURCC:
40 #include "libmpdemux/aviheader.h"
42 #include "libmpcodecs/img_format.h"
43 #include "codec-cfg.h"
45 #ifndef CODECS2HTML
46 #include "codecs.conf.h"
47 #endif
49 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
51 #define MAX_NR_TOKEN 16
53 #define MAX_LINE_LEN 1000
55 #define RET_EOF -1
56 #define RET_EOL -2
58 #define TYPE_VIDEO 0
59 #define TYPE_AUDIO 1
61 char * codecs_file = NULL;
63 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
64 unsigned int *map)
66 int i, j, freeslots;
67 unsigned int tmp;
69 /* find first unused slot */
70 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
71 /* NOTHING */;
72 freeslots = CODECS_MAX_FOURCC - i;
73 if (!freeslots)
74 goto err_out_too_many;
76 do {
77 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
78 for (j = 0; j < i; j++)
79 if (tmp == fourcc[j])
80 goto err_out_duplicated;
81 fourcc[i] = tmp;
82 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
83 s += 4;
84 i++;
85 } while ((*(s++) == ',') && --freeslots);
87 if (!freeslots)
88 goto err_out_too_many;
89 if (*(--s) != '\0')
90 goto err_out_parse_error;
91 return 1;
92 err_out_duplicated:
93 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFourcc);
94 return 0;
95 err_out_too_many:
96 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
97 return 0;
98 err_out_parse_error:
99 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
100 return 0;
103 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
105 int i, j;
106 char *endptr;
108 /* find first unused slot */
109 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
110 /* NOTHING */;
111 if (i == CODECS_MAX_FOURCC) {
112 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
113 return 0;
116 fourcc[i]=strtoul(s,&endptr,0);
117 if (*endptr != '\0') {
118 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDNotNumber);
119 return 0;
122 if(alias){
123 fourccmap[i]=strtoul(alias,&endptr,0);
124 if (*endptr != '\0') {
125 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDAliasNotNumber);
126 return 0;
128 } else
129 fourccmap[i]=fourcc[i];
131 for (j = 0; j < i; j++)
132 if (fourcc[j] == fourcc[i]) {
133 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFID);
134 return 0;
137 return 1;
140 static struct {
141 const char *name;
142 const unsigned int num;
143 } fmt_table[] = {
144 {"YV12", IMGFMT_YV12},
145 {"I420", IMGFMT_I420},
146 {"IYUV", IMGFMT_IYUV},
147 {"NV12", IMGFMT_NV12},
148 {"NV21", IMGFMT_NV21},
149 {"YVU9", IMGFMT_YVU9},
150 {"IF09", IMGFMT_IF09},
151 {"444P", IMGFMT_444P},
152 {"422P", IMGFMT_422P},
153 {"411P", IMGFMT_411P},
154 {"Y800", IMGFMT_Y800},
155 {"Y8", IMGFMT_Y8},
157 {"YUY2", IMGFMT_YUY2},
158 {"UYVY", IMGFMT_UYVY},
159 {"YVYU", IMGFMT_YVYU},
161 {"RGB4", IMGFMT_RGB|4},
162 {"RGB8", IMGFMT_RGB|8},
163 {"RGB15", IMGFMT_RGB|15},
164 {"RGB16", IMGFMT_RGB|16},
165 {"RGB24", IMGFMT_RGB|24},
166 {"RGB32", IMGFMT_RGB|32},
167 {"BGR4", IMGFMT_BGR|4},
168 {"BGR8", IMGFMT_BGR|8},
169 {"BGR15", IMGFMT_BGR|15},
170 {"BGR16", IMGFMT_BGR|16},
171 {"BGR24", IMGFMT_BGR|24},
172 {"BGR32", IMGFMT_BGR|32},
173 {"RGB1", IMGFMT_RGB|1},
174 {"BGR1", IMGFMT_BGR|1},
176 {"MPES", IMGFMT_MPEGPES},
177 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
178 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
179 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
181 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
182 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
184 {NULL, 0}
188 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
189 unsigned char *outflags)
192 static char *flagstr[] = {
193 "flip",
194 "noflip",
195 "yuvhack",
196 "query",
197 "static",
198 NULL
201 int i, j, freeslots;
202 unsigned char flags;
204 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
205 /* NOTHING */;
206 freeslots = CODECS_MAX_OUTFMT - i;
207 if (!freeslots)
208 goto err_out_too_many;
210 flags = 0;
211 if(sflags) {
212 do {
213 for (j = 0; flagstr[j] != NULL; j++)
214 if (!strncmp(sflags, flagstr[j],
215 strlen(flagstr[j])))
216 break;
217 if (flagstr[j] == NULL)
218 goto err_out_parse_error;
219 flags|=(1<<j);
220 sflags+=strlen(flagstr[j]);
221 } while (*(sflags++) == ',');
223 if (*(--sflags) != '\0')
224 goto err_out_parse_error;
227 do {
228 for (j = 0; fmt_table[j].name != NULL; j++)
229 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
230 break;
231 if (fmt_table[j].name == NULL)
232 goto err_out_parse_error;
233 outfmt[i] = fmt_table[j].num;
234 outflags[i] = flags;
235 ++i;
236 sfmt+=strlen(fmt_table[j].name);
237 } while ((*(sfmt++) == ',') && --freeslots);
239 if (!freeslots)
240 goto err_out_too_many;
242 if (*(--sfmt) != '\0')
243 goto err_out_parse_error;
245 return 1;
246 err_out_too_many:
247 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyOut);
248 return 0;
249 err_out_parse_error:
250 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
251 return 0;
254 #if 0
255 static short get_driver(char *s,int audioflag)
257 static char *audiodrv[] = {
258 "null",
259 "mp3lib",
260 "pcm",
261 "libac3",
262 "acm",
263 "alaw",
264 "msgsm",
265 "dshow",
266 "dvdpcm",
267 "hwac3",
268 "libvorbis",
269 "ffmpeg",
270 "libmad",
271 "msadpcm",
272 "liba52",
273 "g72x",
274 "imaadpcm",
275 "dk4adpcm",
276 "dk3adpcm",
277 "roqaudio",
278 "faad",
279 "realaud",
280 "libdv",
281 NULL
283 static char *videodrv[] = {
284 "null",
285 "libmpeg2",
286 "vfw",
287 "odivx",
288 "dshow",
289 "ffmpeg",
290 "vfwex",
291 "divx4",
292 "raw",
293 "msrle",
294 "xanim",
295 "msvidc",
296 "fli",
297 "cinepak",
298 "qtrle",
299 "nuv",
300 "cyuv",
301 "qtsmc",
302 "ducktm1",
303 "roqvideo",
304 "qtrpza",
305 "mpng",
306 "ijpg",
307 "zlib",
308 "mpegpes",
309 "zrmjpeg",
310 "realvid",
311 "xvid",
312 "libdv",
313 NULL
315 char **drv=audioflag?audiodrv:videodrv;
316 int i;
318 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
320 return -1;
322 #endif
324 static int validate_codec(codecs_t *c, int type)
326 unsigned int i;
327 char *tmp_name = c->name;
329 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
330 /* NOTHING */;
332 if (i < strlen(tmp_name)) {
333 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_InvalidCodecName, c->name);
334 return 0;
337 if (!c->info)
338 c->info = strdup(c->name);
340 #if 0
341 if (c->fourcc[0] == 0xffffffff) {
342 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksFourcc, c->name);
343 return 0;
345 #endif
347 if (!c->drv) {
348 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksDriver, c->name);
349 return 0;
352 #if 0
353 #warning codec->driver == 4;... <- ezt nem kellene belehegeszteni...
354 #warning HOL VANNAK DEFINIALVA????????????
355 if (!c->dll && (c->driver == 4 ||
356 (c->driver == 2 && type == TYPE_VIDEO))) {
357 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsDLL, c->name);
358 return 0;
360 #warning guid.f1 lehet 0? honnan lehet tudni, hogy nem adtak meg?
361 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
363 if (type == TYPE_VIDEO)
364 if (c->outfmt[0] == 0xffffffff) {
365 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsOutfmt, c->name);
366 return 0;
368 #endif
369 return 1;
372 static int add_comment(char *s, char **d)
374 int pos;
376 if (!*d)
377 pos = 0;
378 else {
379 pos = strlen(*d);
380 (*d)[pos++] = '\n';
382 if (!(*d = (char *) realloc(*d, pos + strlen(s) + 1))) {
383 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantAllocateComment);
384 return 0;
386 strcpy(*d + pos, s);
387 return 1;
390 static short get_cpuflags(char *s)
392 static char *flagstr[] = {
393 "mmx",
394 "sse",
395 "3dnow",
396 NULL
398 int i;
399 short flags = 0;
401 do {
402 for (i = 0; flagstr[i]; i++)
403 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
404 break;
405 if (!flagstr[i])
406 goto err_out_parse_error;
407 flags |= 1<<i;
408 s += strlen(flagstr[i]);
409 } while (*(s++) == ',');
411 if (*(--s) != '\0')
412 goto err_out_parse_error;
414 return flags;
415 err_out_parse_error:
416 return 0;
419 static FILE *fp;
420 static int line_num = 0;
421 static char *line;
422 static char *token[MAX_NR_TOKEN];
423 static int read_nextline = 1;
425 static int get_token(int min, int max)
427 static int line_pos;
428 int i;
429 char c;
431 if (max >= MAX_NR_TOKEN) {
432 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN);
433 goto out_eof;
436 memset(token, 0x00, sizeof(*token) * max);
438 if (read_nextline) {
439 if (!fgets(line, MAX_LINE_LEN, fp))
440 goto out_eof;
441 line_pos = 0;
442 ++line_num;
443 read_nextline = 0;
445 for (i = 0; i < max; i++) {
446 while (isspace(line[line_pos]))
447 ++line_pos;
448 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
449 line[line_pos] == ';') {
450 read_nextline = 1;
451 if (i >= min)
452 goto out_ok;
453 goto out_eol;
455 token[i] = line + line_pos;
456 c = line[line_pos];
457 if (c == '"' || c == '\'') {
458 token[i]++;
459 while (line[++line_pos] != c && line[line_pos])
460 /* NOTHING */;
461 } else {
462 for (/* NOTHING */; !isspace(line[line_pos]) &&
463 line[line_pos]; line_pos++)
464 /* NOTHING */;
466 if (!line[line_pos]) {
467 read_nextline = 1;
468 if (i >= min - 1)
469 goto out_ok;
470 goto out_eol;
472 line[line_pos] = '\0';
473 line_pos++;
475 out_ok:
476 return i;
477 out_eof:
478 read_nextline = 1;
479 return RET_EOF;
480 out_eol:
481 return RET_EOL;
484 static codecs_t *video_codecs=NULL;
485 static codecs_t *audio_codecs=NULL;
486 static int nr_vcodecs = 0;
487 static int nr_acodecs = 0;
489 int parse_codec_cfg(char *cfgfile)
491 codecs_t *codec = NULL; // current codec
492 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
493 char *endptr; // strtoul()...
494 int *nr_codecsp;
495 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
496 int tmp, i;
498 // in case we call it a second time
499 codecs_uninit_free();
501 nr_vcodecs = 0;
502 nr_acodecs = 0;
504 if(cfgfile==NULL) {
505 #ifdef CODECS2HTML
506 return 0;
507 #else
508 video_codecs = builtin_video_codecs;
509 audio_codecs = builtin_audio_codecs;
510 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
511 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
512 return 1;
513 #endif
516 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_ReadingFile, cfgfile);
518 if ((fp = fopen(cfgfile, "r")) == NULL) {
519 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_CantOpenFileError, cfgfile, strerror(errno));
520 return 0;
523 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
524 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantGetMemoryForLine, strerror(errno));
525 return 0;
527 read_nextline = 1;
530 * this only catches release lines at the start of
531 * codecs.conf, before audiocodecs and videocodecs.
533 while ((tmp = get_token(1, 1)) == RET_EOL)
534 /* NOTHING */;
535 if (tmp == RET_EOF)
536 goto out;
537 if (!strcmp(token[0], "release")) {
538 if (get_token(1, 2) < 0)
539 goto err_out_parse_error;
540 tmp = atoi(token[0]);
541 if (tmp < CODEC_CFG_MIN)
542 goto err_out_release_num;
543 while ((tmp = get_token(1, 1)) == RET_EOL)
544 /* NOTHING */;
545 if (tmp == RET_EOF)
546 goto out;
547 } else
548 goto err_out_release_num;
551 * check if the next block starts with 'audiocodec' or
552 * with 'videocodec'
554 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
555 goto loop_enter;
556 goto err_out_parse_error;
558 while ((tmp = get_token(1, 1)) != RET_EOF) {
559 if (tmp == RET_EOL)
560 continue;
561 if (!strcmp(token[0], "audiocodec") ||
562 !strcmp(token[0], "videocodec")) {
563 if (!validate_codec(codec, codec_type))
564 goto err_out_not_valid;
565 loop_enter:
566 if (*token[0] == 'v') {
567 codec_type = TYPE_VIDEO;
568 nr_codecsp = &nr_vcodecs;
569 codecsp = &video_codecs;
570 } else if (*token[0] == 'a') {
571 codec_type = TYPE_AUDIO;
572 nr_codecsp = &nr_acodecs;
573 codecsp = &audio_codecs;
574 #ifdef DEBUG
575 } else {
576 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
577 goto err_out;
578 #endif
580 if (!(*codecsp = (codecs_t *) realloc(*codecsp,
581 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
582 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantReallocCodecsp, strerror(errno));
583 goto err_out;
585 codec=*codecsp + *nr_codecsp;
586 ++*nr_codecsp;
587 memset(codec,0,sizeof(codecs_t));
588 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
589 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
590 memset(codec->infmt, 0xff, sizeof(codec->infmt));
592 if (get_token(1, 1) < 0)
593 goto err_out_parse_error;
594 for (i = 0; i < *nr_codecsp - 1; i++) {
595 if(( (*codecsp)[i].name!=NULL) &&
596 (!strcmp(token[0], (*codecsp)[i].name)) ) {
597 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNameNotUnique, token[0]);
598 goto err_out_print_linenum;
601 if (!(codec->name = strdup(token[0]))) {
602 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupName, strerror(errno));
603 goto err_out;
605 } else if (!strcmp(token[0], "info")) {
606 if (codec->info || get_token(1, 1) < 0)
607 goto err_out_parse_error;
608 if (!(codec->info = strdup(token[0]))) {
609 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupInfo, strerror(errno));
610 goto err_out;
612 } else if (!strcmp(token[0], "comment")) {
613 if (get_token(1, 1) < 0)
614 goto err_out_parse_error;
615 add_comment(token[0], &codec->comment);
616 } else if (!strcmp(token[0], "fourcc")) {
617 if (get_token(1, 2) < 0)
618 goto err_out_parse_error;
619 if (!add_to_fourcc(token[0], token[1],
620 codec->fourcc,
621 codec->fourccmap))
622 goto err_out_print_linenum;
623 } else if (!strcmp(token[0], "format")) {
624 if (get_token(1, 2) < 0)
625 goto err_out_parse_error;
626 if (!add_to_format(token[0], token[1],
627 codec->fourcc,codec->fourccmap))
628 goto err_out_print_linenum;
629 } else if (!strcmp(token[0], "driver")) {
630 if (get_token(1, 1) < 0)
631 goto err_out_parse_error;
632 if (!(codec->drv = strdup(token[0]))) {
633 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDriver, strerror(errno));
634 goto err_out;
636 } else if (!strcmp(token[0], "dll")) {
637 if (get_token(1, 1) < 0)
638 goto err_out_parse_error;
639 if (!(codec->dll = strdup(token[0]))) {
640 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDLL, strerror(errno));
641 goto err_out;
643 } else if (!strcmp(token[0], "guid")) {
644 if (get_token(11, 11) < 0)
645 goto err_out_parse_error;
646 codec->guid.f1=strtoul(token[0],&endptr,0);
647 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
648 *endptr != '\0')
649 goto err_out_parse_error;
650 codec->guid.f2=strtoul(token[1],&endptr,0);
651 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
652 *endptr != '\0')
653 goto err_out_parse_error;
654 codec->guid.f3=strtoul(token[2],&endptr,0);
655 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
656 *endptr != '\0')
657 goto err_out_parse_error;
658 for (i = 0; i < 8; i++) {
659 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
660 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
661 *endptr != '\0')
662 goto err_out_parse_error;
664 } else if (!strcmp(token[0], "out")) {
665 if (get_token(1, 2) < 0)
666 goto err_out_parse_error;
667 if (!add_to_inout(token[0], token[1], codec->outfmt,
668 codec->outflags))
669 goto err_out_print_linenum;
670 } else if (!strcmp(token[0], "in")) {
671 if (get_token(1, 2) < 0)
672 goto err_out_parse_error;
673 if (!add_to_inout(token[0], token[1], codec->infmt,
674 codec->inflags))
675 goto err_out_print_linenum;
676 } else if (!strcmp(token[0], "flags")) {
677 if (get_token(1, 1) < 0)
678 goto err_out_parse_error;
679 if (!strcmp(token[0], "seekable"))
680 codec->flags |= CODECS_FLAG_SEEKABLE;
681 else
682 if (!strcmp(token[0], "align16"))
683 codec->flags |= CODECS_FLAG_ALIGN16;
684 else
685 goto err_out_parse_error;
686 } else if (!strcmp(token[0], "status")) {
687 if (get_token(1, 1) < 0)
688 goto err_out_parse_error;
689 if (!strcasecmp(token[0], "working"))
690 codec->status = CODECS_STATUS_WORKING;
691 else if (!strcasecmp(token[0], "crashing"))
692 codec->status = CODECS_STATUS_NOT_WORKING;
693 else if (!strcasecmp(token[0], "untested"))
694 codec->status = CODECS_STATUS_UNTESTED;
695 else if (!strcasecmp(token[0], "buggy"))
696 codec->status = CODECS_STATUS_PROBLEMS;
697 else
698 goto err_out_parse_error;
699 } else if (!strcmp(token[0], "cpuflags")) {
700 if (get_token(1, 1) < 0)
701 goto err_out_parse_error;
702 if (!(codec->cpuflags = get_cpuflags(token[0])))
703 goto err_out_parse_error;
704 } else
705 goto err_out_parse_error;
707 if (!validate_codec(codec, codec_type))
708 goto err_out_not_valid;
709 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_AudioVideoCodecTotals, nr_acodecs, nr_vcodecs);
710 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
711 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
712 out:
713 free(line);
714 line=NULL;
715 fclose(fp);
716 return 1;
718 err_out_parse_error:
719 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
720 err_out_print_linenum:
721 PRINT_LINENUM;
722 err_out:
723 codecs_uninit_free();
725 free(line);
726 line=NULL;
727 line_num = 0;
728 fclose(fp);
729 return 0;
730 err_out_not_valid:
731 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecDefinitionIncorrect);
732 goto err_out_print_linenum;
733 err_out_release_num:
734 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_OutdatedCodecsConf);
735 goto err_out_print_linenum;
738 static void codecs_free(codecs_t* codecs,int count) {
739 int i;
740 for ( i = 0; i < count; i++)
741 if ( (codecs[i]).name ) {
742 if( (codecs[i]).name )
743 free((codecs[i]).name);
744 if( (codecs[i]).info )
745 free((codecs[i]).info);
746 if( (codecs[i]).comment )
747 free((codecs[i]).comment);
748 if( (codecs[i]).dll )
749 free((codecs[i]).dll);
750 if( (codecs[i]).drv )
751 free((codecs[i]).drv);
753 if (codecs)
754 free(codecs);
757 void codecs_uninit_free(void) {
758 if (video_codecs)
759 codecs_free(video_codecs,nr_vcodecs);
760 video_codecs=NULL;
761 if (audio_codecs)
762 codecs_free(audio_codecs,nr_acodecs);
763 audio_codecs=NULL;
766 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
767 codecs_t *start, int force)
769 return find_codec(fourcc, fourccmap, start, 1, force);
772 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
773 codecs_t *start, int force)
775 return find_codec(fourcc, fourccmap, start, 0, force);
778 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
779 codecs_t *start, int audioflag, int force)
781 int i, j;
782 codecs_t *c;
784 #if 0
785 if (start) {
786 for (/* NOTHING */; start->name; start++) {
787 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
788 if (start->fourcc[j] == fourcc) {
789 if (fourccmap)
790 *fourccmap = start->fourccmap[j];
791 return start;
795 } else
796 #endif
798 if (audioflag) {
799 i = nr_acodecs;
800 c = audio_codecs;
801 } else {
802 i = nr_vcodecs;
803 c = video_codecs;
805 if(!i) return NULL;
806 for (/* NOTHING */; i--; c++) {
807 if(start && c<=start) continue;
808 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
809 // FIXME: do NOT hardwire 'null' name here:
810 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
811 if (fourccmap)
812 *fourccmap = c->fourccmap[j];
813 return c;
816 if (force) return c;
819 return NULL;
822 void select_codec(char* codecname,int audioflag){
823 int i;
824 codecs_t *c;
825 // printf("select_codec('%s')\n",codecname);
826 if (audioflag) {
827 i = nr_acodecs;
828 c = audio_codecs;
829 } else {
830 i = nr_vcodecs;
831 c = video_codecs;
833 if(i)
834 for (/* NOTHING */; i--; c++)
835 if(!strcmp(c->name,codecname))
836 c->flags|=CODECS_FLAG_SELECTED;
839 void codecs_reset_selection(int audioflag){
840 int i;
841 codecs_t *c;
842 if (audioflag) {
843 i = nr_acodecs;
844 c = audio_codecs;
845 } else {
846 i = nr_vcodecs;
847 c = video_codecs;
849 if(i)
850 for (/* NOTHING */; i--; c++)
851 c->flags&=(~CODECS_FLAG_SELECTED);
854 void list_codecs(int audioflag){
855 int i;
856 codecs_t *c;
858 if (audioflag) {
859 i = nr_acodecs;
860 c = audio_codecs;
861 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
862 } else {
863 i = nr_vcodecs;
864 c = video_codecs;
865 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
867 if(!i) return;
868 for (/* NOTHING */; i--; c++) {
869 char* s="unknown ";
870 switch(c->status){
871 case CODECS_STATUS_WORKING: s="working ";break;
872 case CODECS_STATUS_PROBLEMS: s="problems";break;
873 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
874 case CODECS_STATUS_UNTESTED: s="untested";break;
876 if(c->dll)
877 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
878 else
879 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
887 #ifdef CODECS2HTML
889 * Fake out GUI references when building the codecs2html utility.
891 #ifdef HAVE_NEW_GUI
892 void gtkMessageBox( int type,char * str ) { return; }
893 int use_gui = 0;
894 #endif
896 void wrapline(FILE *f2,char *s){
897 int c;
898 if(!s){
899 fprintf(f2,"-");
900 return;
902 while((c=*s++)){
903 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
907 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
908 int c,d;
909 while((c=fgetc(f1))>=0){
910 if(c!='%'){
911 fputc(c,f2);
912 continue;
914 d=fgetc(f1);
916 switch(d){
917 case '.':
918 return; // end of section
919 case 'n':
920 wrapline(f2,codec->name); break;
921 case 'i':
922 wrapline(f2,codec->info); break;
923 case 'c':
924 wrapline(f2,codec->comment); break;
925 case 'd':
926 wrapline(f2,codec->dll); break;
927 case 'D':
928 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
929 case 'F':
930 for(d=0;d<CODECS_MAX_FOURCC;d++)
931 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
932 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
933 break;
934 case 'f':
935 for(d=0;d<CODECS_MAX_FOURCC;d++)
936 if(codec->fourcc[d]!=0xFFFFFFFF)
937 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
938 break;
939 case 'Y':
940 for(d=0;d<CODECS_MAX_OUTFMT;d++)
941 if(codec->outfmt[d]!=0xFFFFFFFF){
942 for (c=0; fmt_table[c].name; c++)
943 if(fmt_table[c].num==codec->outfmt[d]) break;
944 if(fmt_table[c].name)
945 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
947 break;
948 default:
949 fputc(c,f2);
950 fputc(d,f2);
956 void skiphtml(FILE *f1){
957 int c,d;
958 while((c=fgetc(f1))>=0){
959 if(c!='%'){
960 continue;
962 d=fgetc(f1);
963 if(d=='.') return; // end of section
967 static void print_int_array(const int* a, int size)
969 printf("{ ");
970 while (size--)
971 if(abs(*a)<256)
972 printf("%d%s", *a++, size?", ":"");
973 else
974 printf("0x%X%s", *a++, size?", ":"");
975 printf(" }");
978 static void print_char_array(const unsigned char* a, int size)
980 printf("{ ");
981 while (size--)
982 if((*a)<10)
983 printf("%d%s", *a++, size?", ":"");
984 else
985 printf("0x%02x%s", *a++, size?", ":"");
986 printf(" }");
989 static void print_string(const char* s)
991 if (!s) printf("NULL");
992 else printf("\"%s\"", s);
995 int main(int argc, char* argv[])
997 codecs_t *cl;
998 FILE *f1;
999 FILE *f2;
1000 int c,d,i;
1001 int pos;
1002 int section=-1;
1003 int nr_codecs;
1004 int win32=-1;
1005 int dshow=-1;
1006 int win32ex=-1;
1009 * Take path to codecs.conf from command line, or fall back on
1010 * etc/codecs.conf
1012 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1013 exit(1);
1015 if (argc > 1) {
1016 int i, j;
1017 const char* nm[2];
1018 codecs_t* cod[2];
1019 int nr[2];
1021 nm[0] = "builtin_video_codecs";
1022 cod[0] = video_codecs;
1023 nr[0] = nr_vcodecs;
1025 nm[1] = "builtin_audio_codecs";
1026 cod[1] = audio_codecs;
1027 nr[1] = nr_acodecs;
1029 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1031 for (i=0; i<2; i++) {
1032 printf("codecs_t %s[] = {\n", nm[i]);
1033 for (j = 0; j < nr[i]; j++) {
1034 printf("{");
1036 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1037 printf(", /* fourcc */\n");
1039 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1040 printf(", /* fourccmap */\n");
1042 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1043 printf(", /* outfmt */\n");
1045 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1046 printf(", /* outflags */\n");
1048 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1049 printf(", /* infmt */\n");
1051 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1052 printf(", /* inflags */\n");
1054 print_string(cod[i][j].name); printf(", /* name */\n");
1055 print_string(cod[i][j].info); printf(", /* info */\n");
1056 print_string(cod[i][j].comment); printf(", /* comment */\n");
1057 print_string(cod[i][j].dll); printf(", /* dll */\n");
1058 print_string(cod[i][j].drv); printf(", /* drv */\n");
1060 printf("{ 0x%08lx, %hu, %hu,",
1061 cod[i][j].guid.f1,
1062 cod[i][j].guid.f2,
1063 cod[i][j].guid.f3);
1064 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1065 printf(" }, /* GUID */\n");
1066 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1067 cod[i][j].flags,
1068 cod[i][j].status,
1069 cod[i][j].cpuflags);
1070 if (j < nr[i]) printf(",\n");
1072 printf("};\n\n");
1074 exit(0);
1077 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1078 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1080 while((c=fgetc(f1))>=0){
1081 if(c!='%'){
1082 fputc(c,f2);
1083 continue;
1085 d=fgetc(f1);
1086 if(d>='0' && d<='9'){
1087 // begin section
1088 section=d-'0';
1089 //printf("BEGIN %d\n",section);
1090 if(section>=5){
1091 // audio
1092 cl = audio_codecs;
1093 nr_codecs = nr_acodecs;
1094 dshow=7;win32=4;
1095 } else {
1096 // video
1097 cl = video_codecs;
1098 nr_codecs = nr_vcodecs;
1099 dshow=4;win32=2;win32ex=6;
1101 pos=ftell(f1);
1102 for(i=0;i<nr_codecs;i++){
1103 fseek(f1,pos,SEEK_SET);
1104 switch(section){
1105 case 0:
1106 case 5:
1107 if(cl[i].status==CODECS_STATUS_WORKING)
1108 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1109 parsehtml(f1,f2,&cl[i],section,dshow);
1110 break;
1111 #if 0
1112 case 1:
1113 case 6:
1114 if(cl[i].status==CODECS_STATUS_WORKING)
1115 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1116 parsehtml(f1,f2,&cl[i],section,dshow);
1117 break;
1118 #endif
1119 case 2:
1120 case 7:
1121 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1122 parsehtml(f1,f2,&cl[i],section,dshow);
1123 break;
1124 case 3:
1125 case 8:
1126 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1127 parsehtml(f1,f2,&cl[i],section,dshow);
1128 break;
1129 case 4:
1130 case 9:
1131 if(cl[i].status==CODECS_STATUS_UNTESTED)
1132 parsehtml(f1,f2,&cl[i],section,dshow);
1133 break;
1134 default:
1135 printf("Warning! unimplemented section: %d\n",section);
1138 fseek(f1,pos,SEEK_SET);
1139 skiphtml(f1);
1140 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1142 continue;
1144 fputc(c,f2);
1145 fputc(d,f2);
1148 fclose(f2);
1149 fclose(f1);
1150 return 0;
1153 #endif
1155 #ifdef TESTING
1156 int main(void)
1158 codecs_t *c;
1159 int i,j, nr_codecs, state;
1161 if (!(parse_codec_cfg("etc/codecs.conf")))
1162 return 0;
1163 if (!video_codecs)
1164 printf("no videoconfig.\n");
1165 if (!audio_codecs)
1166 printf("no audioconfig.\n");
1168 printf("videocodecs:\n");
1169 c = video_codecs;
1170 nr_codecs = nr_vcodecs;
1171 state = 0;
1172 next:
1173 if (c) {
1174 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1175 nr_codecs);
1176 for(i=0;i<nr_codecs;i++, c++){
1177 printf("\n============== %scodec %02d ===============\n",
1178 state==0?"video":"audio",i);
1179 printf("name='%s'\n",c->name);
1180 printf("info='%s'\n",c->info);
1181 printf("comment='%s'\n",c->comment);
1182 printf("dll='%s'\n",c->dll);
1183 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1184 c->flags, c->driver, c->status, c->cpuflags);
1186 for(j=0;j<CODECS_MAX_FOURCC;j++){
1187 if(c->fourcc[j]!=0xFFFFFFFF){
1188 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1192 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1193 if(c->outfmt[j]!=0xFFFFFFFF){
1194 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1198 for(j=0;j<CODECS_MAX_INFMT;j++){
1199 if(c->infmt[j]!=0xFFFFFFFF){
1200 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1204 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1205 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1206 printf("\n");
1211 if (!state) {
1212 printf("audiocodecs:\n");
1213 c = audio_codecs;
1214 nr_codecs = nr_acodecs;
1215 state = 1;
1216 goto next;
1218 return 0;
1221 #endif