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