libcdio
[mplayer.git] / codec-cfg.c
blobafa33e56263608029f99f6a5ac9ec94f6dc4d9f4
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, int force)
762 return find_codec(fourcc, fourccmap, start, 1, force);
765 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
766 codecs_t *start, int force)
768 return find_codec(fourcc, fourccmap, start, 0, force);
771 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
772 codecs_t *start, int audioflag, int force)
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;
809 if (force) return c;
812 return NULL;
815 void select_codec(char* codecname,int audioflag){
816 int i;
817 codecs_t *c;
818 // printf("select_codec('%s')\n",codecname);
819 if (audioflag) {
820 i = nr_acodecs;
821 c = audio_codecs;
822 } else {
823 i = nr_vcodecs;
824 c = video_codecs;
826 if(i)
827 for (/* NOTHING */; i--; c++)
828 if(!strcmp(c->name,codecname))
829 c->flags|=CODECS_FLAG_SELECTED;
832 void codecs_reset_selection(int audioflag){
833 int i;
834 codecs_t *c;
835 if (audioflag) {
836 i = nr_acodecs;
837 c = audio_codecs;
838 } else {
839 i = nr_vcodecs;
840 c = video_codecs;
842 if(i)
843 for (/* NOTHING */; i--; c++)
844 c->flags&=(~CODECS_FLAG_SELECTED);
847 void list_codecs(int audioflag){
848 int i;
849 codecs_t *c;
851 if (audioflag) {
852 i = nr_acodecs;
853 c = audio_codecs;
854 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
855 } else {
856 i = nr_vcodecs;
857 c = video_codecs;
858 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
860 if(!i) return;
861 for (/* NOTHING */; i--; c++) {
862 char* s="unknown ";
863 switch(c->status){
864 case CODECS_STATUS_WORKING: s="working ";break;
865 case CODECS_STATUS_PROBLEMS: s="problems";break;
866 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
867 case CODECS_STATUS_UNTESTED: s="untested";break;
869 if(c->dll)
870 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
871 else
872 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
880 #ifdef CODECS2HTML
882 * Fake out GUI references when building the codecs2html utility.
884 #ifdef HAVE_NEW_GUI
885 void gtkMessageBox( int type,char * str ) { return; }
886 int use_gui = 0;
887 #endif
889 void wrapline(FILE *f2,char *s){
890 int c;
891 if(!s){
892 fprintf(f2,"-");
893 return;
895 while((c=*s++)){
896 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
900 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
901 int c,d;
902 while((c=fgetc(f1))>=0){
903 if(c!='%'){
904 fputc(c,f2);
905 continue;
907 d=fgetc(f1);
909 switch(d){
910 case '.':
911 return; // end of section
912 case 'n':
913 wrapline(f2,codec->name); break;
914 case 'i':
915 wrapline(f2,codec->info); break;
916 case 'c':
917 wrapline(f2,codec->comment); break;
918 case 'd':
919 wrapline(f2,codec->dll); break;
920 case 'D':
921 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
922 case 'F':
923 for(d=0;d<CODECS_MAX_FOURCC;d++)
924 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
925 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
926 break;
927 case 'f':
928 for(d=0;d<CODECS_MAX_FOURCC;d++)
929 if(codec->fourcc[d]!=0xFFFFFFFF)
930 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
931 break;
932 case 'Y':
933 for(d=0;d<CODECS_MAX_OUTFMT;d++)
934 if(codec->outfmt[d]!=0xFFFFFFFF){
935 for (c=0; fmt_table[c].name; c++)
936 if(fmt_table[c].num==codec->outfmt[d]) break;
937 if(fmt_table[c].name)
938 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
940 break;
941 default:
942 fputc(c,f2);
943 fputc(d,f2);
949 void skiphtml(FILE *f1){
950 int c,d;
951 while((c=fgetc(f1))>=0){
952 if(c!='%'){
953 continue;
955 d=fgetc(f1);
956 if(d=='.') return; // end of section
960 static void print_int_array(const int* a, int size)
962 printf("{ ");
963 while (size--)
964 if(abs(*a)<256)
965 printf("%d%s", *a++, size?", ":"");
966 else
967 printf("0x%X%s", *a++, size?", ":"");
968 printf(" }");
971 static void print_char_array(const unsigned char* a, int size)
973 printf("{ ");
974 while (size--)
975 if((*a)<10)
976 printf("%d%s", *a++, size?", ":"");
977 else
978 printf("0x%02x%s", *a++, size?", ":"");
979 printf(" }");
982 static void print_string(const char* s)
984 if (!s) printf("NULL");
985 else printf("\"%s\"", s);
988 int main(int argc, char* argv[])
990 codecs_t *cl;
991 FILE *f1;
992 FILE *f2;
993 int c,d,i;
994 int pos;
995 int section=-1;
996 int nr_codecs;
997 int win32=-1;
998 int dshow=-1;
999 int win32ex=-1;
1002 * Take path to codecs.conf from command line, or fall back on
1003 * etc/codecs.conf
1005 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1006 exit(1);
1008 if (argc > 1) {
1009 int i, j;
1010 const char* nm[2];
1011 codecs_t* cod[2];
1012 int nr[2];
1014 nm[0] = "builtin_video_codecs";
1015 cod[0] = video_codecs;
1016 nr[0] = nr_vcodecs;
1018 nm[1] = "builtin_audio_codecs";
1019 cod[1] = audio_codecs;
1020 nr[1] = nr_acodecs;
1022 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1024 for (i=0; i<2; i++) {
1025 printf("codecs_t %s[] = {\n", nm[i]);
1026 for (j = 0; j < nr[i]; j++) {
1027 printf("{");
1029 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1030 printf(", /* fourcc */\n");
1032 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1033 printf(", /* fourccmap */\n");
1035 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1036 printf(", /* outfmt */\n");
1038 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1039 printf(", /* outflags */\n");
1041 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1042 printf(", /* infmt */\n");
1044 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1045 printf(", /* inflags */\n");
1047 print_string(cod[i][j].name); printf(", /* name */\n");
1048 print_string(cod[i][j].info); printf(", /* info */\n");
1049 print_string(cod[i][j].comment); printf(", /* comment */\n");
1050 print_string(cod[i][j].dll); printf(", /* dll */\n");
1051 print_string(cod[i][j].drv); printf(", /* drv */\n");
1053 printf("{ 0x%08lx, %hu, %hu,",
1054 cod[i][j].guid.f1,
1055 cod[i][j].guid.f2,
1056 cod[i][j].guid.f3);
1057 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1058 printf(" }, /* GUID */\n");
1059 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1060 cod[i][j].flags,
1061 cod[i][j].status,
1062 cod[i][j].cpuflags);
1063 if (j < nr[i]) printf(",\n");
1065 printf("};\n\n");
1067 exit(0);
1070 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1071 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1073 while((c=fgetc(f1))>=0){
1074 if(c!='%'){
1075 fputc(c,f2);
1076 continue;
1078 d=fgetc(f1);
1079 if(d>='0' && d<='9'){
1080 // begin section
1081 section=d-'0';
1082 printf("BEGIN %d\n",section);
1083 if(section>=5){
1084 // audio
1085 cl = audio_codecs;
1086 nr_codecs = nr_acodecs;
1087 dshow=7;win32=4;
1088 } else {
1089 // video
1090 cl = video_codecs;
1091 nr_codecs = nr_vcodecs;
1092 dshow=4;win32=2;win32ex=6;
1094 pos=ftell(f1);
1095 for(i=0;i<nr_codecs;i++){
1096 fseek(f1,pos,SEEK_SET);
1097 switch(section){
1098 case 0:
1099 case 5:
1100 if(cl[i].status==CODECS_STATUS_WORKING)
1101 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1102 parsehtml(f1,f2,&cl[i],section,dshow);
1103 break;
1104 #if 0
1105 case 1:
1106 case 6:
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 #endif
1112 case 2:
1113 case 7:
1114 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1115 parsehtml(f1,f2,&cl[i],section,dshow);
1116 break;
1117 case 3:
1118 case 8:
1119 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1120 parsehtml(f1,f2,&cl[i],section,dshow);
1121 break;
1122 case 4:
1123 case 9:
1124 if(cl[i].status==CODECS_STATUS_UNTESTED)
1125 parsehtml(f1,f2,&cl[i],section,dshow);
1126 break;
1127 default:
1128 printf("Warning! unimplemented section: %d\n",section);
1131 fseek(f1,pos,SEEK_SET);
1132 skiphtml(f1);
1133 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1135 continue;
1137 fputc(c,f2);
1138 fputc(d,f2);
1141 fclose(f2);
1142 fclose(f1);
1143 return 0;
1146 #endif
1148 #ifdef TESTING
1149 int main(void)
1151 codecs_t *c;
1152 int i,j, nr_codecs, state;
1154 if (!(parse_codec_cfg("etc/codecs.conf")))
1155 return 0;
1156 if (!video_codecs)
1157 printf("no videoconfig.\n");
1158 if (!audio_codecs)
1159 printf("no audioconfig.\n");
1161 printf("videocodecs:\n");
1162 c = video_codecs;
1163 nr_codecs = nr_vcodecs;
1164 state = 0;
1165 next:
1166 if (c) {
1167 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1168 nr_codecs);
1169 for(i=0;i<nr_codecs;i++, c++){
1170 printf("\n============== %scodec %02d ===============\n",
1171 state==0?"video":"audio",i);
1172 printf("name='%s'\n",c->name);
1173 printf("info='%s'\n",c->info);
1174 printf("comment='%s'\n",c->comment);
1175 printf("dll='%s'\n",c->dll);
1176 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1177 c->flags, c->driver, c->status, c->cpuflags);
1179 for(j=0;j<CODECS_MAX_FOURCC;j++){
1180 if(c->fourcc[j]!=0xFFFFFFFF){
1181 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1185 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1186 if(c->outfmt[j]!=0xFFFFFFFF){
1187 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1191 for(j=0;j<CODECS_MAX_INFMT;j++){
1192 if(c->infmt[j]!=0xFFFFFFFF){
1193 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1197 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1198 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1199 printf("\n");
1204 if (!state) {
1205 printf("audiocodecs:\n");
1206 c = audio_codecs;
1207 nr_codecs = nr_acodecs;
1208 state = 1;
1209 goto next;
1211 return 0;
1214 #endif