Makefile: delete .d files in "clean" target too
[mplayer.git] / codec-cfg.c
blob199ba70f19e52be1ce746478618e1e79aaf102e0
1 /*
2 * codecs.conf parser
4 * Copyright (C) 2001 Szabolcs Berecz <szabi@inf.elte.hu>
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #define DEBUG
25 //disable asserts
26 #define NDEBUG
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <assert.h>
35 #include <string.h>
36 #include <stdint.h>
38 #include "config.h"
39 #include "mp_msg.h"
40 #include "libmpcodecs/img_format.h"
41 #include "codec-cfg.h"
42 #include "bstr.h"
43 #include "stream/stream.h"
44 #include "path.h"
46 static const char embedded_file[] =
47 #include "codecs.conf.h"
49 static const struct bstr builtin_codecs_conf = {
50 .start = (char *)embedded_file, .len = sizeof(embedded_file) - 1
53 #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
54 ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
55 ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
57 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
59 #define MAX_NR_TOKEN 16
61 #define RET_EOF -1
62 #define RET_EOL -2
64 #define TYPE_VIDEO 0
65 #define TYPE_AUDIO 1
67 static int codecs_conf_release;
68 char * codecs_file = NULL;
70 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
71 unsigned int *map)
73 int i, j, freeslots;
74 unsigned int tmp;
76 /* find first unused slot */
77 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
78 /* NOTHING */;
79 freeslots = CODECS_MAX_FOURCC - i;
80 if (!freeslots)
81 goto err_out_too_many;
83 do {
84 if (strlen(s) < 4)
85 goto err_out_parse_error;
86 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
87 for (j = 0; j < i; j++)
88 if (tmp == fourcc[j])
89 goto err_out_duplicated;
90 fourcc[i] = tmp;
91 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
92 s += 4;
93 i++;
94 } while ((*(s++) == ',') && --freeslots);
96 if (!freeslots)
97 goto err_out_too_many;
98 if (*(--s) != '\0')
99 goto err_out_parse_error;
100 return 1;
101 err_out_duplicated:
102 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
103 return 0;
104 err_out_too_many:
105 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
106 return 0;
107 err_out_parse_error:
108 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
109 return 0;
112 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
114 int i, j;
115 char *endptr;
117 /* find first unused slot */
118 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
119 /* NOTHING */;
120 if (i == CODECS_MAX_FOURCC) {
121 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
122 return 0;
125 fourcc[i]=strtoul(s,&endptr,0);
126 if (*endptr != '\0') {
127 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
128 return 0;
131 if(alias){
132 fourccmap[i]=strtoul(alias,&endptr,0);
133 if (*endptr != '\0') {
134 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
135 return 0;
137 } else
138 fourccmap[i]=fourcc[i];
140 for (j = 0; j < i; j++)
141 if (fourcc[j] == fourcc[i]) {
142 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
143 return 0;
146 return 1;
149 static const struct {
150 const char *name;
151 const unsigned int num;
152 } fmt_table[] = {
153 // note: due to parser deficiencies/simplicity, if one format
154 // name matches the beginning of another, the longer one _must_
155 // come first in this list.
156 {"YV12", IMGFMT_YV12},
157 {"I420", IMGFMT_I420},
158 {"IYUV", IMGFMT_IYUV},
159 {"NV12", IMGFMT_NV12},
160 {"NV21", IMGFMT_NV21},
161 {"YVU9", IMGFMT_YVU9},
162 {"IF09", IMGFMT_IF09},
163 {"444P16LE", IMGFMT_444P16_LE},
164 {"444P16BE", IMGFMT_444P16_BE},
165 {"422P16LE", IMGFMT_422P16_LE},
166 {"422P16BE", IMGFMT_422P16_BE},
167 {"420P16LE", IMGFMT_420P16_LE},
168 {"420P16BE", IMGFMT_420P16_BE},
169 {"444P16", IMGFMT_444P16},
170 {"444P10", IMGFMT_444P10},
171 {"444P9", IMGFMT_444P9},
172 {"422P16", IMGFMT_422P16},
173 {"422P10", IMGFMT_422P10},
174 {"420P16", IMGFMT_420P16},
175 {"420P10", IMGFMT_420P10},
176 {"420P9", IMGFMT_420P9},
177 {"420A", IMGFMT_420A},
178 {"444P", IMGFMT_444P},
179 {"422P", IMGFMT_422P},
180 {"411P", IMGFMT_411P},
181 {"440P", IMGFMT_440P},
182 {"Y800", IMGFMT_Y800},
183 {"Y8", IMGFMT_Y8},
185 {"YUY2", IMGFMT_YUY2},
186 {"UYVY", IMGFMT_UYVY},
187 {"YVYU", IMGFMT_YVYU},
189 {"RGB48LE", IMGFMT_RGB48LE},
190 {"RGB48BE", IMGFMT_RGB48BE},
191 {"RGB4", IMGFMT_RGB4},
192 {"RGB8", IMGFMT_RGB8},
193 {"RGB15", IMGFMT_RGB15},
194 {"RGB16", IMGFMT_RGB16},
195 {"RGB24", IMGFMT_RGB24},
196 {"RGB32", IMGFMT_RGB32},
197 {"BGR4", IMGFMT_BGR4},
198 {"BGR8", IMGFMT_BGR8},
199 {"BGR15", IMGFMT_BGR15},
200 {"BGR16", IMGFMT_BGR16},
201 {"BGR24", IMGFMT_BGR24},
202 {"BGR32", IMGFMT_BGR32},
203 {"RGB1", IMGFMT_RGB1},
204 {"BGR1", IMGFMT_BGR1},
206 {"MPES", IMGFMT_MPEGPES},
208 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
209 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
211 {"VDPAU_MPEG1",IMGFMT_VDPAU_MPEG1},
212 {"VDPAU_MPEG2",IMGFMT_VDPAU_MPEG2},
213 {"VDPAU_H264",IMGFMT_VDPAU_H264},
214 {"VDPAU_WMV3",IMGFMT_VDPAU_WMV3},
215 {"VDPAU_VC1",IMGFMT_VDPAU_VC1},
216 {"VDPAU_MPEG4",IMGFMT_VDPAU_MPEG4},
218 {NULL, 0}
222 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
223 unsigned char *outflags)
226 static char *flagstr[] = {
227 "flip",
228 "noflip",
229 "yuvhack",
230 "query",
231 "static",
232 NULL
235 int i, j, freeslots;
236 unsigned char flags;
238 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
239 /* NOTHING */;
240 freeslots = CODECS_MAX_OUTFMT - i;
241 if (!freeslots)
242 goto err_out_too_many;
244 flags = 0;
245 if(sflags) {
246 do {
247 for (j = 0; flagstr[j] != NULL; j++)
248 if (!strncmp(sflags, flagstr[j],
249 strlen(flagstr[j])))
250 break;
251 if (flagstr[j] == NULL)
252 goto err_out_parse_error;
253 flags|=(1<<j);
254 sflags+=strlen(flagstr[j]);
255 } while (*(sflags++) == ',');
257 if (*(--sflags) != '\0')
258 goto err_out_parse_error;
261 do {
262 for (j = 0; fmt_table[j].name != NULL; j++)
263 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
264 break;
265 if (fmt_table[j].name == NULL)
266 goto err_out_parse_error;
267 outfmt[i] = fmt_table[j].num;
268 outflags[i] = flags;
269 ++i;
270 sfmt+=strlen(fmt_table[j].name);
271 } while ((*(sfmt++) == ',') && --freeslots);
273 if (!freeslots)
274 goto err_out_too_many;
276 if (*(--sfmt) != '\0')
277 goto err_out_parse_error;
279 return 1;
280 err_out_too_many:
281 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many out...");
282 return 0;
283 err_out_parse_error:
284 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
285 return 0;
288 static int validate_codec(codecs_t *c, int type)
290 unsigned int i;
291 char *tmp_name = c->name;
293 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
294 /* NOTHING */;
296 if (i < strlen(tmp_name)) {
297 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
298 return 0;
301 if (!c->info)
302 c->info = strdup(c->name);
304 #if 0
305 if (c->fourcc[0] == 0xffffffff) {
306 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have FourCC/format!\n", c->name);
307 return 0;
309 #endif
311 if (!c->drv) {
312 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
313 return 0;
316 #if 0
317 //FIXME: codec->driver == 4;... <- this should not be put in here...
318 //FIXME: Where are they defined ????????????
319 if (!c->dll && (c->driver == 4 ||
320 (c->driver == 2 && type == TYPE_VIDEO))) {
321 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs a 'dll'!\n", c->name);
322 return 0;
324 // FIXME: Can guid.f1 be 0? How does one know that it was not given?
325 // if (!(codec->flags & CODECS_FLAG_AUDIO) && codec->driver == 4)
327 if (type == TYPE_VIDEO)
328 if (c->outfmt[0] == 0xffffffff) {
329 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) needs an 'outfmt'!\n", c->name);
330 return 0;
332 #endif
333 return 1;
336 static int add_comment(char *s, char **d)
338 int pos;
340 if (!*d)
341 pos = 0;
342 else {
343 pos = strlen(*d);
344 (*d)[pos++] = '\n';
346 if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
347 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
348 return 0;
350 strcpy(*d + pos, s);
351 return 1;
354 static short get_cpuflags(char *s)
356 static char *flagstr[] = {
357 "mmx",
358 "sse",
359 "3dnow",
360 NULL
362 int i;
363 short flags = 0;
365 do {
366 for (i = 0; flagstr[i]; i++)
367 if (!strncmp(s, flagstr[i], strlen(flagstr[i])))
368 break;
369 if (!flagstr[i])
370 goto err_out_parse_error;
371 flags |= 1<<i;
372 s += strlen(flagstr[i]);
373 } while (*(s++) == ',');
375 if (*(--s) != '\0')
376 goto err_out_parse_error;
378 return flags;
379 err_out_parse_error:
380 return 0;
383 static struct bstr filetext;
384 static int line_num = 0;
385 static char *line;
386 static char *token[MAX_NR_TOKEN];
387 static int read_nextline = 1;
389 static int get_token(int min, int max)
391 static int line_pos;
392 int i;
393 char c;
395 if (max >= MAX_NR_TOKEN) {
396 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_MR_TOKEN!");
397 goto out_eof;
400 memset(token, 0x00, sizeof(*token) * max);
402 if (read_nextline) {
403 if (!filetext.len)
404 goto out_eof;
405 struct bstr nextline = bstr_getline(filetext, &filetext);
406 line = nextline.start;
407 line[nextline.len - 1] = 0;
408 line_pos = 0;
409 ++line_num;
410 read_nextline = 0;
412 for (i = 0; i < max; i++) {
413 while (isspace(line[line_pos]))
414 ++line_pos;
415 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
416 line[line_pos] == ';') {
417 read_nextline = 1;
418 if (i >= min)
419 goto out_ok;
420 goto out_eol;
422 token[i] = line + line_pos;
423 c = line[line_pos];
424 if (c == '"' || c == '\'') {
425 token[i]++;
426 while (line[++line_pos] != c && line[line_pos])
427 /* NOTHING */;
428 } else {
429 for (/* NOTHING */; !isspace(line[line_pos]) &&
430 line[line_pos]; line_pos++)
431 /* NOTHING */;
433 if (!line[line_pos]) {
434 read_nextline = 1;
435 if (i >= min - 1)
436 goto out_ok;
437 goto out_eol;
439 line[line_pos] = '\0';
440 line_pos++;
442 out_ok:
443 return i;
444 out_eof:
445 read_nextline = 1;
446 return RET_EOF;
447 out_eol:
448 return RET_EOL;
451 static codecs_t *video_codecs=NULL;
452 static codecs_t *audio_codecs=NULL;
453 static int nr_vcodecs = 0;
454 static int nr_acodecs = 0;
456 int parse_codec_cfg(const char *cfgfile)
458 codecs_t *codec = NULL; // current codec
459 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
460 char *endptr; // strtoul()...
461 int *nr_codecsp;
462 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
463 int tmp, i;
464 int codec_cfg_min;
466 for (struct bstr s = builtin_codecs_conf; ; bstr_getline(s, &s)) {
467 if (!s.len)
468 abort();
469 if (bstr_eatstart0(&s, "release ")) {
470 codec_cfg_min = atoi(s.start);
471 break;
475 // in case we call it a second time
476 codecs_uninit_free();
478 nr_vcodecs = 0;
479 nr_acodecs = 0;
481 if (cfgfile) {
482 // Avoid printing errors from open_stream when trying optional files
483 if (!mp_path_exists(cfgfile)) {
484 mp_tmsg(MSGT_CODECCFG, MSGL_V,
485 "No optional codecs config file: %s\n", cfgfile);
486 return 0;
488 mp_msg(MSGT_CODECCFG, MSGL_V, "Reading codec config file: %s\n",
489 cfgfile);
490 struct stream *s = open_stream(cfgfile, NULL, NULL);
491 if (!s)
492 return 0;
493 filetext = stream_read_complete(s, NULL, 10000000, 1);
494 free_stream(s);
495 if (!filetext.start)
496 return 0;
497 } else
498 // Parsing modifies the data
499 filetext = bstrdup(NULL, builtin_codecs_conf);
500 void *tmpmem = filetext.start;
502 read_nextline = 1;
505 * this only catches release lines at the start of
506 * codecs.conf, before audiocodecs and videocodecs.
508 while ((tmp = get_token(1, 1)) == RET_EOL)
509 /* NOTHING */;
510 if (tmp == RET_EOF)
511 goto out;
512 if (!strcmp(token[0], "release")) {
513 if (get_token(1, 2) < 0)
514 goto err_out_parse_error;
515 tmp = atoi(token[0]);
516 if (tmp < codec_cfg_min)
517 goto err_out_release_num;
518 codecs_conf_release = tmp;
519 while ((tmp = get_token(1, 1)) == RET_EOL)
520 /* NOTHING */;
521 if (tmp == RET_EOF)
522 goto out;
523 } else
524 goto err_out_release_num;
527 * check if the next block starts with 'audiocodec' or
528 * with 'videocodec'
530 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
531 goto loop_enter;
532 goto err_out_parse_error;
534 while ((tmp = get_token(1, 1)) != RET_EOF) {
535 if (tmp == RET_EOL)
536 continue;
537 if (!strcmp(token[0], "audiocodec") ||
538 !strcmp(token[0], "videocodec")) {
539 if (!validate_codec(codec, codec_type))
540 goto err_out_not_valid;
541 loop_enter:
542 if (*token[0] == 'v') {
543 codec_type = TYPE_VIDEO;
544 nr_codecsp = &nr_vcodecs;
545 codecsp = &video_codecs;
546 } else if (*token[0] == 'a') {
547 codec_type = TYPE_AUDIO;
548 nr_codecsp = &nr_acodecs;
549 codecsp = &audio_codecs;
550 #ifdef DEBUG
551 } else {
552 mp_msg(MSGT_CODECCFG,MSGL_ERR,"picsba\n");
553 goto err_out;
554 #endif
556 if (!(*codecsp = realloc(*codecsp,
557 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
558 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
559 goto err_out;
561 codec=*codecsp + *nr_codecsp;
562 ++*nr_codecsp;
563 memset(codec,0,sizeof(codecs_t));
564 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
565 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
566 memset(codec->infmt, 0xff, sizeof(codec->infmt));
568 if (get_token(1, 1) < 0)
569 goto err_out_parse_error;
570 for (i = 0; i < *nr_codecsp - 1; i++) {
571 if(( (*codecsp)[i].name!=NULL) &&
572 (!strcmp(token[0], (*codecsp)[i].name)) ) {
573 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
574 goto err_out_print_linenum;
577 if (!(codec->name = strdup(token[0]))) {
578 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
579 goto err_out;
581 } else if (!strcmp(token[0], "info")) {
582 if (codec->info || get_token(1, 1) < 0)
583 goto err_out_parse_error;
584 if (!(codec->info = strdup(token[0]))) {
585 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
586 goto err_out;
588 } else if (!strcmp(token[0], "comment")) {
589 if (get_token(1, 1) < 0)
590 goto err_out_parse_error;
591 add_comment(token[0], &codec->comment);
592 } else if (!strcmp(token[0], "fourcc")) {
593 if (get_token(1, 2) < 0)
594 goto err_out_parse_error;
595 if (!add_to_fourcc(token[0], token[1],
596 codec->fourcc,
597 codec->fourccmap))
598 goto err_out_print_linenum;
599 } else if (!strcmp(token[0], "format")) {
600 if (get_token(1, 2) < 0)
601 goto err_out_parse_error;
602 if (!add_to_format(token[0], token[1],
603 codec->fourcc,codec->fourccmap))
604 goto err_out_print_linenum;
605 } else if (!strcmp(token[0], "driver")) {
606 if (get_token(1, 1) < 0)
607 goto err_out_parse_error;
608 if (!(codec->drv = strdup(token[0]))) {
609 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
610 goto err_out;
612 } else if (!strcmp(token[0], "dll")) {
613 if (get_token(1, 1) < 0)
614 goto err_out_parse_error;
615 if (!(codec->dll = strdup(token[0]))) {
616 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s", strerror(errno));
617 goto err_out;
619 } else if (!strcmp(token[0], "guid")) {
620 if (get_token(11, 11) < 0)
621 goto err_out_parse_error;
622 codec->guid.f1=strtoul(token[0],&endptr,0);
623 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
624 *endptr != '\0')
625 goto err_out_parse_error;
626 codec->guid.f2=strtoul(token[1],&endptr,0);
627 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
628 *endptr != '\0')
629 goto err_out_parse_error;
630 codec->guid.f3=strtoul(token[2],&endptr,0);
631 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
632 *endptr != '\0')
633 goto err_out_parse_error;
634 for (i = 0; i < 8; i++) {
635 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
636 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
637 *endptr != '\0')
638 goto err_out_parse_error;
640 } else if (!strcmp(token[0], "out")) {
641 if (get_token(1, 2) < 0)
642 goto err_out_parse_error;
643 if (!add_to_inout(token[0], token[1], codec->outfmt,
644 codec->outflags))
645 goto err_out_print_linenum;
646 } else if (!strcmp(token[0], "in")) {
647 if (get_token(1, 2) < 0)
648 goto err_out_parse_error;
649 if (!add_to_inout(token[0], token[1], codec->infmt,
650 codec->inflags))
651 goto err_out_print_linenum;
652 } else if (!strcmp(token[0], "flags")) {
653 if (get_token(1, 1) < 0)
654 goto err_out_parse_error;
655 if (!strcmp(token[0], "seekable"))
656 codec->flags |= CODECS_FLAG_SEEKABLE;
657 else if (!strcmp(token[0], "align16"))
658 codec->flags |= CODECS_FLAG_ALIGN16;
659 else
660 goto err_out_parse_error;
661 } else if (!strcmp(token[0], "status")) {
662 if (get_token(1, 1) < 0)
663 goto err_out_parse_error;
664 if (!strcasecmp(token[0], "working"))
665 codec->status = CODECS_STATUS_WORKING;
666 else if (!strcasecmp(token[0], "crashing"))
667 codec->status = CODECS_STATUS_NOT_WORKING;
668 else if (!strcasecmp(token[0], "untested"))
669 codec->status = CODECS_STATUS_UNTESTED;
670 else if (!strcasecmp(token[0], "buggy"))
671 codec->status = CODECS_STATUS_PROBLEMS;
672 else
673 goto err_out_parse_error;
674 } else if (!strcmp(token[0], "cpuflags")) {
675 if (get_token(1, 1) < 0)
676 goto err_out_parse_error;
677 if (!(codec->cpuflags = get_cpuflags(token[0])))
678 goto err_out_parse_error;
679 } else
680 goto err_out_parse_error;
682 if (!validate_codec(codec, codec_type))
683 goto err_out_not_valid;
684 mp_tmsg(MSGT_CODECCFG, MSGL_V, "%d audio & %d video codecs\n", nr_acodecs,
685 nr_vcodecs);
686 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
687 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
688 out:
689 talloc_free(tmpmem);
690 line=NULL;
691 return 1;
693 err_out_parse_error:
694 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
695 err_out_print_linenum:
696 PRINT_LINENUM;
697 err_out:
698 codecs_uninit_free();
700 talloc_free(tmpmem);
701 line=NULL;
702 line_num = 0;
703 return 0;
704 err_out_not_valid:
705 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
706 goto err_out_print_linenum;
707 err_out_release_num:
708 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
709 goto err_out_print_linenum;
712 static void codecs_free(codecs_t* codecs,int count) {
713 int i;
714 for ( i = 0; i < count; i++)
715 if ( codecs[i].name ) {
716 free(codecs[i].name);
717 free(codecs[i].info);
718 free(codecs[i].comment);
719 free(codecs[i].dll);
720 free(codecs[i].drv);
722 free(codecs);
725 void codecs_uninit_free(void) {
726 if (video_codecs)
727 codecs_free(video_codecs,nr_vcodecs);
728 video_codecs=NULL;
729 if (audio_codecs)
730 codecs_free(audio_codecs,nr_acodecs);
731 audio_codecs=NULL;
734 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
735 codecs_t *start, int force)
737 return find_codec(fourcc, fourccmap, start, 1, force);
740 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
741 codecs_t *start, int force)
743 return find_codec(fourcc, fourccmap, start, 0, force);
746 codecs_t* find_codec(unsigned int fourcc,unsigned int *fourccmap,
747 codecs_t *start, int audioflag, int force)
749 int i, j;
750 codecs_t *c;
752 #if 0
753 if (start) {
754 for (/* NOTHING */; start->name; start++) {
755 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
756 if (start->fourcc[j] == fourcc) {
757 if (fourccmap)
758 *fourccmap = start->fourccmap[j];
759 return start;
763 } else
764 #endif
766 if (audioflag) {
767 i = nr_acodecs;
768 c = audio_codecs;
769 } else {
770 i = nr_vcodecs;
771 c = video_codecs;
773 if(!i) return NULL;
774 for (/* NOTHING */; i--; c++) {
775 if(start && c<=start) continue;
776 for (j = 0; j < CODECS_MAX_FOURCC; j++) {
777 // FIXME: do NOT hardwire 'null' name here:
778 if (c->fourcc[j]==fourcc || !strcmp(c->drv,"null")) {
779 if (fourccmap)
780 *fourccmap = c->fourccmap[j];
781 return c;
784 if (force) return c;
787 return NULL;
790 void stringset_init(stringset_t *set) {
791 *set = calloc(1, sizeof(char *));
794 void stringset_free(stringset_t *set) {
795 int count = 0;
796 while ((*set)[count]) free((*set)[count++]);
797 free(*set);
798 *set = NULL;
801 void stringset_add(stringset_t *set, const char *str) {
802 int count = 0;
803 while ((*set)[count]) count++;
804 count++;
805 *set = realloc(*set, sizeof(char *) * (count + 1));
806 (*set)[count - 1] = strdup(str);
807 (*set)[count] = NULL;
810 int stringset_test(stringset_t *set, const char *str) {
811 stringset_t s;
812 for (s = *set; *s; s++)
813 if (strcmp(*s, str) == 0)
814 return 1;
815 return 0;
818 void list_codecs(int audioflag){
819 int i;
820 codecs_t *c;
822 if (audioflag) {
823 i = nr_acodecs;
824 c = audio_codecs;
825 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
826 } else {
827 i = nr_vcodecs;
828 c = video_codecs;
829 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
831 if(!i) return;
832 for (/* NOTHING */; i--; c++) {
833 char* s="unknown ";
834 switch(c->status){
835 case CODECS_STATUS_WORKING: s="working ";break;
836 case CODECS_STATUS_PROBLEMS: s="problems";break;
837 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
838 case CODECS_STATUS_UNTESTED: s="untested";break;
840 if(c->dll)
841 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
842 else
843 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);