h/w revision detection patch by Timothy Lee <timothy.lee@siriushk.com>
[mplayer.git] / codec-cfg.c
blob0b15fcade37ae54c1af4cf049723238d005d640b
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;
336 /* XXX fix this: shitty with 'null' codec */
337 if (!c->driver) {
338 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecLacksDriver, c->name);
339 return 0;
341 #endif
343 #if 0
344 #warning codec->driver == 4;... <- ezt nem kellene belehegeszteni...
345 #warning HOL VANNAK DEFINIALVA????????????
346 if (!c->dll && (c->driver == 4 ||
347 (c->driver == 2 && type == TYPE_VIDEO))) {
348 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsDLL, c->name);
349 return 0;
351 #warning guid.f1 lehet 0? honnan lehet tudni, hogy nem adtak meg?
352 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
354 if (type == TYPE_VIDEO)
355 if (c->outfmt[0] == 0xffffffff) {
356 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNeedsOutfmt, c->name);
357 return 0;
359 #endif
360 return 1;
363 static int add_comment(char *s, char **d)
365 int pos;
367 if (!*d)
368 pos = 0;
369 else {
370 pos = strlen(*d);
371 (*d)[pos++] = '\n';
373 if (!(*d = (char *) realloc(*d, pos + strlen(s) + 1))) {
374 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantAllocateComment);
375 return 0;
377 strcpy(*d + pos, s);
378 return 1;
381 static short get_cpuflags(char *s)
383 static char *flagstr[] = {
384 "mmx",
385 "sse",
386 "3dnow",
387 NULL
389 int i;
390 short flags = 0;
392 do {
393 for (i = 0; flagstr[i]; i++)
394 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
395 break;
396 if (!flagstr[i])
397 goto err_out_parse_error;
398 flags |= 1<<i;
399 s += strlen(flagstr[i]);
400 } while (*(s++) == ',');
402 if (*(--s) != '\0')
403 goto err_out_parse_error;
405 return flags;
406 err_out_parse_error:
407 return 0;
410 static FILE *fp;
411 static int line_num = 0;
412 static char *line;
413 static char *token[MAX_NR_TOKEN];
414 static int read_nextline = 1;
416 static int get_token(int min, int max)
418 static int line_pos;
419 int i;
420 char c;
422 if (max >= MAX_NR_TOKEN) {
423 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN);
424 goto out_eof;
427 memset(token, 0x00, sizeof(*token) * max);
429 if (read_nextline) {
430 if (!fgets(line, MAX_LINE_LEN, fp))
431 goto out_eof;
432 line_pos = 0;
433 ++line_num;
434 read_nextline = 0;
436 for (i = 0; i < max; i++) {
437 while (isspace(line[line_pos]))
438 ++line_pos;
439 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
440 line[line_pos] == ';') {
441 read_nextline = 1;
442 if (i >= min)
443 goto out_ok;
444 goto out_eol;
446 token[i] = line + line_pos;
447 c = line[line_pos];
448 if (c == '"' || c == '\'') {
449 token[i]++;
450 while (line[++line_pos] != c && line[line_pos])
451 /* NOTHING */;
452 } else {
453 for (/* NOTHING */; !isspace(line[line_pos]) &&
454 line[line_pos]; line_pos++)
455 /* NOTHING */;
457 if (!line[line_pos]) {
458 read_nextline = 1;
459 if (i >= min - 1)
460 goto out_ok;
461 goto out_eol;
463 line[line_pos] = '\0';
464 line_pos++;
466 out_ok:
467 return i;
468 out_eof:
469 read_nextline = 1;
470 return RET_EOF;
471 out_eol:
472 return RET_EOL;
475 static codecs_t *video_codecs=NULL;
476 static codecs_t *audio_codecs=NULL;
477 static int nr_vcodecs = 0;
478 static int nr_acodecs = 0;
480 int parse_codec_cfg(char *cfgfile)
482 codecs_t *codec = NULL; // current codec
483 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
484 char *endptr; // strtoul()...
485 int *nr_codecsp;
486 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
487 int tmp, i;
489 // in case we call it a second time
490 codecs_uninit_free();
492 nr_vcodecs = 0;
493 nr_acodecs = 0;
495 if(cfgfile==NULL) {
496 #ifdef CODECS2HTML
497 return 0;
498 #else
499 video_codecs = builtin_video_codecs;
500 audio_codecs = builtin_audio_codecs;
501 nr_vcodecs = sizeof(builtin_video_codecs)/sizeof(codecs_t);
502 nr_acodecs = sizeof(builtin_audio_codecs)/sizeof(codecs_t);
503 return 1;
504 #endif
507 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_ReadingFile, cfgfile);
509 if ((fp = fopen(cfgfile, "r")) == NULL) {
510 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantOpenFileError, cfgfile, strerror(errno));
511 return 0;
514 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
515 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantGetMemoryForLine, strerror(errno));
516 return 0;
518 read_nextline = 1;
521 * this only catches release lines at the start of
522 * codecs.conf, before audiocodecs and videocodecs.
524 while ((tmp = get_token(1, 1)) == RET_EOL)
525 /* NOTHING */;
526 if (tmp == RET_EOF)
527 goto out;
528 if (!strcmp(token[0], "release")) {
529 if (get_token(1, 2) < 0)
530 goto err_out_parse_error;
531 tmp = atoi(token[0]);
532 if (tmp < CODEC_CFG_MIN)
533 goto err_out_release_num;
534 while ((tmp = get_token(1, 1)) == RET_EOL)
535 /* NOTHING */;
536 if (tmp == RET_EOF)
537 goto out;
538 } else
539 goto err_out_release_num;
542 * check if the next block starts with 'audiocodec' or
543 * with 'videocodec'
545 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
546 goto loop_enter;
547 goto err_out_parse_error;
549 while ((tmp = get_token(1, 1)) != RET_EOF) {
550 if (tmp == RET_EOL)
551 continue;
552 if (!strcmp(token[0], "audiocodec") ||
553 !strcmp(token[0], "videocodec")) {
554 if (!validate_codec(codec, codec_type))
555 goto err_out_not_valid;
556 loop_enter:
557 if (*token[0] == 'v') {
558 codec_type = TYPE_VIDEO;
559 nr_codecsp = &nr_vcodecs;
560 codecsp = &video_codecs;
561 } else if (*token[0] == 'a') {
562 codec_type = TYPE_AUDIO;
563 nr_codecsp = &nr_acodecs;
564 codecsp = &audio_codecs;
565 #ifdef DEBUG
566 } else {
567 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
568 goto err_out;
569 #endif
571 if (!(*codecsp = (codecs_t *) realloc(*codecsp,
572 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
573 mp_msg(MSGT_CODECCFG,MSGL_FATAL,MSGTR_CantReallocCodecsp, strerror(errno));
574 goto err_out;
576 codec=*codecsp + *nr_codecsp;
577 ++*nr_codecsp;
578 memset(codec,0,sizeof(codecs_t));
579 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
580 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
581 memset(codec->infmt, 0xff, sizeof(codec->infmt));
583 if (get_token(1, 1) < 0)
584 goto err_out_parse_error;
585 for (i = 0; i < *nr_codecsp - 1; i++) {
586 if(( (*codecsp)[i].name!=NULL) &&
587 (!strcmp(token[0], (*codecsp)[i].name)) ) {
588 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecNameNotUnique, token[0]);
589 goto err_out_print_linenum;
592 if (!(codec->name = strdup(token[0]))) {
593 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupName, strerror(errno));
594 goto err_out;
596 } else if (!strcmp(token[0], "info")) {
597 if (codec->info || get_token(1, 1) < 0)
598 goto err_out_parse_error;
599 if (!(codec->info = strdup(token[0]))) {
600 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupInfo, strerror(errno));
601 goto err_out;
603 } else if (!strcmp(token[0], "comment")) {
604 if (get_token(1, 1) < 0)
605 goto err_out_parse_error;
606 add_comment(token[0], &codec->comment);
607 } else if (!strcmp(token[0], "fourcc")) {
608 if (get_token(1, 2) < 0)
609 goto err_out_parse_error;
610 if (!add_to_fourcc(token[0], token[1],
611 codec->fourcc,
612 codec->fourccmap))
613 goto err_out_print_linenum;
614 } else if (!strcmp(token[0], "format")) {
615 if (get_token(1, 2) < 0)
616 goto err_out_parse_error;
617 if (!add_to_format(token[0], token[1],
618 codec->fourcc,codec->fourccmap))
619 goto err_out_print_linenum;
620 } else if (!strcmp(token[0], "driver")) {
621 if (get_token(1, 1) < 0)
622 goto err_out_parse_error;
623 if (!(codec->drv = strdup(token[0]))) {
624 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDriver, strerror(errno));
625 goto err_out;
627 } else if (!strcmp(token[0], "dll")) {
628 if (get_token(1, 1) < 0)
629 goto err_out_parse_error;
630 if (!(codec->dll = strdup(token[0]))) {
631 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CantStrdupDLL, strerror(errno));
632 goto err_out;
634 } else if (!strcmp(token[0], "guid")) {
635 if (get_token(11, 11) < 0)
636 goto err_out_parse_error;
637 codec->guid.f1=strtoul(token[0],&endptr,0);
638 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
639 *endptr != '\0')
640 goto err_out_parse_error;
641 codec->guid.f2=strtoul(token[1],&endptr,0);
642 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
643 *endptr != '\0')
644 goto err_out_parse_error;
645 codec->guid.f3=strtoul(token[2],&endptr,0);
646 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
647 *endptr != '\0')
648 goto err_out_parse_error;
649 for (i = 0; i < 8; i++) {
650 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
651 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
652 *endptr != '\0')
653 goto err_out_parse_error;
655 } else if (!strcmp(token[0], "out")) {
656 if (get_token(1, 2) < 0)
657 goto err_out_parse_error;
658 if (!add_to_inout(token[0], token[1], codec->outfmt,
659 codec->outflags))
660 goto err_out_print_linenum;
661 } else if (!strcmp(token[0], "in")) {
662 if (get_token(1, 2) < 0)
663 goto err_out_parse_error;
664 if (!add_to_inout(token[0], token[1], codec->infmt,
665 codec->inflags))
666 goto err_out_print_linenum;
667 } else if (!strcmp(token[0], "flags")) {
668 if (get_token(1, 1) < 0)
669 goto err_out_parse_error;
670 if (!strcmp(token[0], "seekable"))
671 codec->flags |= CODECS_FLAG_SEEKABLE;
672 else
673 if (!strcmp(token[0], "align16"))
674 codec->flags |= CODECS_FLAG_ALIGN16;
675 else
676 goto err_out_parse_error;
677 } else if (!strcmp(token[0], "status")) {
678 if (get_token(1, 1) < 0)
679 goto err_out_parse_error;
680 if (!strcasecmp(token[0], "working"))
681 codec->status = CODECS_STATUS_WORKING;
682 else if (!strcasecmp(token[0], "crashing"))
683 codec->status = CODECS_STATUS_NOT_WORKING;
684 else if (!strcasecmp(token[0], "untested"))
685 codec->status = CODECS_STATUS_UNTESTED;
686 else if (!strcasecmp(token[0], "buggy"))
687 codec->status = CODECS_STATUS_PROBLEMS;
688 else
689 goto err_out_parse_error;
690 } else if (!strcmp(token[0], "cpuflags")) {
691 if (get_token(1, 1) < 0)
692 goto err_out_parse_error;
693 if (!(codec->cpuflags = get_cpuflags(token[0])))
694 goto err_out_parse_error;
695 } else
696 goto err_out_parse_error;
698 if (!validate_codec(codec, codec_type))
699 goto err_out_not_valid;
700 mp_msg(MSGT_CODECCFG,MSGL_INFO,MSGTR_AudioVideoCodecTotals, nr_acodecs, nr_vcodecs);
701 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
702 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
703 out:
704 free(line);
705 line=NULL;
706 fclose(fp);
707 return 1;
709 err_out_parse_error:
710 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_ParseError);
711 err_out_print_linenum:
712 PRINT_LINENUM;
713 err_out:
714 codecs_uninit_free();
716 free(line);
717 line=NULL;
718 line_num = 0;
719 fclose(fp);
720 return 0;
721 err_out_not_valid:
722 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_CodecDefinitionIncorrect);
723 goto err_out_print_linenum;
724 err_out_release_num:
725 mp_msg(MSGT_CODECCFG,MSGL_ERR,MSGTR_OutdatedCodecsConf);
726 goto err_out_print_linenum;
729 static void codecs_free(codecs_t* codecs,int count) {
730 int i;
731 for ( i = 0; i < count; i++)
732 if ( (codecs[i]).name ) {
733 if( (codecs[i]).name )
734 free((codecs[i]).name);
735 if( (codecs[i]).info )
736 free((codecs[i]).info);
737 if( (codecs[i]).comment )
738 free((codecs[i]).comment);
739 if( (codecs[i]).dll )
740 free((codecs[i]).dll);
741 if( (codecs[i]).drv )
742 free((codecs[i]).drv);
744 if (codecs)
745 free(codecs);
748 void codecs_uninit_free() {
749 codecs_free(video_codecs,nr_vcodecs);
750 video_codecs=NULL;
751 codecs_free(audio_codecs,nr_acodecs);
752 audio_codecs=NULL;
755 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
756 codecs_t *start)
758 return find_codec(fourcc, fourccmap, start, 1);
761 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
762 codecs_t *start)
764 return find_codec(fourcc, fourccmap, start, 0);
767 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
768 codecs_t *start, int audioflag)
770 int i, j;
771 codecs_t *c;
773 #if 0
774 if (start) {
775 for (/* NOTHING */; start->name; start++) {
776 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
777 if (start->fourcc[j] == fourcc) {
778 if (fourccmap)
779 *fourccmap = start->fourccmap[j];
780 return start;
784 } else
785 #endif
787 if (audioflag) {
788 i = nr_acodecs;
789 c = audio_codecs;
790 } else {
791 i = nr_vcodecs;
792 c = video_codecs;
794 if(!i) return NULL;
795 for (/* NOTHING */; i--; c++) {
796 if(start && c<=start) continue;
797 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
798 // FIXME: do NOT hardwire 'null' name here:
799 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
800 if (fourccmap)
801 *fourccmap = c->fourccmap[j];
802 return c;
807 return NULL;
810 void select_codec(char* codecname,int audioflag){
811 int i;
812 codecs_t *c;
813 // printf("select_codec('%s')\n",codecname);
814 if (audioflag) {
815 i = nr_acodecs;
816 c = audio_codecs;
817 } else {
818 i = nr_vcodecs;
819 c = video_codecs;
821 if(i)
822 for (/* NOTHING */; i--; c++)
823 if(!strcmp(c->name,codecname))
824 c->flags|=CODECS_FLAG_SELECTED;
827 void codecs_reset_selection(int audioflag){
828 int i;
829 codecs_t *c;
830 if (audioflag) {
831 i = nr_acodecs;
832 c = audio_codecs;
833 } else {
834 i = nr_vcodecs;
835 c = video_codecs;
837 if(i)
838 for (/* NOTHING */; i--; c++)
839 c->flags&=(~CODECS_FLAG_SELECTED);
842 void list_codecs(int audioflag){
843 int i;
844 codecs_t *c;
846 if (audioflag) {
847 i = nr_acodecs;
848 c = audio_codecs;
849 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
850 } else {
851 i = nr_vcodecs;
852 c = video_codecs;
853 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
855 if(!i) return;
856 for (/* NOTHING */; i--; c++) {
857 char* s="unknown ";
858 switch(c->status){
859 case CODECS_STATUS_WORKING: s="working ";break;
860 case CODECS_STATUS_PROBLEMS: s="problems";break;
861 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
862 case CODECS_STATUS_UNTESTED: s="untested";break;
864 if(c->dll)
865 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
866 else
867 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
875 #ifdef CODECS2HTML
877 * Fake out GUI references when building the codecs2html utility.
879 #ifdef HAVE_NEW_GUI
880 void gtkMessageBox( int type,char * str ) { return; }
881 int use_gui = 0;
882 #endif
884 void wrapline(FILE *f2,char *s){
885 int c;
886 if(!s){
887 fprintf(f2,"-");
888 return;
890 while((c=*s++)){
891 if(c==',') fprintf(f2,"<br>"); else fputc(c,f2);
895 void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
896 int c,d;
897 while((c=fgetc(f1))>=0){
898 if(c!='%'){
899 fputc(c,f2);
900 continue;
902 d=fgetc(f1);
904 switch(d){
905 case '.':
906 return; // end of section
907 case 'n':
908 wrapline(f2,codec->name); break;
909 case 'i':
910 wrapline(f2,codec->info); break;
911 case 'c':
912 wrapline(f2,codec->comment); break;
913 case 'd':
914 wrapline(f2,codec->dll); break;
915 case 'D':
916 fprintf(f2,"%c",!strcmp(codec->drv,"dshow")?'+':'-'); break;
917 case 'F':
918 for(d=0;d<CODECS_MAX_FOURCC;d++)
919 if(!d || codec->fourcc[d]!=0xFFFFFFFF)
920 fprintf(f2,"%s%.4s",d?"<br>":"",(codec->fourcc[d]==0xFFFFFFFF || codec->fourcc[d]<0x20202020)?!d?"-":"":(char*) &codec->fourcc[d]);
921 break;
922 case 'f':
923 for(d=0;d<CODECS_MAX_FOURCC;d++)
924 if(codec->fourcc[d]!=0xFFFFFFFF)
925 fprintf(f2,"%s0x%X",d?"<br>":"",codec->fourcc[d]);
926 break;
927 case 'Y':
928 for(d=0;d<CODECS_MAX_OUTFMT;d++)
929 if(codec->outfmt[d]!=0xFFFFFFFF){
930 for (c=0; fmt_table[c].name; c++)
931 if(fmt_table[c].num==codec->outfmt[d]) break;
932 if(fmt_table[c].name)
933 fprintf(f2,"%s%s",d?"<br>":"",fmt_table[c].name);
935 break;
936 default:
937 fputc(c,f2);
938 fputc(d,f2);
944 void skiphtml(FILE *f1){
945 int c,d;
946 while((c=fgetc(f1))>=0){
947 if(c!='%'){
948 continue;
950 d=fgetc(f1);
951 if(d=='.') return; // end of section
955 static void print_int_array(const int* a, int size)
957 printf("{ ");
958 while (size--)
959 if(abs(*a)<256)
960 printf("%d%s", *a++, size?", ":"");
961 else
962 printf("0x%X%s", *a++, size?", ":"");
963 printf(" }");
966 static void print_char_array(const unsigned char* a, int size)
968 printf("{ ");
969 while (size--)
970 if((*a)<10)
971 printf("%d%s", *a++, size?", ":"");
972 else
973 printf("0x%02x%s", *a++, size?", ":"");
974 printf(" }");
977 static void print_string(const char* s)
979 if (!s) printf("NULL");
980 else printf("\"%s\"", s);
983 int main(int argc, char* argv[])
985 codecs_t *cl;
986 FILE *f1;
987 FILE *f2;
988 int c,d,i;
989 int pos;
990 int section=-1;
991 int nr_codecs;
992 int win32=-1;
993 int dshow=-1;
994 int win32ex=-1;
997 * Take path to codecs.conf from command line, or fall back on
998 * etc/codecs.conf
1000 if (!(nr_codecs = parse_codec_cfg((argc>1)?argv[1]:"etc/codecs.conf")))
1001 exit(1);
1003 if (argc > 1) {
1004 int i, j;
1005 const char* nm[2];
1006 codecs_t* cod[2];
1007 int nr[2];
1009 nm[0] = "builtin_video_codecs";
1010 cod[0] = video_codecs;
1011 nr[0] = nr_vcodecs;
1013 nm[1] = "builtin_audio_codecs";
1014 cod[1] = audio_codecs;
1015 nr[1] = nr_acodecs;
1017 printf("/* GENERATED FROM %s, DO NOT EDIT! */\n\n",argv[1]);
1019 for (i=0; i<2; i++) {
1020 printf("codecs_t %s[] = {\n", nm[i]);
1021 for (j = 0; j < nr[i]; j++) {
1022 printf("{");
1024 print_int_array(cod[i][j].fourcc, CODECS_MAX_FOURCC);
1025 printf(", /* fourcc */\n");
1027 print_int_array(cod[i][j].fourccmap, CODECS_MAX_FOURCC);
1028 printf(", /* fourccmap */\n");
1030 print_int_array(cod[i][j].outfmt, CODECS_MAX_OUTFMT);
1031 printf(", /* outfmt */\n");
1033 print_char_array(cod[i][j].outflags, CODECS_MAX_OUTFMT);
1034 printf(", /* outflags */\n");
1036 print_int_array(cod[i][j].infmt, CODECS_MAX_INFMT);
1037 printf(", /* infmt */\n");
1039 print_char_array(cod[i][j].inflags, CODECS_MAX_INFMT);
1040 printf(", /* inflags */\n");
1042 print_string(cod[i][j].name); printf(", /* name */\n");
1043 print_string(cod[i][j].info); printf(", /* info */\n");
1044 print_string(cod[i][j].comment); printf(", /* comment */\n");
1045 print_string(cod[i][j].dll); printf(", /* dll */\n");
1046 print_string(cod[i][j].drv); printf(", /* drv */\n");
1048 printf("{ 0x%08lx, %hu, %hu,",
1049 cod[i][j].guid.f1,
1050 cod[i][j].guid.f2,
1051 cod[i][j].guid.f3);
1052 print_char_array(cod[i][j].guid.f4, sizeof(cod[i][j].guid.f4));
1053 printf(" }, /* GUID */\n");
1054 printf("%hd /* flags */, %hd /* status */, %hd /* cpuflags */ }\n",
1055 cod[i][j].flags,
1056 cod[i][j].status,
1057 cod[i][j].cpuflags);
1058 if (j < nr[i]) printf(",\n");
1060 printf("};\n\n");
1062 exit(0);
1065 f1=fopen("DOCS/tech/codecs-in.html","rb"); if(!f1) exit(1);
1066 f2=fopen("DOCS/en/codecs-status.html","wb"); if(!f2) exit(1);
1068 while((c=fgetc(f1))>=0){
1069 if(c!='%'){
1070 fputc(c,f2);
1071 continue;
1073 d=fgetc(f1);
1074 if(d>='0' && d<='9'){
1075 // begin section
1076 section=d-'0';
1077 printf("BEGIN %d\n",section);
1078 if(section>=5){
1079 // audio
1080 cl = audio_codecs;
1081 nr_codecs = nr_acodecs;
1082 dshow=7;win32=4;
1083 } else {
1084 // video
1085 cl = video_codecs;
1086 nr_codecs = nr_vcodecs;
1087 dshow=4;win32=2;win32ex=6;
1089 pos=ftell(f1);
1090 for(i=0;i<nr_codecs;i++){
1091 fseek(f1,pos,SEEK_SET);
1092 switch(section){
1093 case 0:
1094 case 5:
1095 if(cl[i].status==CODECS_STATUS_WORKING)
1096 // if(!(!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1097 parsehtml(f1,f2,&cl[i],section,dshow);
1098 break;
1099 #if 0
1100 case 1:
1101 case 6:
1102 if(cl[i].status==CODECS_STATUS_WORKING)
1103 if((!strcmp(cl[i].drv,"vfw") || !strcmp(cl[i].drv,"dshow") || !strcmp(cl[i].drv,"vfwex") || !strcmp(cl[i].drv,"acm")))
1104 parsehtml(f1,f2,&cl[i],section,dshow);
1105 break;
1106 #endif
1107 case 2:
1108 case 7:
1109 if(cl[i].status==CODECS_STATUS_PROBLEMS)
1110 parsehtml(f1,f2,&cl[i],section,dshow);
1111 break;
1112 case 3:
1113 case 8:
1114 if(cl[i].status==CODECS_STATUS_NOT_WORKING)
1115 parsehtml(f1,f2,&cl[i],section,dshow);
1116 break;
1117 case 4:
1118 case 9:
1119 if(cl[i].status==CODECS_STATUS_UNTESTED)
1120 parsehtml(f1,f2,&cl[i],section,dshow);
1121 break;
1122 default:
1123 printf("Warning! unimplemented section: %d\n",section);
1126 fseek(f1,pos,SEEK_SET);
1127 skiphtml(f1);
1128 //void parsehtml(FILE *f1,FILE *f2,codecs_t *codec,int section,int dshow){
1130 continue;
1132 fputc(c,f2);
1133 fputc(d,f2);
1136 fclose(f2);
1137 fclose(f1);
1138 return 0;
1141 #endif
1143 #ifdef TESTING
1144 int main(void)
1146 codecs_t *c;
1147 int i,j, nr_codecs, state;
1149 if (!(parse_codec_cfg("etc/codecs.conf")))
1150 return 0;
1151 if (!video_codecs)
1152 printf("no videoconfig.\n");
1153 if (!audio_codecs)
1154 printf("no audioconfig.\n");
1156 printf("videocodecs:\n");
1157 c = video_codecs;
1158 nr_codecs = nr_vcodecs;
1159 state = 0;
1160 next:
1161 if (c) {
1162 printf("number of %scodecs: %d\n", state==0?"video":"audio",
1163 nr_codecs);
1164 for(i=0;i<nr_codecs;i++, c++){
1165 printf("\n============== %scodec %02d ===============\n",
1166 state==0?"video":"audio",i);
1167 printf("name='%s'\n",c->name);
1168 printf("info='%s'\n",c->info);
1169 printf("comment='%s'\n",c->comment);
1170 printf("dll='%s'\n",c->dll);
1171 printf("flags=%X driver=%d status=%d cpuflags=%d\n",
1172 c->flags, c->driver, c->status, c->cpuflags);
1174 for(j=0;j<CODECS_MAX_FOURCC;j++){
1175 if(c->fourcc[j]!=0xFFFFFFFF){
1176 printf("fourcc %02d: %08X (%.4s) ===> %08X (%.4s)\n",j,c->fourcc[j],(char *) &c->fourcc[j],c->fourccmap[j],(char *) &c->fourccmap[j]);
1180 for(j=0;j<CODECS_MAX_OUTFMT;j++){
1181 if(c->outfmt[j]!=0xFFFFFFFF){
1182 printf("outfmt %02d: %08X (%.4s) flags: %d\n",j,c->outfmt[j],(char *) &c->outfmt[j],c->outflags[j]);
1186 for(j=0;j<CODECS_MAX_INFMT;j++){
1187 if(c->infmt[j]!=0xFFFFFFFF){
1188 printf("infmt %02d: %08X (%.4s) flags: %d\n",j,c->infmt[j],(char *) &c->infmt[j],c->inflags[j]);
1192 printf("GUID: %08lX %04X %04X",c->guid.f1,c->guid.f2,c->guid.f3);
1193 for(j=0;j<8;j++) printf(" %02X",c->guid.f4[j]);
1194 printf("\n");
1199 if (!state) {
1200 printf("audiocodecs:\n");
1201 c = audio_codecs;
1202 nr_codecs = nr_acodecs;
1203 state = 1;
1204 goto next;
1206 return 0;
1209 #endif