10l to Nico for this copy&paste bug
[mplayer/glamo.git] / codec-cfg.c
blob66c721013e9e3e50ba1f9b07ecd2822b70b3faaf
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 -Iloader/ -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"
30 #include "help_mp.h"
32 // for mmioFOURCC:
33 #include "libmpdemux/aviheader.h"
35 #include "libmpcodecs/img_format.h"
36 #include "codec-cfg.h"
38 #ifndef CODECS2HTML
39 #include "codecs.conf.h"
40 #endif
42 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
44 #define MAX_NR_TOKEN 16
46 #define MAX_LINE_LEN 1000
48 #define RET_EOF -1
49 #define RET_EOL -2
51 #define TYPE_VIDEO 0
52 #define TYPE_AUDIO 1
54 char * codecs_file = NULL;
56 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
57 unsigned int *map)
59 int i, j, freeslots;
60 unsigned int tmp;
62 /* find first unused slot */
63 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
64 /* NOTHING */;
65 freeslots = CODECS_MAX_FOURCC - i;
66 if (!freeslots)
67 goto err_out_too_many;
69 do {
70 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
71 for (j = 0; j < i; j++)
72 if (tmp == fourcc[j])
73 goto err_out_duplicated;
74 fourcc[i] = tmp;
75 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
76 s += 4;
77 i++;
78 } while ((*(s++) == ',') && --freeslots);
80 if (!freeslots)
81 goto err_out_too_many;
82 if (*(--s) != '\0')
83 goto err_out_parse_error;
84 return 1;
85 err_out_duplicated:
86 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFourcc);
87 return 0;
88 err_out_too_many:
89 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
90 return 0;
91 err_out_parse_error:
92 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
93 return 0;
96 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
98 int i, j;
99 char *endptr;
101 /* find first unused slot */
102 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
103 /* NOTHING */;
104 if (i == CODECS_MAX_FOURCC) {
105 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
106 return 0;
109 fourcc[i]=strtoul(s,&endptr,0);
110 if (*endptr != '\0') {
111 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDNotNumber);
112 return 0;
115 if(alias){
116 fourccmap[i]=strtoul(alias,&endptr,0);
117 if (*endptr != '\0') {
118 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDAliasNotNumber);
119 return 0;
121 } else
122 fourccmap[i]=fourcc[i];
124 for (j = 0; j < i; j++)
125 if (fourcc[j] == fourcc[i]) {
126 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFID);
127 return 0;
130 return 1;
133 static struct {
134 const char *name;
135 const unsigned int num;
136 } fmt_table[] = {
137 {"YV12", IMGFMT_YV12},
138 {"I420", IMGFMT_I420},
139 {"IYUV", IMGFMT_IYUV},
140 {"NV12", IMGFMT_NV12},
141 {"NV21", IMGFMT_NV21},
142 {"YVU9", IMGFMT_YVU9},
143 {"IF09", IMGFMT_IF09},
144 {"444P", IMGFMT_444P},
145 {"422P", IMGFMT_422P},
146 {"411P", IMGFMT_411P},
147 {"Y800", IMGFMT_Y800},
148 {"Y8", IMGFMT_Y8},
150 {"YUY2", IMGFMT_YUY2},
151 {"UYVY", IMGFMT_UYVY},
152 {"YVYU", IMGFMT_YVYU},
154 {"RGB4", IMGFMT_RGB|4},
155 {"RGB8", IMGFMT_RGB|8},
156 {"RGB15", IMGFMT_RGB|15},
157 {"RGB16", IMGFMT_RGB|16},
158 {"RGB24", IMGFMT_RGB|24},
159 {"RGB32", IMGFMT_RGB|32},
160 {"BGR4", IMGFMT_BGR|4},
161 {"BGR8", IMGFMT_BGR|8},
162 {"BGR15", IMGFMT_BGR|15},
163 {"BGR16", IMGFMT_BGR|16},
164 {"BGR24", IMGFMT_BGR|24},
165 {"BGR32", IMGFMT_BGR|32},
166 {"RGB1", IMGFMT_RGB|1},
167 {"BGR1", IMGFMT_BGR|1},
169 {"MPES", IMGFMT_MPEGPES},
170 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
171 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
172 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
174 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
175 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
177 {NULL, 0}
181 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
182 unsigned char *outflags)
185 static char *flagstr[] = {
186 "flip",
187 "noflip",
188 "yuvhack",
189 "query",
190 "static",
191 NULL
194 int i, j, freeslots;
195 unsigned char flags;
197 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
198 /* NOTHING */;
199 freeslots = CODECS_MAX_OUTFMT - i;
200 if (!freeslots)
201 goto err_out_too_many;
203 flags = 0;
204 if(sflags) {
205 do {
206 for (j = 0; flagstr[j] != NULL; j++)
207 if (!strncmp(sflags, flagstr[j],
208 strlen(flagstr[j])))
209 break;
210 if (flagstr[j] == NULL)
211 goto err_out_parse_error;
212 flags|=(1<<j);
213 sflags+=strlen(flagstr[j]);
214 } while (*(sflags++) == ',');
216 if (*(--sflags) != '\0')
217 goto err_out_parse_error;
220 do {
221 for (j = 0; fmt_table[j].name != NULL; j++)
222 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
223 break;
224 if (fmt_table[j].name == NULL)
225 goto err_out_parse_error;
226 outfmt[i] = fmt_table[j].num;
227 outflags[i] = flags;
228 ++i;
229 sfmt+=strlen(fmt_table[j].name);
230 } while ((*(sfmt++) == ',') && --freeslots);
232 if (!freeslots)
233 goto err_out_too_many;
235 if (*(--sfmt) != '\0')
236 goto err_out_parse_error;
238 return 1;
239 err_out_too_many:
240 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyOut);
241 return 0;
242 err_out_parse_error:
243 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
244 return 0;
247 #if 0
248 static short get_driver(char *s,int audioflag)
250 static char *audiodrv[] = {
251 "null",
252 "mp3lib",
253 "pcm",
254 "libac3",
255 "acm",
256 "alaw",
257 "msgsm",
258 "dshow",
259 "dvdpcm",
260 "hwac3",
261 "libvorbis",
262 "ffmpeg",
263 "libmad",
264 "msadpcm",
265 "liba52",
266 "g72x",
267 "imaadpcm",
268 "dk4adpcm",
269 "dk3adpcm",
270 "roqaudio",
271 "faad",
272 "realaud",
273 "libdv",
274 NULL
276 static char *videodrv[] = {
277 "null",
278 "libmpeg2",
279 "vfw",
280 "odivx",
281 "dshow",
282 "ffmpeg",
283 "vfwex",
284 "divx4",
285 "raw",
286 "msrle",
287 "xanim",
288 "msvidc",
289 "fli",
290 "cinepak",
291 "qtrle",
292 "nuv",
293 "cyuv",
294 "qtsmc",
295 "ducktm1",
296 "roqvideo",
297 "qtrpza",
298 "mpng",
299 "ijpg",
300 "zlib",
301 "mpegpes",
302 "zrmjpeg",
303 "realvid",
304 "xvid",
305 "libdv",
306 NULL
308 char **drv=audioflag?audiodrv:videodrv;
309 int i;
311 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
313 return -1;
315 #endif
317 static int validate_codec(codecs_t *c, int type)
319 unsigned int i;
320 char *tmp_name = c->name;
322 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
323 /* NOTHING */;
325 if (i < strlen(tmp_name)) {
326 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_InvalidCodecName, c->name);
327 return 0;
330 if (!c->info)
331 c->info = strdup(c->name);
333 #if 0
334 if (c->fourcc[0] == 0xffffffff) {
335 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksFourcc, c->name);
336 return 0;
338 #endif
340 if (!c->drv) {
341 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksDriver, c->name);
342 return 0;
345 #if 0
346 #warning codec->driver == 4;... <- ezt nem kellene belehegeszteni...
347 #warning HOL VANNAK DEFINIALVA????????????
348 if (!c->dll && (c->driver == 4 ||
349 (c->driver == 2 && type == TYPE_VIDEO))) {
350 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsDLL, c->name);
351 return 0;
353 #warning guid.f1 lehet 0? honnan lehet tudni, hogy nem adtak meg?
354 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
356 if (type == TYPE_VIDEO)
357 if (c->outfmt[0] == 0xffffffff) {
358 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsOutfmt, c->name);
359 return 0;
361 #endif
362 return 1;
365 static int add_comment(char *s, char **d)
367 int pos;
369 if (!*d)
370 pos = 0;
371 else {
372 pos = strlen(*d);
373 (*d)[pos++] = '\n';
375 if (!(*d = (char *) realloc(*d, pos + strlen(s) + 1))) {
376 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantAllocateComment);
377 return 0;
379 strcpy(*d + pos, s);
380 return 1;
383 static short get_cpuflags(char *s)
385 static char *flagstr[] = {
386 "mmx",
387 "sse",
388 "3dnow",
389 NULL
391 int i;
392 short flags = 0;
394 do {
395 for (i = 0; flagstr[i]; i++)
396 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
397 break;
398 if (!flagstr[i])
399 goto err_out_parse_error;
400 flags |= 1<<i;
401 s += strlen(flagstr[i]);
402 } while (*(s++) == ',');
404 if (*(--s) != '\0')
405 goto err_out_parse_error;
407 return flags;
408 err_out_parse_error:
409 return 0;
412 static FILE *fp;
413 static int line_num = 0;
414 static char *line;
415 static char *token[MAX_NR_TOKEN];
416 static int read_nextline = 1;
418 static int get_token(int min, int max)
420 static int line_pos;
421 int i;
422 char c;
424 if (max >= MAX_NR_TOKEN) {
425 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN);
426 goto out_eof;
429 memset(token, 0x00, sizeof(*token) * max);
431 if (read_nextline) {
432 if (!fgets(line, MAX_LINE_LEN, fp))
433 goto out_eof;
434 line_pos = 0;
435 ++line_num;
436 read_nextline = 0;
438 for (i = 0; i < max; i++) {
439 while (isspace(line[line_pos]))
440 ++line_pos;
441 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
442 line[line_pos] == ';') {
443 read_nextline = 1;
444 if (i >= min)
445 goto out_ok;
446 goto out_eol;
448 token[i] = line + line_pos;
449 c = line[line_pos];
450 if (c == '"' || c == '\'') {
451 token[i]++;
452 while (line[++line_pos] != c && line[line_pos])
453 /* NOTHING */;
454 } else {
455 for (/* NOTHING */; !isspace(line[line_pos]) &&
456 line[line_pos]; line_pos++)
457 /* NOTHING */;
459 if (!line[line_pos]) {
460 read_nextline = 1;
461 if (i >= min - 1)
462 goto out_ok;
463 goto out_eol;
465 line[line_pos] = '\0';
466 line_pos++;
468 out_ok:
469 return i;
470 out_eof:
471 read_nextline = 1;
472 return RET_EOF;
473 out_eol:
474 return RET_EOL;
477 static codecs_t *video_codecs=NULL;
478 static codecs_t *audio_codecs=NULL;
479 static int nr_vcodecs = 0;
480 static int nr_acodecs = 0;
482 int parse_codec_cfg(char *cfgfile)
484 codecs_t *codec = NULL; // current codec
485 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
486 char *endptr; // strtoul()...
487 int *nr_codecsp;
488 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
489 int tmp, i;
491 // in case we call it a second time
492 codecs_uninit_free();
494 nr_vcodecs = 0;
495 nr_acodecs = 0;
497 if(cfgfile==NULL) {
498 #ifdef CODECS2HTML
499 return 0;
500 #else
501 video_codecs = builtin_video_codecs;
502 audio_codecs = builtin_audio_codecs;
503 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
504 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
505 return 1;
506 #endif
509 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_ReadingFile, cfgfile);
511 if ((fp = fopen(cfgfile, "r")) == NULL) {
512 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_CantOpenFileError, cfgfile, strerror(errno));
513 return 0;
516 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
517 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantGetMemoryForLine, strerror(errno));
518 return 0;
520 read_nextline = 1;
523 * this only catches release lines at the start of
524 * codecs.conf, before audiocodecs and videocodecs.
526 while ((tmp = get_token(1, 1)) == RET_EOL)
527 /* NOTHING */;
528 if (tmp == RET_EOF)
529 goto out;
530 if (!strcmp(token[0], "release")) {
531 if (get_token(1, 2) < 0)
532 goto err_out_parse_error;
533 tmp = atoi(token[0]);
534 if (tmp < CODEC_CFG_MIN)
535 goto err_out_release_num;
536 while ((tmp = get_token(1, 1)) == RET_EOL)
537 /* NOTHING */;
538 if (tmp == RET_EOF)
539 goto out;
540 } else
541 goto err_out_release_num;
544 * check if the next block starts with 'audiocodec' or
545 * with 'videocodec'
547 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
548 goto loop_enter;
549 goto err_out_parse_error;
551 while ((tmp = get_token(1, 1)) != RET_EOF) {
552 if (tmp == RET_EOL)
553 continue;
554 if (!strcmp(token[0], "audiocodec") ||
555 !strcmp(token[0], "videocodec")) {
556 if (!validate_codec(codec, codec_type))
557 goto err_out_not_valid;
558 loop_enter:
559 if (*token[0] == 'v') {
560 codec_type = TYPE_VIDEO;
561 nr_codecsp = &nr_vcodecs;
562 codecsp = &video_codecs;
563 } else if (*token[0] == 'a') {
564 codec_type = TYPE_AUDIO;
565 nr_codecsp = &nr_acodecs;
566 codecsp = &audio_codecs;
567 #ifdef DEBUG
568 } else {
569 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
570 goto err_out;
571 #endif
573 if (!(*codecsp = (codecs_t *) realloc(*codecsp,
574 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
575 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantReallocCodecsp, strerror(errno));
576 goto err_out;
578 codec=*codecsp + *nr_codecsp;
579 ++*nr_codecsp;
580 memset(codec,0,sizeof(codecs_t));
581 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
582 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
583 memset(codec->infmt, 0xff, sizeof(codec->infmt));
585 if (get_token(1, 1) < 0)
586 goto err_out_parse_error;
587 for (i = 0; i < *nr_codecsp - 1; i++) {
588 if(( (*codecsp)[i].name!=NULL) &&
589 (!strcmp(token[0], (*codecsp)[i].name)) ) {
590 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNameNotUnique, token[0]);
591 goto err_out_print_linenum;
594 if (!(codec->name = strdup(token[0]))) {
595 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupName, strerror(errno));
596 goto err_out;
598 } else if (!strcmp(token[0], "info")) {
599 if (codec->info || get_token(1, 1) < 0)
600 goto err_out_parse_error;
601 if (!(codec->info = strdup(token[0]))) {
602 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupInfo, strerror(errno));
603 goto err_out;
605 } else if (!strcmp(token[0], "comment")) {
606 if (get_token(1, 1) < 0)
607 goto err_out_parse_error;
608 add_comment(token[0], &codec->comment);
609 } else if (!strcmp(token[0], "fourcc")) {
610 if (get_token(1, 2) < 0)
611 goto err_out_parse_error;
612 if (!add_to_fourcc(token[0], token[1],
613 codec->fourcc,
614 codec->fourccmap))
615 goto err_out_print_linenum;
616 } else if (!strcmp(token[0], "format")) {
617 if (get_token(1, 2) < 0)
618 goto err_out_parse_error;
619 if (!add_to_format(token[0], token[1],
620 codec->fourcc,codec->fourccmap))
621 goto err_out_print_linenum;
622 } else if (!strcmp(token[0], "driver")) {
623 if (get_token(1, 1) < 0)
624 goto err_out_parse_error;
625 if (!(codec->drv = strdup(token[0]))) {
626 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDriver, strerror(errno));
627 goto err_out;
629 } else if (!strcmp(token[0], "dll")) {
630 if (get_token(1, 1) < 0)
631 goto err_out_parse_error;
632 if (!(codec->dll = strdup(token[0]))) {
633 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDLL, strerror(errno));
634 goto err_out;
636 } else if (!strcmp(token[0], "guid")) {
637 if (get_token(11, 11) < 0)
638 goto err_out_parse_error;
639 codec->guid.f1=strtoul(token[0],&endptr,0);
640 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
641 *endptr != '\0')
642 goto err_out_parse_error;
643 codec->guid.f2=strtoul(token[1],&endptr,0);
644 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
645 *endptr != '\0')
646 goto err_out_parse_error;
647 codec->guid.f3=strtoul(token[2],&endptr,0);
648 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
649 *endptr != '\0')
650 goto err_out_parse_error;
651 for (i = 0; i < 8; i++) {
652 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
653 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
654 *endptr != '\0')
655 goto err_out_parse_error;
657 } else if (!strcmp(token[0], "out")) {
658 if (get_token(1, 2) < 0)
659 goto err_out_parse_error;
660 if (!add_to_inout(token[0], token[1], codec->outfmt,
661 codec->outflags))
662 goto err_out_print_linenum;
663 } else if (!strcmp(token[0], "in")) {
664 if (get_token(1, 2) < 0)
665 goto err_out_parse_error;
666 if (!add_to_inout(token[0], token[1], codec->infmt,
667 codec->inflags))
668 goto err_out_print_linenum;
669 } else if (!strcmp(token[0], "flags")) {
670 if (get_token(1, 1) < 0)
671 goto err_out_parse_error;
672 if (!strcmp(token[0], "seekable"))
673 codec->flags |= CODECS_FLAG_SEEKABLE;
674 else
675 if (!strcmp(token[0], "align16"))
676 codec->flags |= CODECS_FLAG_ALIGN16;
677 else
678 goto err_out_parse_error;
679 } else if (!strcmp(token[0], "status")) {
680 if (get_token(1, 1) < 0)
681 goto err_out_parse_error;
682 if (!strcasecmp(token[0], "working"))
683 codec->status = CODECS_STATUS_WORKING;
684 else if (!strcasecmp(token[0], "crashing"))
685 codec->status = CODECS_STATUS_NOT_WORKING;
686 else if (!strcasecmp(token[0], "untested"))
687 codec->status = CODECS_STATUS_UNTESTED;
688 else if (!strcasecmp(token[0], "buggy"))
689 codec->status = CODECS_STATUS_PROBLEMS;
690 else
691 goto err_out_parse_error;
692 } else if (!strcmp(token[0], "cpuflags")) {
693 if (get_token(1, 1) < 0)
694 goto err_out_parse_error;
695 if (!(codec->cpuflags = get_cpuflags(token[0])))
696 goto err_out_parse_error;
697 } else
698 goto err_out_parse_error;
700 if (!validate_codec(codec, codec_type))
701 goto err_out_not_valid;
702 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_AudioVideoCodecTotals, nr_acodecs, nr_vcodecs);
703 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
704 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
705 out:
706 free(line);
707 line=NULL;
708 fclose(fp);
709 return 1;
711 err_out_parse_error:
712 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
713 err_out_print_linenum:
714 PRINT_LINENUM;
715 err_out:
716 codecs_uninit_free();
718 free(line);
719 line=NULL;
720 line_num = 0;
721 fclose(fp);
722 return 0;
723 err_out_not_valid:
724 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecDefinitionIncorrect);
725 goto err_out_print_linenum;
726 err_out_release_num:
727 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_OutdatedCodecsConf);
728 goto err_out_print_linenum;
731 static void codecs_free(codecs_t* codecs,int count) {
732 int i;
733 for ( i = 0; i < count; i++)
734 if ( (codecs[i]).name ) {
735 if( (codecs[i]).name )
736 free((codecs[i]).name);
737 if( (codecs[i]).info )
738 free((codecs[i]).info);
739 if( (codecs[i]).comment )
740 free((codecs[i]).comment);
741 if( (codecs[i]).dll )
742 free((codecs[i]).dll);
743 if( (codecs[i]).drv )
744 free((codecs[i]).drv);
746 if (codecs)
747 free(codecs);
750 void codecs_uninit_free() {
751 if (video_codecs)
752 codecs_free(video_codecs,nr_vcodecs);
753 video_codecs=NULL;
754 if (audio_codecs)
755 codecs_free(audio_codecs,nr_acodecs);
756 audio_codecs=NULL;
759 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
760 codecs_t *start)
762 return find_codec(fourcc, fourccmap, start, 1);
765 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
766 codecs_t *start)
768 return find_codec(fourcc, fourccmap, start, 0);
771 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
772 codecs_t *start, int audioflag)
774 int i, j;
775 codecs_t *c;
777 #if 0
778 if (start) {
779 for (/* NOTHING */; start->name; start++) {
780 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
781 if (start->fourcc[j] == fourcc) {
782 if (fourccmap)
783 *fourccmap = start->fourccmap[j];
784 return start;
788 } else
789 #endif
791 if (audioflag) {
792 i = nr_acodecs;
793 c = audio_codecs;
794 } else {
795 i = nr_vcodecs;
796 c = video_codecs;
798 if(!i) return NULL;
799 for (/* NOTHING */; i--; c++) {
800 if(start && c<=start) continue;
801 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
802 // FIXME: do NOT hardwire 'null' name here:
803 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
804 if (fourccmap)
805 *fourccmap = c->fourccmap[j];
806 return c;
811 return NULL;
814 void select_codec(char* codecname,int audioflag){
815 int i;
816 codecs_t *c;
817 // printf("select_codec('%s')\n",codecname);
818 if (audioflag) {
819 i = nr_acodecs;
820 c = audio_codecs;
821 } else {
822 i = nr_vcodecs;
823 c = video_codecs;
825 if(i)
826 for (/* NOTHING */; i--; c++)
827 if(!strcmp(c->name,codecname))
828 c->flags|=CODECS_FLAG_SELECTED;
831 void codecs_reset_selection(int audioflag){
832 int i;
833 codecs_t *c;
834 if (audioflag) {
835 i = nr_acodecs;
836 c = audio_codecs;
837 } else {
838 i = nr_vcodecs;
839 c = video_codecs;
841 if(i)
842 for (/* NOTHING */; i--; c++)
843 c->flags&=(~CODECS_FLAG_SELECTED);
846 void list_codecs(int audioflag){
847 int i;
848 codecs_t *c;
850 if (audioflag) {
851 i = nr_acodecs;
852 c = audio_codecs;
853 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
854 } else {
855 i = nr_vcodecs;
856 c = video_codecs;
857 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
859 if(!i) return;
860 for (/* NOTHING */; i--; c++) {
861 char* s="unknown ";
862 switch(c->status){
863 case CODECS_STATUS_WORKING: s="working ";break;
864 case CODECS_STATUS_PROBLEMS: s="problems";break;
865 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
866 case CODECS_STATUS_UNTESTED: s="untested";break;
868 if(c->dll)
869 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
870 else
871 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
879 #ifdef CODECS2HTML
881 * Fake out GUI references when building the codecs2html utility.
883 #ifdef HAVE_NEW_GUI
884 void gtkMessageBox( int type,char * str ) { return; }
885 int use_gui = 0;
886 #endif
888 void wrapline(FILE *f2,char *s){
889 int c;
890 if(!s){
891 fprintf(f2,"-");
892 return;
894 while((c=*s++)){
895 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
899 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
900 int c,d;
901 while((c=fgetc(f1))>=0){
902 if(c!='%'){
903 fputc(c,f2);
904 continue;
906 d=fgetc(f1);
908 switch(d){
909 case '.':
910 return; // end of section
911 case 'n':
912 wrapline(f2,codec->name); break;
913 case 'i':
914 wrapline(f2,codec->info); break;
915 case 'c':
916 wrapline(f2,codec->comment); break;
917 case 'd':
918 wrapline(f2,codec->dll); break;
919 case 'D':
920 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
921 case 'F':
922 for(d=0;d<CODECS_MAX_FOURCC;d++)
923 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
924 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
925 break;
926 case 'f':
927 for(d=0;d<CODECS_MAX_FOURCC;d++)
928 if(codec->fourcc[d]!=0xFFFFFFFF)
929 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
930 break;
931 case 'Y':
932 for(d=0;d<CODECS_MAX_OUTFMT;d++)
933 if(codec->outfmt[d]!=0xFFFFFFFF){
934 for (c=0; fmt_table[c].name; c++)
935 if(fmt_table[c].num==codec->outfmt[d]) break;
936 if(fmt_table[c].name)
937 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
939 break;
940 default:
941 fputc(c,f2);
942 fputc(d,f2);
948 void skiphtml(FILE *f1){
949 int c,d;
950 while((c=fgetc(f1))>=0){
951 if(c!='%'){
952 continue;
954 d=fgetc(f1);
955 if(d=='.') return; // end of section
959 static void print_int_array(const int* a, int size)
961 printf("{ ");
962 while (size--)
963 if(abs(*a)<256)
964 printf("%d%s", *a++, size?", ":"");
965 else
966 printf("0x%X%s", *a++, size?", ":"");
967 printf(" }");
970 static void print_char_array(const unsigned char* a, int size)
972 printf("{ ");
973 while (size--)
974 if((*a)<10)
975 printf("%d%s", *a++, size?", ":"");
976 else
977 printf("0x%02x%s", *a++, size?", ":"");
978 printf(" }");
981 static void print_string(const char* s)
983 if (!s) printf("NULL");
984 else printf("\"%s\"", s);
987 int main(int argc, char* argv[])
989 codecs_t *cl;
990 FILE *f1;
991 FILE *f2;
992 int c,d,i;
993 int pos;
994 int section=-1;
995 int nr_codecs;
996 int win32=-1;
997 int dshow=-1;
998 int win32ex=-1;
1001 * Take path to codecs.conf from command line, or fall back on
1002 * etc/codecs.conf
1004 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1005 exit(1);
1007 if (argc > 1) {
1008 int i, j;
1009 const char* nm[2];
1010 codecs_t* cod[2];
1011 int nr[2];
1013 nm[0] = "builtin_video_codecs";
1014 cod[0] = video_codecs;
1015 nr[0] = nr_vcodecs;
1017 nm[1] = "builtin_audio_codecs";
1018 cod[1] = audio_codecs;
1019 nr[1] = nr_acodecs;
1021 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1023 for (i=0; i<2; i++) {
1024 printf("codecs_t %s[] = {\n", nm[i]);
1025 for (j = 0; j < nr[i]; j++) {
1026 printf("{");
1028 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1029 printf(", /* fourcc */\n");
1031 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1032 printf(", /* fourccmap */\n");
1034 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1035 printf(", /* outfmt */\n");
1037 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1038 printf(", /* outflags */\n");
1040 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1041 printf(", /* infmt */\n");
1043 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1044 printf(", /* inflags */\n");
1046 print_string(cod[i][j].name); printf(", /* name */\n");
1047 print_string(cod[i][j].info); printf(", /* info */\n");
1048 print_string(cod[i][j].comment); printf(", /* comment */\n");
1049 print_string(cod[i][j].dll); printf(", /* dll */\n");
1050 print_string(cod[i][j].drv); printf(", /* drv */\n");
1052 printf("{ 0x%08lx, %hu, %hu,",
1053 cod[i][j].guid.f1,
1054 cod[i][j].guid.f2,
1055 cod[i][j].guid.f3);
1056 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1057 printf(" }, /* GUID */\n");
1058 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1059 cod[i][j].flags,
1060 cod[i][j].status,
1061 cod[i][j].cpuflags);
1062 if (j < nr[i]) printf(",\n");
1064 printf("};\n\n");
1066 exit(0);
1069 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1070 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1072 while((c=fgetc(f1))>=0){
1073 if(c!='%'){
1074 fputc(c,f2);
1075 continue;
1077 d=fgetc(f1);
1078 if(d>='0' && d<='9'){
1079 // begin section
1080 section=d-'0';
1081 printf("BEGIN %d\n",section);
1082 if(section>=5){
1083 // audio
1084 cl = audio_codecs;
1085 nr_codecs = nr_acodecs;
1086 dshow=7;win32=4;
1087 } else {
1088 // video
1089 cl = video_codecs;
1090 nr_codecs = nr_vcodecs;
1091 dshow=4;win32=2;win32ex=6;
1093 pos=ftell(f1);
1094 for(i=0;i<nr_codecs;i++){
1095 fseek(f1,pos,SEEK_SET);
1096 switch(section){
1097 case 0:
1098 case 5:
1099 if(cl[i].status==CODECS_STATUS_WORKING)
1100 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1101 parsehtml(f1,f2,&cl[i],section,dshow);
1102 break;
1103 #if 0
1104 case 1:
1105 case 6:
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 #endif
1111 case 2:
1112 case 7:
1113 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1114 parsehtml(f1,f2,&cl[i],section,dshow);
1115 break;
1116 case 3:
1117 case 8:
1118 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1119 parsehtml(f1,f2,&cl[i],section,dshow);
1120 break;
1121 case 4:
1122 case 9:
1123 if(cl[i].status==CODECS_STATUS_UNTESTED)
1124 parsehtml(f1,f2,&cl[i],section,dshow);
1125 break;
1126 default:
1127 printf("Warning! unimplemented section: %d\n",section);
1130 fseek(f1,pos,SEEK_SET);
1131 skiphtml(f1);
1132 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1134 continue;
1136 fputc(c,f2);
1137 fputc(d,f2);
1140 fclose(f2);
1141 fclose(f1);
1142 return 0;
1145 #endif
1147 #ifdef TESTING
1148 int main(void)
1150 codecs_t *c;
1151 int i,j, nr_codecs, state;
1153 if (!(parse_codec_cfg("etc/codecs.conf")))
1154 return 0;
1155 if (!video_codecs)
1156 printf("no videoconfig.\n");
1157 if (!audio_codecs)
1158 printf("no audioconfig.\n");
1160 printf("videocodecs:\n");
1161 c = video_codecs;
1162 nr_codecs = nr_vcodecs;
1163 state = 0;
1164 next:
1165 if (c) {
1166 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1167 nr_codecs);
1168 for(i=0;i<nr_codecs;i++, c++){
1169 printf("\n============== %scodec %02d ===============\n",
1170 state==0?"video":"audio",i);
1171 printf("name='%s'\n",c->name);
1172 printf("info='%s'\n",c->info);
1173 printf("comment='%s'\n",c->comment);
1174 printf("dll='%s'\n",c->dll);
1175 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1176 c->flags, c->driver, c->status, c->cpuflags);
1178 for(j=0;j<CODECS_MAX_FOURCC;j++){
1179 if(c->fourcc[j]!=0xFFFFFFFF){
1180 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1184 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1185 if(c->outfmt[j]!=0xFFFFFFFF){
1186 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1190 for(j=0;j<CODECS_MAX_INFMT;j++){
1191 if(c->infmt[j]!=0xFFFFFFFF){
1192 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1196 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1197 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1198 printf("\n");
1203 if (!state) {
1204 printf("audiocodecs:\n");
1205 c = audio_codecs;
1206 nr_codecs = nr_acodecs;
1207 state = 1;
1208 goto next;
1210 return 0;
1213 #endif