10l initial patch by Oded Shimon <ods15 at ods15.dyndns.org>
[mplayer/greg.git] / codec-cfg.c
blob90a5ad2c550c4de84a745c5f14537e8facb04b56
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: gcc -Iloader/ -DCODECS2HTML -o codecs2html codecs-cfg.c
9 * TODO: implement informat in CODECS2HTML too
12 #define DEBUG
14 //disable asserts
15 #define NDEBUG
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <ctype.h>
23 #include <assert.h>
24 #include <string.h>
26 #include "config.h"
27 #include "mp_msg.h"
29 #include "help_mp.h"
31 // for mmioFOURCC:
32 #include "libmpdemux/aviheader.h"
34 #include "libvo/img_format.h"
35 #include "codec-cfg.h"
37 #ifndef CODECS2HTML
38 #include "codecs.conf.h"
39 #endif
41 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
43 #define MAX_NR_TOKEN 16
45 #define MAX_LINE_LEN 1000
47 #define RET_EOF -1
48 #define RET_EOL -2
50 #define TYPE_VIDEO 0
51 #define TYPE_AUDIO 1
53 char * codecs_file = NULL;
55 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
56 unsigned int *map)
58 int i, j, freeslots;
59 unsigned int tmp;
61 /* find first unused slot */
62 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
63 /* NOTHING */;
64 freeslots = CODECS_MAX_FOURCC - i;
65 if (!freeslots)
66 goto err_out_too_many;
68 do {
69 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
70 for (j = 0; j < i; j++)
71 if (tmp == fourcc[j])
72 goto err_out_duplicated;
73 fourcc[i] = tmp;
74 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
75 s += 4;
76 i++;
77 } while ((*(s++) == ',') && --freeslots);
79 if (!freeslots)
80 goto err_out_too_many;
81 if (*(--s) != '\0')
82 goto err_out_parse_error;
83 return 1;
84 err_out_duplicated:
85 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFourcc);
86 return 0;
87 err_out_too_many:
88 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
89 return 0;
90 err_out_parse_error:
91 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
92 return 0;
95 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
97 int i, j;
98 char *endptr;
100 /* find first unused slot */
101 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
102 /* NOTHING */;
103 if (i == CODECS_MAX_FOURCC) {
104 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyFourccs);
105 return 0;
108 fourcc[i]=strtoul(s,&endptr,0);
109 if (*endptr != '\0') {
110 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDNotNumber);
111 return 0;
114 if(alias){
115 fourccmap[i]=strtoul(alias,&endptr,0);
116 if (*endptr != '\0') {
117 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseErrorFIDAliasNotNumber);
118 return 0;
120 } else
121 fourccmap[i]=fourcc[i];
123 for (j = 0; j < i; j++)
124 if (fourcc[j] == fourcc[i]) {
125 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_DuplicateFID);
126 return 0;
129 return 1;
132 static struct {
133 const char *name;
134 const unsigned int num;
135 } fmt_table[] = {
136 {"YV12", IMGFMT_YV12},
137 {"I420", IMGFMT_I420},
138 {"IYUV", IMGFMT_IYUV},
139 {"NV12", IMGFMT_NV12},
140 {"NV21", IMGFMT_NV21},
141 {"YVU9", IMGFMT_YVU9},
142 {"IF09", IMGFMT_IF09},
143 {"444P", IMGFMT_444P},
144 {"422P", IMGFMT_422P},
145 {"411P", IMGFMT_411P},
147 {"YUY2", IMGFMT_YUY2},
148 {"UYVY", IMGFMT_UYVY},
149 {"YVYU", IMGFMT_YVYU},
151 {"RGB4", IMGFMT_RGB|4},
152 {"RGB8", IMGFMT_RGB|8},
153 {"RGB15", IMGFMT_RGB|15},
154 {"RGB16", IMGFMT_RGB|16},
155 {"RGB24", IMGFMT_RGB|24},
156 {"RGB32", IMGFMT_RGB|32},
157 {"BGR4", IMGFMT_BGR|4},
158 {"BGR8", IMGFMT_BGR|8},
159 {"BGR15", IMGFMT_BGR|15},
160 {"BGR16", IMGFMT_BGR|16},
161 {"BGR24", IMGFMT_BGR|24},
162 {"BGR32", IMGFMT_BGR|32},
163 {"RGB1", IMGFMT_RGB|1},
164 {"BGR1", IMGFMT_BGR|1},
166 {"MPES", IMGFMT_MPEGPES},
167 {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI},
168 {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT},
169 {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB},
171 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
172 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
174 {NULL, 0}
178 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
179 unsigned char *outflags)
182 static char *flagstr[] = {
183 "flip",
184 "noflip",
185 "yuvhack",
186 "query",
187 "static",
188 NULL
191 int i, j, freeslots;
192 unsigned char flags;
194 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
195 /* NOTHING */;
196 freeslots = CODECS_MAX_OUTFMT - i;
197 if (!freeslots)
198 goto err_out_too_many;
200 flags = 0;
201 if(sflags) {
202 do {
203 for (j = 0; flagstr[j] != NULL; j++)
204 if (!strncmp(sflags, flagstr[j],
205 strlen(flagstr[j])))
206 break;
207 if (flagstr[j] == NULL)
208 goto err_out_parse_error;
209 flags|=(1<<j);
210 sflags+=strlen(flagstr[j]);
211 } while (*(sflags++) == ',');
213 if (*(--sflags) != '\0')
214 goto err_out_parse_error;
217 do {
218 for (j = 0; fmt_table[j].name != NULL; j++)
219 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
220 break;
221 if (fmt_table[j].name == NULL)
222 goto err_out_parse_error;
223 outfmt[i] = fmt_table[j].num;
224 outflags[i] = flags;
225 ++i;
226 sfmt+=strlen(fmt_table[j].name);
227 } while ((*(sfmt++) == ',') && --freeslots);
229 if (!freeslots)
230 goto err_out_too_many;
232 if (*(--sfmt) != '\0')
233 goto err_out_parse_error;
235 return 1;
236 err_out_too_many:
237 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_TooManyOut);
238 return 0;
239 err_out_parse_error:
240 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
241 return 0;
244 #if 0
245 static short get_driver(char *s,int audioflag)
247 static char *audiodrv[] = {
248 "null",
249 "mp3lib",
250 "pcm",
251 "libac3",
252 "acm",
253 "alaw",
254 "msgsm",
255 "dshow",
256 "dvdpcm",
257 "hwac3",
258 "libvorbis",
259 "ffmpeg",
260 "libmad",
261 "msadpcm",
262 "liba52",
263 "g72x",
264 "imaadpcm",
265 "dk4adpcm",
266 "dk3adpcm",
267 "roqaudio",
268 "faad",
269 "realaud",
270 "libdv",
271 NULL
273 static char *videodrv[] = {
274 "null",
275 "libmpeg2",
276 "vfw",
277 "odivx",
278 "dshow",
279 "ffmpeg",
280 "vfwex",
281 "divx4",
282 "raw",
283 "msrle",
284 "xanim",
285 "msvidc",
286 "fli",
287 "cinepak",
288 "qtrle",
289 "nuv",
290 "cyuv",
291 "qtsmc",
292 "ducktm1",
293 "roqvideo",
294 "qtrpza",
295 "mpng",
296 "ijpg",
297 "zlib",
298 "mpegpes",
299 "zrmjpeg",
300 "realvid",
301 "xvid",
302 "libdv",
303 NULL
305 char **drv=audioflag?audiodrv:videodrv;
306 int i;
308 for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i;
310 return -1;
312 #endif
314 static int validate_codec(codecs_t *c, int type)
316 unsigned int i;
317 char *tmp_name = c->name;
319 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
320 /* NOTHING */;
322 if (i < strlen(tmp_name)) {
323 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_InvalidCodecName, c->name);
324 return 0;
327 if (!c->info)
328 c->info = strdup(c->name);
330 #if 0
331 if (c->fourcc[0] == 0xffffffff) {
332 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksFourcc, c->name);
333 return 0;
335 #endif
337 if (!c->drv) {
338 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksDriver, c->name);
339 return 0;
342 #if 0
343 #warning codec->driver == 4;... <- ezt nem kellene belehegeszteni...
344 #warning HOL VANNAK DEFINIALVA????????????
345 if (!c->dll && (c->driver == 4 ||
346 (c->driver == 2 && type == TYPE_VIDEO))) {
347 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsDLL, c->name);
348 return 0;
350 #warning guid.f1 lehet 0? honnan lehet tudni, hogy nem adtak meg?
351 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
353 if (type == TYPE_VIDEO)
354 if (c->outfmt[0] == 0xffffffff) {
355 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsOutfmt, c->name);
356 return 0;
358 #endif
359 return 1;
362 static int add_comment(char *s, char **d)
364 int pos;
366 if (!*d)
367 pos = 0;
368 else {
369 pos = strlen(*d);
370 (*d)[pos++] = '\n';
372 if (!(*d = (char *) realloc(*d, pos + strlen(s) + 1))) {
373 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantAllocateComment);
374 return 0;
376 strcpy(*d + pos, s);
377 return 1;
380 static short get_cpuflags(char *s)
382 static char *flagstr[] = {
383 "mmx",
384 "sse",
385 "3dnow",
386 NULL
388 int i;
389 short flags = 0;
391 do {
392 for (i = 0; flagstr[i]; i++)
393 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
394 break;
395 if (!flagstr[i])
396 goto err_out_parse_error;
397 flags |= 1<<i;
398 s += strlen(flagstr[i]);
399 } while (*(s++) == ',');
401 if (*(--s) != '\0')
402 goto err_out_parse_error;
404 return flags;
405 err_out_parse_error:
406 return 0;
409 static FILE *fp;
410 static int line_num = 0;
411 static char *line;
412 static char *token[MAX_NR_TOKEN];
413 static int read_nextline = 1;
415 static int get_token(int min, int max)
417 static int line_pos;
418 int i;
419 char c;
421 if (max >= MAX_NR_TOKEN) {
422 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN);
423 goto out_eof;
426 memset(token, 0x00, sizeof(*token) * max);
428 if (read_nextline) {
429 if (!fgets(line, MAX_LINE_LEN, fp))
430 goto out_eof;
431 line_pos = 0;
432 ++line_num;
433 read_nextline = 0;
435 for (i = 0; i < max; i++) {
436 while (isspace(line[line_pos]))
437 ++line_pos;
438 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
439 line[line_pos] == ';') {
440 read_nextline = 1;
441 if (i >= min)
442 goto out_ok;
443 goto out_eol;
445 token[i] = line + line_pos;
446 c = line[line_pos];
447 if (c == '"' || c == '\'') {
448 token[i]++;
449 while (line[++line_pos] != c && line[line_pos])
450 /* NOTHING */;
451 } else {
452 for (/* NOTHING */; !isspace(line[line_pos]) &&
453 line[line_pos]; line_pos++)
454 /* NOTHING */;
456 if (!line[line_pos]) {
457 read_nextline = 1;
458 if (i >= min - 1)
459 goto out_ok;
460 goto out_eol;
462 line[line_pos] = '\0';
463 line_pos++;
465 out_ok:
466 return i;
467 out_eof:
468 read_nextline = 1;
469 return RET_EOF;
470 out_eol:
471 return RET_EOL;
474 static codecs_t *video_codecs=NULL;
475 static codecs_t *audio_codecs=NULL;
476 static int nr_vcodecs = 0;
477 static int nr_acodecs = 0;
479 int parse_codec_cfg(char *cfgfile)
481 codecs_t *codec = NULL; // current codec
482 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
483 char *endptr; // strtoul()...
484 int *nr_codecsp;
485 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
486 int tmp, i;
488 // in case we call it a second time
489 codecs_uninit_free();
491 nr_vcodecs = 0;
492 nr_acodecs = 0;
494 if(cfgfile==NULL) {
495 #ifdef CODECS2HTML
496 return 0;
497 #else
498 video_codecs = builtin_video_codecs;
499 audio_codecs = builtin_audio_codecs;
500 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
501 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
502 return 1;
503 #endif
506 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_ReadingFile, cfgfile);
508 if ((fp = fopen(cfgfile, "r")) == NULL) {
509 mp_msg(MSGT_CODECCFG,MSGL_V,MSGTR_CantOpenFileError, cfgfile, strerror(errno));
510 return 0;
513 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
514 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantGetMemoryForLine, strerror(errno));
515 return 0;
517 read_nextline = 1;
520 * this only catches release lines at the start of
521 * codecs.conf, before audiocodecs and videocodecs.
523 while ((tmp = get_token(1, 1)) == RET_EOL)
524 /* NOTHING */;
525 if (tmp == RET_EOF)
526 goto out;
527 if (!strcmp(token[0], "release")) {
528 if (get_token(1, 2) < 0)
529 goto err_out_parse_error;
530 tmp = atoi(token[0]);
531 if (tmp < CODEC_CFG_MIN)
532 goto err_out_release_num;
533 while ((tmp = get_token(1, 1)) == RET_EOL)
534 /* NOTHING */;
535 if (tmp == RET_EOF)
536 goto out;
537 } else
538 goto err_out_release_num;
541 * check if the next block starts with 'audiocodec' or
542 * with 'videocodec'
544 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
545 goto loop_enter;
546 goto err_out_parse_error;
548 while ((tmp = get_token(1, 1)) != RET_EOF) {
549 if (tmp == RET_EOL)
550 continue;
551 if (!strcmp(token[0], "audiocodec") ||
552 !strcmp(token[0], "videocodec")) {
553 if (!validate_codec(codec, codec_type))
554 goto err_out_not_valid;
555 loop_enter:
556 if (*token[0] == 'v') {
557 codec_type = TYPE_VIDEO;
558 nr_codecsp = &nr_vcodecs;
559 codecsp = &video_codecs;
560 } else if (*token[0] == 'a') {
561 codec_type = TYPE_AUDIO;
562 nr_codecsp = &nr_acodecs;
563 codecsp = &audio_codecs;
564 #ifdef DEBUG
565 } else {
566 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
567 goto err_out;
568 #endif
570 if (!(*codecsp = (codecs_t *) realloc(*codecsp,
571 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
572 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantReallocCodecsp, strerror(errno));
573 goto err_out;
575 codec=*codecsp + *nr_codecsp;
576 ++*nr_codecsp;
577 memset(codec,0,sizeof(codecs_t));
578 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
579 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
580 memset(codec->infmt, 0xff, sizeof(codec->infmt));
582 if (get_token(1, 1) < 0)
583 goto err_out_parse_error;
584 for (i = 0; i < *nr_codecsp - 1; i++) {
585 if(( (*codecsp)[i].name!=NULL) &&
586 (!strcmp(token[0], (*codecsp)[i].name)) ) {
587 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNameNotUnique, token[0]);
588 goto err_out_print_linenum;
591 if (!(codec->name = strdup(token[0]))) {
592 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupName, strerror(errno));
593 goto err_out;
595 } else if (!strcmp(token[0], "info")) {
596 if (codec->info || get_token(1, 1) < 0)
597 goto err_out_parse_error;
598 if (!(codec->info = strdup(token[0]))) {
599 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupInfo, strerror(errno));
600 goto err_out;
602 } else if (!strcmp(token[0], "comment")) {
603 if (get_token(1, 1) < 0)
604 goto err_out_parse_error;
605 add_comment(token[0], &codec->comment);
606 } else if (!strcmp(token[0], "fourcc")) {
607 if (get_token(1, 2) < 0)
608 goto err_out_parse_error;
609 if (!add_to_fourcc(token[0], token[1],
610 codec->fourcc,
611 codec->fourccmap))
612 goto err_out_print_linenum;
613 } else if (!strcmp(token[0], "format")) {
614 if (get_token(1, 2) < 0)
615 goto err_out_parse_error;
616 if (!add_to_format(token[0], token[1],
617 codec->fourcc,codec->fourccmap))
618 goto err_out_print_linenum;
619 } else if (!strcmp(token[0], "driver")) {
620 if (get_token(1, 1) < 0)
621 goto err_out_parse_error;
622 if (!(codec->drv = strdup(token[0]))) {
623 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDriver, strerror(errno));
624 goto err_out;
626 } else if (!strcmp(token[0], "dll")) {
627 if (get_token(1, 1) < 0)
628 goto err_out_parse_error;
629 if (!(codec->dll = strdup(token[0]))) {
630 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDLL, strerror(errno));
631 goto err_out;
633 } else if (!strcmp(token[0], "guid")) {
634 if (get_token(11, 11) < 0)
635 goto err_out_parse_error;
636 codec->guid.f1=strtoul(token[0],&endptr,0);
637 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
638 *endptr != '\0')
639 goto err_out_parse_error;
640 codec->guid.f2=strtoul(token[1],&endptr,0);
641 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
642 *endptr != '\0')
643 goto err_out_parse_error;
644 codec->guid.f3=strtoul(token[2],&endptr,0);
645 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
646 *endptr != '\0')
647 goto err_out_parse_error;
648 for (i = 0; i < 8; i++) {
649 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
650 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
651 *endptr != '\0')
652 goto err_out_parse_error;
654 } else if (!strcmp(token[0], "out")) {
655 if (get_token(1, 2) < 0)
656 goto err_out_parse_error;
657 if (!add_to_inout(token[0], token[1], codec->outfmt,
658 codec->outflags))
659 goto err_out_print_linenum;
660 } else if (!strcmp(token[0], "in")) {
661 if (get_token(1, 2) < 0)
662 goto err_out_parse_error;
663 if (!add_to_inout(token[0], token[1], codec->infmt,
664 codec->inflags))
665 goto err_out_print_linenum;
666 } else if (!strcmp(token[0], "flags")) {
667 if (get_token(1, 1) < 0)
668 goto err_out_parse_error;
669 if (!strcmp(token[0], "seekable"))
670 codec->flags |= CODECS_FLAG_SEEKABLE;
671 else
672 if (!strcmp(token[0], "align16"))
673 codec->flags |= CODECS_FLAG_ALIGN16;
674 else
675 goto err_out_parse_error;
676 } else if (!strcmp(token[0], "status")) {
677 if (get_token(1, 1) < 0)
678 goto err_out_parse_error;
679 if (!strcasecmp(token[0], "working"))
680 codec->status = CODECS_STATUS_WORKING;
681 else if (!strcasecmp(token[0], "crashing"))
682 codec->status = CODECS_STATUS_NOT_WORKING;
683 else if (!strcasecmp(token[0], "untested"))
684 codec->status = CODECS_STATUS_UNTESTED;
685 else if (!strcasecmp(token[0], "buggy"))
686 codec->status = CODECS_STATUS_PROBLEMS;
687 else
688 goto err_out_parse_error;
689 } else if (!strcmp(token[0], "cpuflags")) {
690 if (get_token(1, 1) < 0)
691 goto err_out_parse_error;
692 if (!(codec->cpuflags = get_cpuflags(token[0])))
693 goto err_out_parse_error;
694 } else
695 goto err_out_parse_error;
697 if (!validate_codec(codec, codec_type))
698 goto err_out_not_valid;
699 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_AudioVideoCodecTotals, nr_acodecs, nr_vcodecs);
700 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
701 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
702 out:
703 free(line);
704 line=NULL;
705 fclose(fp);
706 return 1;
708 err_out_parse_error:
709 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
710 err_out_print_linenum:
711 PRINT_LINENUM;
712 err_out:
713 codecs_uninit_free();
715 free(line);
716 line=NULL;
717 line_num = 0;
718 fclose(fp);
719 return 0;
720 err_out_not_valid:
721 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecDefinitionIncorrect);
722 goto err_out_print_linenum;
723 err_out_release_num:
724 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_OutdatedCodecsConf);
725 goto err_out_print_linenum;
728 static void codecs_free(codecs_t* codecs,int count) {
729 int i;
730 for ( i = 0; i < count; i++)
731 if ( (codecs[i]).name ) {
732 if( (codecs[i]).name )
733 free((codecs[i]).name);
734 if( (codecs[i]).info )
735 free((codecs[i]).info);
736 if( (codecs[i]).comment )
737 free((codecs[i]).comment);
738 if( (codecs[i]).dll )
739 free((codecs[i]).dll);
740 if( (codecs[i]).drv )
741 free((codecs[i]).drv);
743 if (codecs)
744 free(codecs);
747 void codecs_uninit_free() {
748 if (video_codecs)
749 codecs_free(video_codecs,nr_vcodecs);
750 video_codecs=NULL;
751 if (audio_codecs)
752 codecs_free(audio_codecs,nr_acodecs);
753 audio_codecs=NULL;
756 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
757 codecs_t *start)
759 return find_codec(fourcc, fourccmap, start, 1);
762 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
763 codecs_t *start)
765 return find_codec(fourcc, fourccmap, start, 0);
768 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
769 codecs_t *start, int audioflag)
771 int i, j;
772 codecs_t *c;
774 #if 0
775 if (start) {
776 for (/* NOTHING */; start->name; start++) {
777 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
778 if (start->fourcc[j] == fourcc) {
779 if (fourccmap)
780 *fourccmap = start->fourccmap[j];
781 return start;
785 } else
786 #endif
788 if (audioflag) {
789 i = nr_acodecs;
790 c = audio_codecs;
791 } else {
792 i = nr_vcodecs;
793 c = video_codecs;
795 if(!i) return NULL;
796 for (/* NOTHING */; i--; c++) {
797 if(start && c<=start) continue;
798 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
799 // FIXME: do NOT hardwire 'null' name here:
800 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
801 if (fourccmap)
802 *fourccmap = c->fourccmap[j];
803 return c;
808 return NULL;
811 void select_codec(char* codecname,int audioflag){
812 int i;
813 codecs_t *c;
814 // printf("select_codec('%s')\n",codecname);
815 if (audioflag) {
816 i = nr_acodecs;
817 c = audio_codecs;
818 } else {
819 i = nr_vcodecs;
820 c = video_codecs;
822 if(i)
823 for (/* NOTHING */; i--; c++)
824 if(!strcmp(c->name,codecname))
825 c->flags|=CODECS_FLAG_SELECTED;
828 void codecs_reset_selection(int audioflag){
829 int i;
830 codecs_t *c;
831 if (audioflag) {
832 i = nr_acodecs;
833 c = audio_codecs;
834 } else {
835 i = nr_vcodecs;
836 c = video_codecs;
838 if(i)
839 for (/* NOTHING */; i--; c++)
840 c->flags&=(~CODECS_FLAG_SELECTED);
843 void list_codecs(int audioflag){
844 int i;
845 codecs_t *c;
847 if (audioflag) {
848 i = nr_acodecs;
849 c = audio_codecs;
850 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
851 } else {
852 i = nr_vcodecs;
853 c = video_codecs;
854 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
856 if(!i) return;
857 for (/* NOTHING */; i--; c++) {
858 char* s="unknown ";
859 switch(c->status){
860 case CODECS_STATUS_WORKING: s="working ";break;
861 case CODECS_STATUS_PROBLEMS: s="problems";break;
862 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
863 case CODECS_STATUS_UNTESTED: s="untested";break;
865 if(c->dll)
866 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
867 else
868 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
876 #ifdef CODECS2HTML
878 * Fake out GUI references when building the codecs2html utility.
880 #ifdef HAVE_NEW_GUI
881 void gtkMessageBox( int type,char * str ) { return; }
882 int use_gui = 0;
883 #endif
885 void wrapline(FILE *f2,char *s){
886 int c;
887 if(!s){
888 fprintf(f2,"-");
889 return;
891 while((c=*s++)){
892 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
896 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
897 int c,d;
898 while((c=fgetc(f1))>=0){
899 if(c!='%'){
900 fputc(c,f2);
901 continue;
903 d=fgetc(f1);
905 switch(d){
906 case '.':
907 return; // end of section
908 case 'n':
909 wrapline(f2,codec->name); break;
910 case 'i':
911 wrapline(f2,codec->info); break;
912 case 'c':
913 wrapline(f2,codec->comment); break;
914 case 'd':
915 wrapline(f2,codec->dll); break;
916 case 'D':
917 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
918 case 'F':
919 for(d=0;d<CODECS_MAX_FOURCC;d++)
920 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
921 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
922 break;
923 case 'f':
924 for(d=0;d<CODECS_MAX_FOURCC;d++)
925 if(codec->fourcc[d]!=0xFFFFFFFF)
926 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
927 break;
928 case 'Y':
929 for(d=0;d<CODECS_MAX_OUTFMT;d++)
930 if(codec->outfmt[d]!=0xFFFFFFFF){
931 for (c=0; fmt_table[c].name; c++)
932 if(fmt_table[c].num==codec->outfmt[d]) break;
933 if(fmt_table[c].name)
934 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
936 break;
937 default:
938 fputc(c,f2);
939 fputc(d,f2);
945 void skiphtml(FILE *f1){
946 int c,d;
947 while((c=fgetc(f1))>=0){
948 if(c!='%'){
949 continue;
951 d=fgetc(f1);
952 if(d=='.') return; // end of section
956 static void print_int_array(const int* a, int size)
958 printf("{ ");
959 while (size--)
960 if(abs(*a)<256)
961 printf("%d%s", *a++, size?", ":"");
962 else
963 printf("0x%X%s", *a++, size?", ":"");
964 printf(" }");
967 static void print_char_array(const unsigned char* a, int size)
969 printf("{ ");
970 while (size--)
971 if((*a)<10)
972 printf("%d%s", *a++, size?", ":"");
973 else
974 printf("0x%02x%s", *a++, size?", ":"");
975 printf(" }");
978 static void print_string(const char* s)
980 if (!s) printf("NULL");
981 else printf("\"%s\"", s);
984 int main(int argc, char* argv[])
986 codecs_t *cl;
987 FILE *f1;
988 FILE *f2;
989 int c,d,i;
990 int pos;
991 int section=-1;
992 int nr_codecs;
993 int win32=-1;
994 int dshow=-1;
995 int win32ex=-1;
998 * Take path to codecs.conf from command line, or fall back on
999 * etc/codecs.conf
1001 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1002 exit(1);
1004 if (argc > 1) {
1005 int i, j;
1006 const char* nm[2];
1007 codecs_t* cod[2];
1008 int nr[2];
1010 nm[0] = "builtin_video_codecs";
1011 cod[0] = video_codecs;
1012 nr[0] = nr_vcodecs;
1014 nm[1] = "builtin_audio_codecs";
1015 cod[1] = audio_codecs;
1016 nr[1] = nr_acodecs;
1018 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1020 for (i=0; i<2; i++) {
1021 printf("codecs_t %s[] = {\n", nm[i]);
1022 for (j = 0; j < nr[i]; j++) {
1023 printf("{");
1025 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1026 printf(", /* fourcc */\n");
1028 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1029 printf(", /* fourccmap */\n");
1031 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1032 printf(", /* outfmt */\n");
1034 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1035 printf(", /* outflags */\n");
1037 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1038 printf(", /* infmt */\n");
1040 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1041 printf(", /* inflags */\n");
1043 print_string(cod[i][j].name); printf(", /* name */\n");
1044 print_string(cod[i][j].info); printf(", /* info */\n");
1045 print_string(cod[i][j].comment); printf(", /* comment */\n");
1046 print_string(cod[i][j].dll); printf(", /* dll */\n");
1047 print_string(cod[i][j].drv); printf(", /* drv */\n");
1049 printf("{ 0x%08lx, %hu, %hu,",
1050 cod[i][j].guid.f1,
1051 cod[i][j].guid.f2,
1052 cod[i][j].guid.f3);
1053 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1054 printf(" }, /* GUID */\n");
1055 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1056 cod[i][j].flags,
1057 cod[i][j].status,
1058 cod[i][j].cpuflags);
1059 if (j < nr[i]) printf(",\n");
1061 printf("};\n\n");
1063 exit(0);
1066 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1067 f2=fopen("DOCS/en/codecs-status.html","wb"); if(!f2) exit(1);
1069 while((c=fgetc(f1))>=0){
1070 if(c!='%'){
1071 fputc(c,f2);
1072 continue;
1074 d=fgetc(f1);
1075 if(d>='0' && d<='9'){
1076 // begin section
1077 section=d-'0';
1078 printf("BEGIN %d\n",section);
1079 if(section>=5){
1080 // audio
1081 cl = audio_codecs;
1082 nr_codecs = nr_acodecs;
1083 dshow=7;win32=4;
1084 } else {
1085 // video
1086 cl = video_codecs;
1087 nr_codecs = nr_vcodecs;
1088 dshow=4;win32=2;win32ex=6;
1090 pos=ftell(f1);
1091 for(i=0;i<nr_codecs;i++){
1092 fseek(f1,pos,SEEK_SET);
1093 switch(section){
1094 case 0:
1095 case 5:
1096 if(cl[i].status==CODECS_STATUS_WORKING)
1097 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1098 parsehtml(f1,f2,&cl[i],section,dshow);
1099 break;
1100 #if 0
1101 case 1:
1102 case 6:
1103 if(cl[i].status==CODECS_STATUS_WORKING)
1104 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1105 parsehtml(f1,f2,&cl[i],section,dshow);
1106 break;
1107 #endif
1108 case 2:
1109 case 7:
1110 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1111 parsehtml(f1,f2,&cl[i],section,dshow);
1112 break;
1113 case 3:
1114 case 8:
1115 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1116 parsehtml(f1,f2,&cl[i],section,dshow);
1117 break;
1118 case 4:
1119 case 9:
1120 if(cl[i].status==CODECS_STATUS_UNTESTED)
1121 parsehtml(f1,f2,&cl[i],section,dshow);
1122 break;
1123 default:
1124 printf("Warning! unimplemented section: %d\n",section);
1127 fseek(f1,pos,SEEK_SET);
1128 skiphtml(f1);
1129 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1131 continue;
1133 fputc(c,f2);
1134 fputc(d,f2);
1137 fclose(f2);
1138 fclose(f1);
1139 return 0;
1142 #endif
1144 #ifdef TESTING
1145 int main(void)
1147 codecs_t *c;
1148 int i,j, nr_codecs, state;
1150 if (!(parse_codec_cfg("etc/codecs.conf")))
1151 return 0;
1152 if (!video_codecs)
1153 printf("no videoconfig.\n");
1154 if (!audio_codecs)
1155 printf("no audioconfig.\n");
1157 printf("videocodecs:\n");
1158 c = video_codecs;
1159 nr_codecs = nr_vcodecs;
1160 state = 0;
1161 next:
1162 if (c) {
1163 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1164 nr_codecs);
1165 for(i=0;i<nr_codecs;i++, c++){
1166 printf("\n============== %scodec %02d ===============\n",
1167 state==0?"video":"audio",i);
1168 printf("name='%s'\n",c->name);
1169 printf("info='%s'\n",c->info);
1170 printf("comment='%s'\n",c->comment);
1171 printf("dll='%s'\n",c->dll);
1172 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1173 c->flags, c->driver, c->status, c->cpuflags);
1175 for(j=0;j<CODECS_MAX_FOURCC;j++){
1176 if(c->fourcc[j]!=0xFFFFFFFF){
1177 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1181 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1182 if(c->outfmt[j]!=0xFFFFFFFF){
1183 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1187 for(j=0;j<CODECS_MAX_INFMT;j++){
1188 if(c->infmt[j]!=0xFFFFFFFF){
1189 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1193 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1194 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1195 printf("\n");
1200 if (!state) {
1201 printf("audiocodecs:\n");
1202 c = audio_codecs;
1203 nr_codecs = nr_acodecs;
1204 state = 1;
1205 goto next;
1207 return 0;
1210 #endif