help_mp-hu.h synced with r19462
[mplayer/greg.git] / codec-cfg.c
blobcdc0f70f5287c0ed0abf7f29d6867932be3b35cb
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 "dshow",
288 "ffmpeg",
289 "vfwex",
290 "raw",
291 "msrle",
292 "xanim",
293 "msvidc",
294 "fli",
295 "cinepak",
296 "qtrle",
297 "nuv",
298 "cyuv",
299 "qtsmc",
300 "ducktm1",
301 "roqvideo",
302 "qtrpza",
303 "mpng",
304 "ijpg",
305 "zlib",
306 "mpegpes",
307 "zrmjpeg",
308 "realvid",
309 "xvid",
310 "libdv",
311 NULL
313 char **drv=audioflag?audiodrv:videodrv;
314 int i;
316 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
318 return -1;
320 #endif
322 static int validate_codec(codecs_t *c, int type)
324 unsigned int i;
325 char *tmp_name = c->name;
327 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
328 /* NOTHING */;
330 if (i < strlen(tmp_name)) {
331 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_InvalidCodecName, c->name);
332 return 0;
335 if (!c->info)
336 c->info = strdup(c->name);
338 #if 0
339 if (c->fourcc[0] == 0xffffffff) {
340 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksFourcc, c->name);
341 return 0;
343 #endif
345 if (!c->drv) {
346 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksDriver, c->name);
347 return 0;
350 #if 0
351 #warning codec->driver == 4;... <- ezt nem kellene belehegeszteni...
352 #warning HOL VANNAK DEFINIALVA????????????
353 if (!c->dll && (c->driver == 4 ||
354 (c->driver == 2 && type == TYPE_VIDEO))) {
355 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsDLL, c->name);
356 return 0;
358 #warning guid.f1 lehet 0? honnan lehet tudni, hogy nem adtak meg?
359 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
361 if (type == TYPE_VIDEO)
362 if (c->outfmt[0] == 0xffffffff) {
363 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsOutfmt, c->name);
364 return 0;
366 #endif
367 return 1;
370 static int add_comment(char *s, char **d)
372 int pos;
374 if (!*d)
375 pos = 0;
376 else {
377 pos = strlen(*d);
378 (*d)[pos++] = '\n';
380 if (!(*d = (char *) realloc(*d, pos + strlen(s) + 1))) {
381 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantAllocateComment);
382 return 0;
384 strcpy(*d + pos, s);
385 return 1;
388 static short get_cpuflags(char *s)
390 static char *flagstr[] = {
391 "mmx",
392 "sse",
393 "3dnow",
394 NULL
396 int i;
397 short flags = 0;
399 do {
400 for (i = 0; flagstr[i]; i++)
401 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
402 break;
403 if (!flagstr[i])
404 goto err_out_parse_error;
405 flags |= 1<<i;
406 s += strlen(flagstr[i]);
407 } while (*(s++) == ',');
409 if (*(--s) != '\0')
410 goto err_out_parse_error;
412 return flags;
413 err_out_parse_error:
414 return 0;
417 static FILE *fp;
418 static int line_num = 0;
419 static char *line;
420 static char *token[MAX_NR_TOKEN];
421 static int read_nextline = 1;
423 static int get_token(int min, int max)
425 static int line_pos;
426 int i;
427 char c;
429 if (max >= MAX_NR_TOKEN) {
430 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN);
431 goto out_eof;
434 memset(token, 0x00, sizeof(*token) * max);
436 if (read_nextline) {
437 if (!fgets(line, MAX_LINE_LEN, fp))
438 goto out_eof;
439 line_pos = 0;
440 ++line_num;
441 read_nextline = 0;
443 for (i = 0; i < max; i++) {
444 while (isspace(line[line_pos]))
445 ++line_pos;
446 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
447 line[line_pos] == ';') {
448 read_nextline = 1;
449 if (i >= min)
450 goto out_ok;
451 goto out_eol;
453 token[i] = line + line_pos;
454 c = line[line_pos];
455 if (c == '"' || c == '\'') {
456 token[i]++;
457 while (line[++line_pos] != c && line[line_pos])
458 /* NOTHING */;
459 } else {
460 for (/* NOTHING */; !isspace(line[line_pos]) &&
461 line[line_pos]; line_pos++)
462 /* NOTHING */;
464 if (!line[line_pos]) {
465 read_nextline = 1;
466 if (i >= min - 1)
467 goto out_ok;
468 goto out_eol;
470 line[line_pos] = '\0';
471 line_pos++;
473 out_ok:
474 return i;
475 out_eof:
476 read_nextline = 1;
477 return RET_EOF;
478 out_eol:
479 return RET_EOL;
482 static codecs_t *video_codecs=NULL;
483 static codecs_t *audio_codecs=NULL;
484 static int nr_vcodecs = 0;
485 static int nr_acodecs = 0;
487 int parse_codec_cfg(const char *cfgfile)
489 codecs_t *codec = NULL; // current codec
490 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
491 char *endptr; // strtoul()...
492 int *nr_codecsp;
493 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
494 int tmp, i;
496 // in case we call it a second time
497 codecs_uninit_free();
499 nr_vcodecs = 0;
500 nr_acodecs = 0;
502 if(cfgfile==NULL) {
503 #ifdef CODECS2HTML
504 return 0;
505 #else
506 video_codecs = builtin_video_codecs;
507 audio_codecs = builtin_audio_codecs;
508 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
509 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
510 return 1;
511 #endif
514 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_ReadingFile, cfgfile);
516 if ((fp = fopen(cfgfile, "r")) == NULL) {
517 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_CantOpenFileError, cfgfile, strerror(errno));
518 return 0;
521 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
522 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantGetMemoryForLine, strerror(errno));
523 return 0;
525 read_nextline = 1;
528 * this only catches release lines at the start of
529 * codecs.conf, before audiocodecs and videocodecs.
531 while ((tmp = get_token(1, 1)) == RET_EOL)
532 /* NOTHING */;
533 if (tmp == RET_EOF)
534 goto out;
535 if (!strcmp(token[0], "release")) {
536 if (get_token(1, 2) < 0)
537 goto err_out_parse_error;
538 tmp = atoi(token[0]);
539 if (tmp < CODEC_CFG_MIN)
540 goto err_out_release_num;
541 while ((tmp = get_token(1, 1)) == RET_EOL)
542 /* NOTHING */;
543 if (tmp == RET_EOF)
544 goto out;
545 } else
546 goto err_out_release_num;
549 * check if the next block starts with 'audiocodec' or
550 * with 'videocodec'
552 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
553 goto loop_enter;
554 goto err_out_parse_error;
556 while ((tmp = get_token(1, 1)) != RET_EOF) {
557 if (tmp == RET_EOL)
558 continue;
559 if (!strcmp(token[0], "audiocodec") ||
560 !strcmp(token[0], "videocodec")) {
561 if (!validate_codec(codec, codec_type))
562 goto err_out_not_valid;
563 loop_enter:
564 if (*token[0] == 'v') {
565 codec_type = TYPE_VIDEO;
566 nr_codecsp = &nr_vcodecs;
567 codecsp = &video_codecs;
568 } else if (*token[0] == 'a') {
569 codec_type = TYPE_AUDIO;
570 nr_codecsp = &nr_acodecs;
571 codecsp = &audio_codecs;
572 #ifdef DEBUG
573 } else {
574 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
575 goto err_out;
576 #endif
578 if (!(*codecsp = (codecs_t *) realloc(*codecsp,
579 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
580 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantReallocCodecsp, strerror(errno));
581 goto err_out;
583 codec=*codecsp + *nr_codecsp;
584 ++*nr_codecsp;
585 memset(codec,0,sizeof(codecs_t));
586 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
587 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
588 memset(codec->infmt, 0xff, sizeof(codec->infmt));
590 if (get_token(1, 1) < 0)
591 goto err_out_parse_error;
592 for (i = 0; i < *nr_codecsp - 1; i++) {
593 if(( (*codecsp)[i].name!=NULL) &&
594 (!strcmp(token[0], (*codecsp)[i].name)) ) {
595 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNameNotUnique, token[0]);
596 goto err_out_print_linenum;
599 if (!(codec->name = strdup(token[0]))) {
600 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupName, strerror(errno));
601 goto err_out;
603 } else if (!strcmp(token[0], "info")) {
604 if (codec->info || get_token(1, 1) < 0)
605 goto err_out_parse_error;
606 if (!(codec->info = strdup(token[0]))) {
607 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupInfo, strerror(errno));
608 goto err_out;
610 } else if (!strcmp(token[0], "comment")) {
611 if (get_token(1, 1) < 0)
612 goto err_out_parse_error;
613 add_comment(token[0], &codec->comment);
614 } else if (!strcmp(token[0], "fourcc")) {
615 if (get_token(1, 2) < 0)
616 goto err_out_parse_error;
617 if (!add_to_fourcc(token[0], token[1],
618 codec->fourcc,
619 codec->fourccmap))
620 goto err_out_print_linenum;
621 } else if (!strcmp(token[0], "format")) {
622 if (get_token(1, 2) < 0)
623 goto err_out_parse_error;
624 if (!add_to_format(token[0], token[1],
625 codec->fourcc,codec->fourccmap))
626 goto err_out_print_linenum;
627 } else if (!strcmp(token[0], "driver")) {
628 if (get_token(1, 1) < 0)
629 goto err_out_parse_error;
630 if (!(codec->drv = strdup(token[0]))) {
631 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDriver, strerror(errno));
632 goto err_out;
634 } else if (!strcmp(token[0], "dll")) {
635 if (get_token(1, 1) < 0)
636 goto err_out_parse_error;
637 if (!(codec->dll = strdup(token[0]))) {
638 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDLL, strerror(errno));
639 goto err_out;
641 } else if (!strcmp(token[0], "guid")) {
642 if (get_token(11, 11) < 0)
643 goto err_out_parse_error;
644 codec->guid.f1=strtoul(token[0],&endptr,0);
645 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
646 *endptr != '\0')
647 goto err_out_parse_error;
648 codec->guid.f2=strtoul(token[1],&endptr,0);
649 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
650 *endptr != '\0')
651 goto err_out_parse_error;
652 codec->guid.f3=strtoul(token[2],&endptr,0);
653 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
654 *endptr != '\0')
655 goto err_out_parse_error;
656 for (i = 0; i < 8; i++) {
657 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
658 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
659 *endptr != '\0')
660 goto err_out_parse_error;
662 } else if (!strcmp(token[0], "out")) {
663 if (get_token(1, 2) < 0)
664 goto err_out_parse_error;
665 if (!add_to_inout(token[0], token[1], codec->outfmt,
666 codec->outflags))
667 goto err_out_print_linenum;
668 } else if (!strcmp(token[0], "in")) {
669 if (get_token(1, 2) < 0)
670 goto err_out_parse_error;
671 if (!add_to_inout(token[0], token[1], codec->infmt,
672 codec->inflags))
673 goto err_out_print_linenum;
674 } else if (!strcmp(token[0], "flags")) {
675 if (get_token(1, 1) < 0)
676 goto err_out_parse_error;
677 if (!strcmp(token[0], "seekable"))
678 codec->flags |= CODECS_FLAG_SEEKABLE;
679 else
680 if (!strcmp(token[0], "align16"))
681 codec->flags |= CODECS_FLAG_ALIGN16;
682 else
683 goto err_out_parse_error;
684 } else if (!strcmp(token[0], "status")) {
685 if (get_token(1, 1) < 0)
686 goto err_out_parse_error;
687 if (!strcasecmp(token[0], "working"))
688 codec->status = CODECS_STATUS_WORKING;
689 else if (!strcasecmp(token[0], "crashing"))
690 codec->status = CODECS_STATUS_NOT_WORKING;
691 else if (!strcasecmp(token[0], "untested"))
692 codec->status = CODECS_STATUS_UNTESTED;
693 else if (!strcasecmp(token[0], "buggy"))
694 codec->status = CODECS_STATUS_PROBLEMS;
695 else
696 goto err_out_parse_error;
697 } else if (!strcmp(token[0], "cpuflags")) {
698 if (get_token(1, 1) < 0)
699 goto err_out_parse_error;
700 if (!(codec->cpuflags = get_cpuflags(token[0])))
701 goto err_out_parse_error;
702 } else
703 goto err_out_parse_error;
705 if (!validate_codec(codec, codec_type))
706 goto err_out_not_valid;
707 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_AudioVideoCodecTotals, nr_acodecs, nr_vcodecs);
708 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
709 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
710 out:
711 free(line);
712 line=NULL;
713 fclose(fp);
714 return 1;
716 err_out_parse_error:
717 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
718 err_out_print_linenum:
719 PRINT_LINENUM;
720 err_out:
721 codecs_uninit_free();
723 free(line);
724 line=NULL;
725 line_num = 0;
726 fclose(fp);
727 return 0;
728 err_out_not_valid:
729 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecDefinitionIncorrect);
730 goto err_out_print_linenum;
731 err_out_release_num:
732 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_OutdatedCodecsConf);
733 goto err_out_print_linenum;
736 static void codecs_free(codecs_t* codecs,int count) {
737 int i;
738 for ( i = 0; i < count; i++)
739 if ( (codecs[i]).name ) {
740 if( (codecs[i]).name )
741 free((codecs[i]).name);
742 if( (codecs[i]).info )
743 free((codecs[i]).info);
744 if( (codecs[i]).comment )
745 free((codecs[i]).comment);
746 if( (codecs[i]).dll )
747 free((codecs[i]).dll);
748 if( (codecs[i]).drv )
749 free((codecs[i]).drv);
751 if (codecs)
752 free(codecs);
755 void codecs_uninit_free(void) {
756 if (video_codecs)
757 codecs_free(video_codecs,nr_vcodecs);
758 video_codecs=NULL;
759 if (audio_codecs)
760 codecs_free(audio_codecs,nr_acodecs);
761 audio_codecs=NULL;
764 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
765 codecs_t *start, int force)
767 return find_codec(fourcc, fourccmap, start, 1, force);
770 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
771 codecs_t *start, int force)
773 return find_codec(fourcc, fourccmap, start, 0, force);
776 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
777 codecs_t *start, int audioflag, int force)
779 int i, j;
780 codecs_t *c;
782 #if 0
783 if (start) {
784 for (/* NOTHING */; start->name; start++) {
785 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
786 if (start->fourcc[j] == fourcc) {
787 if (fourccmap)
788 *fourccmap = start->fourccmap[j];
789 return start;
793 } else
794 #endif
796 if (audioflag) {
797 i = nr_acodecs;
798 c = audio_codecs;
799 } else {
800 i = nr_vcodecs;
801 c = video_codecs;
803 if(!i) return NULL;
804 for (/* NOTHING */; i--; c++) {
805 if(start && c<=start) continue;
806 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
807 // FIXME: do NOT hardwire 'null' name here:
808 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
809 if (fourccmap)
810 *fourccmap = c->fourccmap[j];
811 return c;
814 if (force) return c;
817 return NULL;
820 void select_codec(char* codecname,int audioflag){
821 int i;
822 codecs_t *c;
823 // printf("select_codec('%s')\n",codecname);
824 if (audioflag) {
825 i = nr_acodecs;
826 c = audio_codecs;
827 } else {
828 i = nr_vcodecs;
829 c = video_codecs;
831 if(i)
832 for (/* NOTHING */; i--; c++)
833 if(!strcmp(c->name,codecname))
834 c->flags|=CODECS_FLAG_SELECTED;
837 void codecs_reset_selection(int audioflag){
838 int i;
839 codecs_t *c;
840 if (audioflag) {
841 i = nr_acodecs;
842 c = audio_codecs;
843 } else {
844 i = nr_vcodecs;
845 c = video_codecs;
847 if(i)
848 for (/* NOTHING */; i--; c++)
849 c->flags&=(~CODECS_FLAG_SELECTED);
852 void list_codecs(int audioflag){
853 int i;
854 codecs_t *c;
856 if (audioflag) {
857 i = nr_acodecs;
858 c = audio_codecs;
859 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
860 } else {
861 i = nr_vcodecs;
862 c = video_codecs;
863 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
865 if(!i) return;
866 for (/* NOTHING */; i--; c++) {
867 char* s="unknown ";
868 switch(c->status){
869 case CODECS_STATUS_WORKING: s="working ";break;
870 case CODECS_STATUS_PROBLEMS: s="problems";break;
871 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
872 case CODECS_STATUS_UNTESTED: s="untested";break;
874 if(c->dll)
875 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
876 else
877 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
885 #ifdef CODECS2HTML
887 * Fake out GUI references when building the codecs2html utility.
889 #ifdef HAVE_NEW_GUI
890 void gtkMessageBox( int type,char * str ) { return; }
891 int use_gui = 0;
892 #endif
894 void wrapline(FILE *f2,char *s){
895 int c;
896 if(!s){
897 fprintf(f2,"-");
898 return;
900 while((c=*s++)){
901 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
905 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
906 int c,d;
907 while((c=fgetc(f1))>=0){
908 if(c!='%'){
909 fputc(c,f2);
910 continue;
912 d=fgetc(f1);
914 switch(d){
915 case '.':
916 return; // end of section
917 case 'n':
918 wrapline(f2,codec->name); break;
919 case 'i':
920 wrapline(f2,codec->info); break;
921 case 'c':
922 wrapline(f2,codec->comment); break;
923 case 'd':
924 wrapline(f2,codec->dll); break;
925 case 'D':
926 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
927 case 'F':
928 for(d=0;d<CODECS_MAX_FOURCC;d++)
929 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
930 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
931 break;
932 case 'f':
933 for(d=0;d<CODECS_MAX_FOURCC;d++)
934 if(codec->fourcc[d]!=0xFFFFFFFF)
935 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
936 break;
937 case 'Y':
938 for(d=0;d<CODECS_MAX_OUTFMT;d++)
939 if(codec->outfmt[d]!=0xFFFFFFFF){
940 for (c=0; fmt_table[c].name; c++)
941 if(fmt_table[c].num==codec->outfmt[d]) break;
942 if(fmt_table[c].name)
943 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
945 break;
946 default:
947 fputc(c,f2);
948 fputc(d,f2);
954 void skiphtml(FILE *f1){
955 int c,d;
956 while((c=fgetc(f1))>=0){
957 if(c!='%'){
958 continue;
960 d=fgetc(f1);
961 if(d=='.') return; // end of section
965 static void print_int_array(const int* a, int size)
967 printf("{ ");
968 while (size--)
969 if(abs(*a)<256)
970 printf("%d%s", *a++, size?", ":"");
971 else
972 printf("0x%X%s", *a++, size?", ":"");
973 printf(" }");
976 static void print_char_array(const unsigned char* a, int size)
978 printf("{ ");
979 while (size--)
980 if((*a)<10)
981 printf("%d%s", *a++, size?", ":"");
982 else
983 printf("0x%02x%s", *a++, size?", ":"");
984 printf(" }");
987 static void print_string(const char* s)
989 if (!s) printf("NULL");
990 else printf("\"%s\"", s);
993 int main(int argc, char* argv[])
995 codecs_t *cl;
996 FILE *f1;
997 FILE *f2;
998 int c,d,i;
999 int pos;
1000 int section=-1;
1001 int nr_codecs;
1002 int win32=-1;
1003 int dshow=-1;
1004 int win32ex=-1;
1007 * Take path to codecs.conf from command line, or fall back on
1008 * etc/codecs.conf
1010 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1011 exit(1);
1013 if (argc > 1) {
1014 int i, j;
1015 const char* nm[2];
1016 codecs_t* cod[2];
1017 int nr[2];
1019 nm[0] = "builtin_video_codecs";
1020 cod[0] = video_codecs;
1021 nr[0] = nr_vcodecs;
1023 nm[1] = "builtin_audio_codecs";
1024 cod[1] = audio_codecs;
1025 nr[1] = nr_acodecs;
1027 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1029 for (i=0; i<2; i++) {
1030 printf("codecs_t %s[] = {\n", nm[i]);
1031 for (j = 0; j < nr[i]; j++) {
1032 printf("{");
1034 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1035 printf(", /* fourcc */\n");
1037 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1038 printf(", /* fourccmap */\n");
1040 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1041 printf(", /* outfmt */\n");
1043 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1044 printf(", /* outflags */\n");
1046 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1047 printf(", /* infmt */\n");
1049 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1050 printf(", /* inflags */\n");
1052 print_string(cod[i][j].name); printf(", /* name */\n");
1053 print_string(cod[i][j].info); printf(", /* info */\n");
1054 print_string(cod[i][j].comment); printf(", /* comment */\n");
1055 print_string(cod[i][j].dll); printf(", /* dll */\n");
1056 print_string(cod[i][j].drv); printf(", /* drv */\n");
1058 printf("{ 0x%08lx, %hu, %hu,",
1059 cod[i][j].guid.f1,
1060 cod[i][j].guid.f2,
1061 cod[i][j].guid.f3);
1062 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1063 printf(" }, /* GUID */\n");
1064 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1065 cod[i][j].flags,
1066 cod[i][j].status,
1067 cod[i][j].cpuflags);
1068 if (j < nr[i]) printf(",\n");
1070 printf("};\n\n");
1072 exit(0);
1075 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1076 f2=fopen("DOCS/codecs-status.html","wb"); if(!f2) exit(1);
1078 while((c=fgetc(f1))>=0){
1079 if(c!='%'){
1080 fputc(c,f2);
1081 continue;
1083 d=fgetc(f1);
1084 if(d>='0' && d<='9'){
1085 // begin section
1086 section=d-'0';
1087 //printf("BEGIN %d\n",section);
1088 if(section>=5){
1089 // audio
1090 cl = audio_codecs;
1091 nr_codecs = nr_acodecs;
1092 dshow=7;win32=4;
1093 } else {
1094 // video
1095 cl = video_codecs;
1096 nr_codecs = nr_vcodecs;
1097 dshow=4;win32=2;win32ex=6;
1099 pos=ftell(f1);
1100 for(i=0;i<nr_codecs;i++){
1101 fseek(f1,pos,SEEK_SET);
1102 switch(section){
1103 case 0:
1104 case 5:
1105 if(cl[i].status==CODECS_STATUS_WORKING)
1106 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1107 parsehtml(f1,f2,&cl[i],section,dshow);
1108 break;
1109 #if 0
1110 case 1:
1111 case 6:
1112 if(cl[i].status==CODECS_STATUS_WORKING)
1113 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1114 parsehtml(f1,f2,&cl[i],section,dshow);
1115 break;
1116 #endif
1117 case 2:
1118 case 7:
1119 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1120 parsehtml(f1,f2,&cl[i],section,dshow);
1121 break;
1122 case 3:
1123 case 8:
1124 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1125 parsehtml(f1,f2,&cl[i],section,dshow);
1126 break;
1127 case 4:
1128 case 9:
1129 if(cl[i].status==CODECS_STATUS_UNTESTED)
1130 parsehtml(f1,f2,&cl[i],section,dshow);
1131 break;
1132 default:
1133 printf("Warning! unimplemented section: %d\n",section);
1136 fseek(f1,pos,SEEK_SET);
1137 skiphtml(f1);
1138 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1140 continue;
1142 fputc(c,f2);
1143 fputc(d,f2);
1146 fclose(f2);
1147 fclose(f1);
1148 return 0;
1151 #endif
1153 #ifdef TESTING
1154 int main(void)
1156 codecs_t *c;
1157 int i,j, nr_codecs, state;
1159 if (!(parse_codec_cfg("etc/codecs.conf")))
1160 return 0;
1161 if (!video_codecs)
1162 printf("no videoconfig.\n");
1163 if (!audio_codecs)
1164 printf("no audioconfig.\n");
1166 printf("videocodecs:\n");
1167 c = video_codecs;
1168 nr_codecs = nr_vcodecs;
1169 state = 0;
1170 next:
1171 if (c) {
1172 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1173 nr_codecs);
1174 for(i=0;i<nr_codecs;i++, c++){
1175 printf("\n============== %scodec %02d ===============\n",
1176 state==0?"video":"audio",i);
1177 printf("name='%s'\n",c->name);
1178 printf("info='%s'\n",c->info);
1179 printf("comment='%s'\n",c->comment);
1180 printf("dll='%s'\n",c->dll);
1181 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1182 c->flags, c->driver, c->status, c->cpuflags);
1184 for(j=0;j<CODECS_MAX_FOURCC;j++){
1185 if(c->fourcc[j]!=0xFFFFFFFF){
1186 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1190 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1191 if(c->outfmt[j]!=0xFFFFFFFF){
1192 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1196 for(j=0;j<CODECS_MAX_INFMT;j++){
1197 if(c->infmt[j]!=0xFFFFFFFF){
1198 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1202 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1203 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1204 printf("\n");
1209 if (!state) {
1210 printf("audiocodecs:\n");
1211 c = audio_codecs;
1212 nr_codecs = nr_acodecs;
1213 state = 1;
1214 goto next;
1216 return 0;
1219 #endif