cocoa_common.m: add missing config.h include
[mplayer.git] / codec-cfg.c
blob0c25e73901d0cc76a48b6d21b8f1fbea1f8a6f8f
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 #include <stdio.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <assert.h>
30 #include <string.h>
31 #include <stdint.h>
33 #include "config.h"
34 #include "mp_msg.h"
35 #include "libmpcodecs/img_format.h"
36 #include "codec-cfg.h"
37 #include "bstr.h"
38 #include "stream/stream.h"
39 #include "path.h"
41 static const char embedded_file[] =
42 #include "codecs.conf.h"
44 static const struct bstr builtin_codecs_conf = {
45 .start = (char *)embedded_file, .len = sizeof(embedded_file) - 1
48 #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
49 ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
50 ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
52 #define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
54 #define MAX_NR_TOKEN 16
56 #define RET_EOF -1
57 #define RET_EOL -2
59 #define TYPE_VIDEO 0
60 #define TYPE_AUDIO 1
62 static int codecs_conf_release;
63 char * codecs_file = NULL;
65 static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
66 unsigned int *map)
68 int i, j, freeslots;
69 unsigned int tmp;
71 /* find first unused slot */
72 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
73 /* NOTHING */;
74 freeslots = CODECS_MAX_FOURCC - i;
75 if (!freeslots)
76 goto err_out_too_many;
78 do {
79 if (strlen(s) < 4)
80 goto err_out_parse_error;
81 tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
82 for (j = 0; j < i; j++)
83 if (tmp == fourcc[j])
84 goto err_out_duplicated;
85 fourcc[i] = tmp;
86 map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
87 s += 4;
88 i++;
89 } while ((*(s++) == ',') && --freeslots);
91 if (!freeslots)
92 goto err_out_too_many;
93 if (*(--s) != '\0')
94 goto err_out_parse_error;
95 return 1;
96 err_out_duplicated:
97 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
98 return 0;
99 err_out_too_many:
100 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
101 return 0;
102 err_out_parse_error:
103 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
104 return 0;
107 static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
109 int i, j;
110 char *endptr;
112 /* find first unused slot */
113 for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
114 /* NOTHING */;
115 if (i == CODECS_MAX_FOURCC) {
116 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
117 return 0;
120 fourcc[i]=strtoul(s,&endptr,0);
121 if (*endptr != '\0') {
122 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
123 return 0;
126 if(alias){
127 fourccmap[i]=strtoul(alias,&endptr,0);
128 if (*endptr != '\0') {
129 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
130 return 0;
132 } else
133 fourccmap[i]=fourcc[i];
135 for (j = 0; j < i; j++)
136 if (fourcc[j] == fourcc[i]) {
137 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
138 return 0;
141 return 1;
144 static const struct {
145 const char *name;
146 const unsigned int num;
147 } fmt_table[] = {
148 // note: due to parser deficiencies/simplicity, if one format
149 // name matches the beginning of another, the longer one _must_
150 // come first in this list.
151 {"YV12", IMGFMT_YV12},
152 {"I420", IMGFMT_I420},
153 {"IYUV", IMGFMT_IYUV},
154 {"NV12", IMGFMT_NV12},
155 {"NV21", IMGFMT_NV21},
156 {"YVU9", IMGFMT_YVU9},
157 {"IF09", IMGFMT_IF09},
158 {"444P16LE", IMGFMT_444P16_LE},
159 {"444P16BE", IMGFMT_444P16_BE},
160 {"422P16LE", IMGFMT_422P16_LE},
161 {"422P16BE", IMGFMT_422P16_BE},
162 {"420P16LE", IMGFMT_420P16_LE},
163 {"420P16BE", IMGFMT_420P16_BE},
164 {"444P16", IMGFMT_444P16},
165 {"444P10", IMGFMT_444P10},
166 {"444P9", IMGFMT_444P9},
167 {"422P16", IMGFMT_422P16},
168 {"422P10", IMGFMT_422P10},
169 {"420P16", IMGFMT_420P16},
170 {"420P10", IMGFMT_420P10},
171 {"420P9", IMGFMT_420P9},
172 {"420A", IMGFMT_420A},
173 {"444P", IMGFMT_444P},
174 {"422P", IMGFMT_422P},
175 {"411P", IMGFMT_411P},
176 {"440P", IMGFMT_440P},
177 {"Y800", IMGFMT_Y800},
178 {"Y8", IMGFMT_Y8},
180 {"YUY2", IMGFMT_YUY2},
181 {"UYVY", IMGFMT_UYVY},
182 {"YVYU", IMGFMT_YVYU},
184 {"RGB48LE", IMGFMT_RGB48LE},
185 {"RGB48BE", IMGFMT_RGB48BE},
186 {"RGB4", IMGFMT_RGB4},
187 {"RGB8", IMGFMT_RGB8},
188 {"RGB15", IMGFMT_RGB15},
189 {"RGB16", IMGFMT_RGB16},
190 {"RGB24", IMGFMT_RGB24},
191 {"RGB32", IMGFMT_RGB32},
192 {"BGR4", IMGFMT_BGR4},
193 {"BGR8", IMGFMT_BGR8},
194 {"BGR15", IMGFMT_BGR15},
195 {"BGR16", IMGFMT_BGR16},
196 {"BGR24", IMGFMT_BGR24},
197 {"BGR32", IMGFMT_BGR32},
198 {"RGB1", IMGFMT_RGB1},
199 {"BGR1", IMGFMT_BGR1},
201 {"MPES", IMGFMT_MPEGPES},
203 {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2},
204 {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2},
206 {"VDPAU_MPEG1",IMGFMT_VDPAU_MPEG1},
207 {"VDPAU_MPEG2",IMGFMT_VDPAU_MPEG2},
208 {"VDPAU_H264",IMGFMT_VDPAU_H264},
209 {"VDPAU_WMV3",IMGFMT_VDPAU_WMV3},
210 {"VDPAU_VC1",IMGFMT_VDPAU_VC1},
211 {"VDPAU_MPEG4",IMGFMT_VDPAU_MPEG4},
213 {NULL, 0}
217 static int add_to_inout(char *sfmt, char *sflags, unsigned int *outfmt,
218 unsigned char *outflags)
221 static char *flagstr[] = {
222 "flip",
223 "noflip",
224 "yuvhack",
225 "query",
226 "static",
227 NULL
230 int i, j, freeslots;
231 unsigned char flags;
233 for (i = 0; i < CODECS_MAX_OUTFMT && outfmt[i] != 0xffffffff; i++)
234 /* NOTHING */;
235 freeslots = CODECS_MAX_OUTFMT - i;
236 if (!freeslots)
237 goto err_out_too_many;
239 flags = 0;
240 if(sflags) {
241 do {
242 for (j = 0; flagstr[j] != NULL; j++)
243 if (!strncmp(sflags, flagstr[j],
244 strlen(flagstr[j])))
245 break;
246 if (flagstr[j] == NULL)
247 goto err_out_parse_error;
248 flags|=(1<<j);
249 sflags+=strlen(flagstr[j]);
250 } while (*(sflags++) == ',');
252 if (*(--sflags) != '\0')
253 goto err_out_parse_error;
256 do {
257 for (j = 0; fmt_table[j].name != NULL; j++)
258 if (!strncmp(sfmt, fmt_table[j].name, strlen(fmt_table[j].name)))
259 break;
260 if (fmt_table[j].name == NULL)
261 goto err_out_parse_error;
262 outfmt[i] = fmt_table[j].num;
263 outflags[i] = flags;
264 ++i;
265 sfmt+=strlen(fmt_table[j].name);
266 } while ((*(sfmt++) == ',') && --freeslots);
268 if (!freeslots)
269 goto err_out_too_many;
271 if (*(--sfmt) != '\0')
272 goto err_out_parse_error;
274 return 1;
275 err_out_too_many:
276 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many out...");
277 return 0;
278 err_out_parse_error:
279 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
280 return 0;
283 static int validate_codec(codecs_t *c, int type)
285 unsigned int i;
286 char *tmp_name = c->name;
288 for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
289 /* NOTHING */;
291 if (i < strlen(tmp_name)) {
292 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
293 return 0;
296 if (!c->info)
297 c->info = strdup(c->name);
299 if (!c->drv) {
300 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
301 return 0;
304 return 1;
307 static int add_comment(char *s, char **d)
309 int pos;
311 if (!*d)
312 pos = 0;
313 else {
314 pos = strlen(*d);
315 (*d)[pos++] = '\n';
317 if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
318 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
319 return 0;
321 strcpy(*d + pos, s);
322 return 1;
325 static struct bstr filetext;
326 static int line_num = 0;
327 static char *line;
328 static char *token[MAX_NR_TOKEN];
329 static int read_nextline = 1;
331 static int get_token(int min, int max)
333 static int line_pos;
334 int i;
335 char c;
337 if (max >= MAX_NR_TOKEN) {
338 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_MR_TOKEN!");
339 goto out_eof;
342 memset(token, 0x00, sizeof(*token) * max);
344 if (read_nextline) {
345 if (!filetext.len)
346 goto out_eof;
347 struct bstr nextline = bstr_getline(filetext, &filetext);
348 line = nextline.start;
349 line[nextline.len - 1] = 0;
350 line_pos = 0;
351 ++line_num;
352 read_nextline = 0;
354 for (i = 0; i < max; i++) {
355 while (isspace(line[line_pos]))
356 ++line_pos;
357 if (line[line_pos] == '\0' || line[line_pos] == '#' ||
358 line[line_pos] == ';') {
359 read_nextline = 1;
360 if (i >= min)
361 goto out_ok;
362 goto out_eol;
364 token[i] = line + line_pos;
365 c = line[line_pos];
366 if (c == '"' || c == '\'') {
367 token[i]++;
368 while (line[++line_pos] != c && line[line_pos])
369 /* NOTHING */;
370 } else {
371 for (/* NOTHING */; !isspace(line[line_pos]) &&
372 line[line_pos]; line_pos++)
373 /* NOTHING */;
375 if (!line[line_pos]) {
376 read_nextline = 1;
377 if (i >= min - 1)
378 goto out_ok;
379 goto out_eol;
381 line[line_pos] = '\0';
382 line_pos++;
384 out_ok:
385 return i;
386 out_eof:
387 read_nextline = 1;
388 return RET_EOF;
389 out_eol:
390 return RET_EOL;
393 static codecs_t *video_codecs=NULL;
394 static codecs_t *audio_codecs=NULL;
395 static int nr_vcodecs = 0;
396 static int nr_acodecs = 0;
398 int parse_codec_cfg(const char *cfgfile)
400 codecs_t *codec = NULL; // current codec
401 codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
402 char *endptr; // strtoul()...
403 int *nr_codecsp;
404 int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
405 int tmp, i;
406 int codec_cfg_min;
408 for (struct bstr s = builtin_codecs_conf; ; bstr_getline(s, &s)) {
409 if (!s.len)
410 abort();
411 if (bstr_eatstart0(&s, "release ")) {
412 codec_cfg_min = atoi(s.start);
413 break;
417 // in case we call it a second time
418 codecs_uninit_free();
420 nr_vcodecs = 0;
421 nr_acodecs = 0;
423 if (cfgfile) {
424 // Avoid printing errors from open_stream when trying optional files
425 if (!mp_path_exists(cfgfile)) {
426 mp_tmsg(MSGT_CODECCFG, MSGL_V,
427 "No optional codecs config file: %s\n", cfgfile);
428 return 0;
430 mp_msg(MSGT_CODECCFG, MSGL_V, "Reading codec config file: %s\n",
431 cfgfile);
432 struct stream *s = open_stream(cfgfile, NULL, NULL);
433 if (!s)
434 return 0;
435 filetext = stream_read_complete(s, NULL, 10000000, 1);
436 free_stream(s);
437 if (!filetext.start)
438 return 0;
439 } else
440 // Parsing modifies the data
441 filetext = bstrdup(NULL, builtin_codecs_conf);
442 void *tmpmem = filetext.start;
444 read_nextline = 1;
447 * this only catches release lines at the start of
448 * codecs.conf, before audiocodecs and videocodecs.
450 while ((tmp = get_token(1, 1)) == RET_EOL)
451 /* NOTHING */;
452 if (tmp == RET_EOF)
453 goto out;
454 if (!strcmp(token[0], "release")) {
455 if (get_token(1, 2) < 0)
456 goto err_out_parse_error;
457 tmp = atoi(token[0]);
458 if (tmp < codec_cfg_min)
459 goto err_out_release_num;
460 codecs_conf_release = tmp;
461 while ((tmp = get_token(1, 1)) == RET_EOL)
462 /* NOTHING */;
463 if (tmp == RET_EOF)
464 goto out;
465 } else
466 goto err_out_release_num;
469 * check if the next block starts with 'audiocodec' or
470 * with 'videocodec'
472 if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
473 goto loop_enter;
474 goto err_out_parse_error;
476 while ((tmp = get_token(1, 1)) != RET_EOF) {
477 if (tmp == RET_EOL)
478 continue;
479 if (!strcmp(token[0], "audiocodec") ||
480 !strcmp(token[0], "videocodec")) {
481 if (!validate_codec(codec, codec_type))
482 goto err_out_not_valid;
483 loop_enter:
484 if (*token[0] == 'v') {
485 codec_type = TYPE_VIDEO;
486 nr_codecsp = &nr_vcodecs;
487 codecsp = &video_codecs;
488 } else {
489 assert(*token[0] == 'a');
490 codec_type = TYPE_AUDIO;
491 nr_codecsp = &nr_acodecs;
492 codecsp = &audio_codecs;
494 if (!(*codecsp = realloc(*codecsp,
495 sizeof(codecs_t) * (*nr_codecsp + 2)))) {
496 mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
497 goto err_out;
499 codec=*codecsp + *nr_codecsp;
500 ++*nr_codecsp;
501 memset(codec,0,sizeof(codecs_t));
502 memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
503 memset(codec->outfmt, 0xff, sizeof(codec->outfmt));
504 memset(codec->infmt, 0xff, sizeof(codec->infmt));
506 if (get_token(1, 1) < 0)
507 goto err_out_parse_error;
508 for (i = 0; i < *nr_codecsp - 1; i++) {
509 if(( (*codecsp)[i].name!=NULL) &&
510 (!strcmp(token[0], (*codecsp)[i].name)) ) {
511 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
512 goto err_out_print_linenum;
515 if (!(codec->name = strdup(token[0]))) {
516 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
517 goto err_out;
519 } else if (!strcmp(token[0], "info")) {
520 if (codec->info || get_token(1, 1) < 0)
521 goto err_out_parse_error;
522 if (!(codec->info = strdup(token[0]))) {
523 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
524 goto err_out;
526 } else if (!strcmp(token[0], "comment")) {
527 if (get_token(1, 1) < 0)
528 goto err_out_parse_error;
529 add_comment(token[0], &codec->comment);
530 } else if (!strcmp(token[0], "fourcc")) {
531 if (get_token(1, 2) < 0)
532 goto err_out_parse_error;
533 if (!add_to_fourcc(token[0], token[1],
534 codec->fourcc,
535 codec->fourccmap))
536 goto err_out_print_linenum;
537 } else if (!strcmp(token[0], "format")) {
538 if (get_token(1, 2) < 0)
539 goto err_out_parse_error;
540 if (!add_to_format(token[0], token[1],
541 codec->fourcc,codec->fourccmap))
542 goto err_out_print_linenum;
543 } else if (!strcmp(token[0], "driver")) {
544 if (get_token(1, 1) < 0)
545 goto err_out_parse_error;
546 if (!(codec->drv = strdup(token[0]))) {
547 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
548 goto err_out;
550 } else if (!strcmp(token[0], "dll")) {
551 if (get_token(1, 1) < 0)
552 goto err_out_parse_error;
553 if (!(codec->dll = strdup(token[0]))) {
554 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s", strerror(errno));
555 goto err_out;
557 } else if (!strcmp(token[0], "guid")) {
558 if (get_token(11, 11) < 0)
559 goto err_out_parse_error;
560 codec->guid.f1=strtoul(token[0],&endptr,0);
561 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
562 *endptr != '\0')
563 goto err_out_parse_error;
564 codec->guid.f2=strtoul(token[1],&endptr,0);
565 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
566 *endptr != '\0')
567 goto err_out_parse_error;
568 codec->guid.f3=strtoul(token[2],&endptr,0);
569 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
570 *endptr != '\0')
571 goto err_out_parse_error;
572 for (i = 0; i < 8; i++) {
573 codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
574 if ((*endptr != ',' || *(endptr + 1) != '\0') &&
575 *endptr != '\0')
576 goto err_out_parse_error;
578 } else if (!strcmp(token[0], "out")) {
579 if (get_token(1, 2) < 0)
580 goto err_out_parse_error;
581 if (!add_to_inout(token[0], token[1], codec->outfmt,
582 codec->outflags))
583 goto err_out_print_linenum;
584 } else if (!strcmp(token[0], "in")) {
585 if (get_token(1, 2) < 0)
586 goto err_out_parse_error;
587 if (!add_to_inout(token[0], token[1], codec->infmt,
588 codec->inflags))
589 goto err_out_print_linenum;
590 } else if (!strcmp(token[0], "flags")) {
591 if (get_token(1, 1) < 0)
592 goto err_out_parse_error;
593 if (!strcmp(token[0], "seekable"))
594 codec->flags |= CODECS_FLAG_SEEKABLE;
595 else if (!strcmp(token[0], "align16"))
596 codec->flags |= CODECS_FLAG_ALIGN16;
597 else
598 goto err_out_parse_error;
599 } else if (!strcmp(token[0], "status")) {
600 if (get_token(1, 1) < 0)
601 goto err_out_parse_error;
602 if (!strcasecmp(token[0], "working"))
603 codec->status = CODECS_STATUS_WORKING;
604 else if (!strcasecmp(token[0], "crashing"))
605 codec->status = CODECS_STATUS_NOT_WORKING;
606 else if (!strcasecmp(token[0], "untested"))
607 codec->status = CODECS_STATUS_UNTESTED;
608 else if (!strcasecmp(token[0], "buggy"))
609 codec->status = CODECS_STATUS_PROBLEMS;
610 else
611 goto err_out_parse_error;
612 } else if (!strcmp(token[0], "anyinput")) {
613 codec->anyinput = true;
614 } else
615 goto err_out_parse_error;
617 if (!validate_codec(codec, codec_type))
618 goto err_out_not_valid;
619 mp_tmsg(MSGT_CODECCFG, MSGL_V, "%d audio & %d video codecs\n", nr_acodecs,
620 nr_vcodecs);
621 if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
622 if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
623 out:
624 talloc_free(tmpmem);
625 line=NULL;
626 return 1;
628 err_out_parse_error:
629 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
630 err_out_print_linenum:
631 PRINT_LINENUM;
632 err_out:
633 codecs_uninit_free();
635 talloc_free(tmpmem);
636 line=NULL;
637 line_num = 0;
638 return 0;
639 err_out_not_valid:
640 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
641 goto err_out_print_linenum;
642 err_out_release_num:
643 mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
644 goto err_out_print_linenum;
647 static void codecs_free(codecs_t* codecs,int count) {
648 int i;
649 for ( i = 0; i < count; i++)
650 if ( codecs[i].name ) {
651 free(codecs[i].name);
652 free(codecs[i].info);
653 free(codecs[i].comment);
654 free(codecs[i].dll);
655 free(codecs[i].drv);
657 free(codecs);
660 void codecs_uninit_free(void) {
661 if (video_codecs)
662 codecs_free(video_codecs,nr_vcodecs);
663 video_codecs=NULL;
664 if (audio_codecs)
665 codecs_free(audio_codecs,nr_acodecs);
666 audio_codecs=NULL;
669 codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
670 codecs_t *start, int force)
672 return find_codec(fourcc, fourccmap, start, 1, force);
675 codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
676 codecs_t *start, int force)
678 return find_codec(fourcc, fourccmap, start, 0, force);
681 struct codecs *find_codec(unsigned int fourcc, unsigned int *fourccmap,
682 codecs_t *start, int audioflag, int force)
684 struct codecs *c, *end;
686 if (audioflag) {
687 c = audio_codecs;
688 end = c + nr_acodecs;
689 } else {
690 c = video_codecs;
691 end = c + nr_vcodecs;
693 if (start)
694 c = start + 1; // actually starts from the next one after the given one
695 for (; c < end; c++) {
696 for (int j = 0; j < CODECS_MAX_FOURCC; j++) {
697 if (c->fourcc[j] == -1)
698 break;
699 if (c->fourcc[j] == fourcc) {
700 if (fourccmap)
701 *fourccmap = c->fourccmap[j];
702 return c;
705 if (c->anyinput || force)
706 return c;
708 return NULL;
711 void stringset_init(stringset_t *set) {
712 *set = calloc(1, sizeof(char *));
715 void stringset_free(stringset_t *set) {
716 int count = 0;
717 while ((*set)[count]) free((*set)[count++]);
718 free(*set);
719 *set = NULL;
722 void stringset_add(stringset_t *set, const char *str) {
723 int count = 0;
724 while ((*set)[count]) count++;
725 count++;
726 *set = realloc(*set, sizeof(char *) * (count + 1));
727 (*set)[count - 1] = strdup(str);
728 (*set)[count] = NULL;
731 int stringset_test(stringset_t *set, const char *str) {
732 stringset_t s;
733 for (s = *set; *s; s++)
734 if (strcmp(*s, str) == 0)
735 return 1;
736 return 0;
739 void list_codecs(int audioflag){
740 int i;
741 codecs_t *c;
743 if (audioflag) {
744 i = nr_acodecs;
745 c = audio_codecs;
746 mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
747 } else {
748 i = nr_vcodecs;
749 c = video_codecs;
750 mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
752 if(!i) return;
753 for (/* NOTHING */; i--; c++) {
754 char* s="unknown ";
755 switch(c->status){
756 case CODECS_STATUS_WORKING: s="working ";break;
757 case CODECS_STATUS_PROBLEMS: s="problems";break;
758 case CODECS_STATUS_NOT_WORKING: s="crashing";break;
759 case CODECS_STATUS_UNTESTED: s="untested";break;
761 if(c->dll)
762 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
763 else
764 mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);