summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/av_common.c130
-rw-r--r--core/av_common.h30
-rw-r--r--core/cfg-mplayer.h9
-rw-r--r--core/codec-cfg.c607
-rw-r--r--core/codec-cfg.h79
-rw-r--r--core/codecs.c147
-rw-r--r--core/codecs.h43
-rw-r--r--core/command.c62
-rw-r--r--core/defaultopts.c2
-rw-r--r--core/m_property.c2
-rw-r--r--core/mp_common.h7
-rw-r--r--core/mpc_info.h44
-rw-r--r--core/mplayer.c95
-rw-r--r--core/options.h4
14 files changed, 395 insertions, 866 deletions
diff --git a/core/av_common.c b/core/av_common.c
new file mode 100644
index 0000000000..55fa5e086b
--- /dev/null
+++ b/core/av_common.c
@@ -0,0 +1,130 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+
+#include "config.h"
+#include "core/mp_talloc.h"
+#include "av_common.h"
+#include "codecs.h"
+
+
+#if !HAVE_AVCODEC_IS_DECODER_API
+static int av_codec_is_decoder(AVCodec *codec)
+{
+ return !!codec->decode;
+}
+#endif
+
+void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type)
+{
+ AVCodec *cur = NULL;
+ for (;;) {
+ cur = av_codec_next(cur);
+ if (!cur)
+ break;
+ if (av_codec_is_decoder(cur) && cur->type == type) {
+ struct mp_decoder_entry entry = {
+ .family = "lavc",
+ .codec = mp_codec_from_av_codec_id(cur->id),
+ .decoder = cur->name,
+ .desc = cur->long_name,
+ };
+ assert(entry.family);
+ MP_TARRAY_APPEND(list, list->entries, list->num_entries, entry);
+ }
+ }
+}
+
+#if HAVE_AVCODEC_CODEC_DESC_API
+
+int mp_codec_to_av_codec_id(const char *codec)
+{
+
+ const AVCodecDescriptor *desc = avcodec_descriptor_get_by_name(codec);
+ return desc ? desc->id : CODEC_ID_NONE;
+}
+
+const char *mp_codec_from_av_codec_id(int codec_id)
+{
+ const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
+ return desc ? desc->name : NULL;
+}
+
+#else
+
+struct mp_av_codec {
+ const char *name;
+ int codec_id;
+};
+
+// Some decoders have a different name from the canonical codec name, for
+// example the codec "dts" CODEC_ID_DTS has the decoder named "dca", and
+// avcodec_find_decoder_by_name("dts") would return 0. We always want the
+// canonical name.
+// On newer lavc versions, avcodec_descriptor_get_by_name("dts") will return
+// CODEC_ID_DTS, which is what we want, but for older versions we need this
+// lookup table.
+struct mp_av_codec mp_av_codec_id_list[] = {
+ {"ra_144", CODEC_ID_RA_144},
+ {"ra_288", CODEC_ID_RA_288},
+ {"smackaudio", CODEC_ID_SMACKAUDIO},
+ {"dts", CODEC_ID_DTS},
+ {"musepack7", CODEC_ID_MUSEPACK7},
+ {"musepack8", CODEC_ID_MUSEPACK8},
+ {"amr_nb", CODEC_ID_AMR_NB},
+ {"amr_wb", CODEC_ID_AMR_WB},
+ {"adpcm_g722", CODEC_ID_ADPCM_G722},
+ {"adpcm_g726", CODEC_ID_ADPCM_G726},
+ {"westwood_snd1", CODEC_ID_WESTWOOD_SND1},
+ {"mp4als", CODEC_ID_MP4ALS},
+ {"vixl", CODEC_ID_VIXL},
+ {"flv1", CODEC_ID_FLV1},
+ {"msmpeg4v3", CODEC_ID_MSMPEG4V3},
+ {"jpeg2000", CODEC_ID_JPEG2000},
+ {"ulti", CODEC_ID_ULTI},
+ {"smackvideo", CODEC_ID_SMACKVIDEO},
+ {"tscc", CODEC_ID_TSCC},
+ {"cscd", CODEC_ID_CSCD},
+ {"tgv", CODEC_ID_TGV},
+ {"roq", CODEC_ID_ROQ},
+ {"idcin", CODEC_ID_IDCIN},
+ {"ws_vqa", CODEC_ID_WS_VQA},
+ {0},
+};
+
+int mp_codec_to_av_codec_id(const char *codec)
+{
+ for (int n = 0; mp_av_codec_id_list[n].name; n++) {
+ if (strcmp(mp_av_codec_id_list[n].name, codec) == 0)
+ return mp_av_codec_id_list[n].codec_id;
+ }
+ AVCodec *avcodec = avcodec_find_decoder_by_name(codec);
+ return avcodec ? avcodec->id : CODEC_ID_NONE;
+}
+
+const char *mp_codec_from_av_codec_id(int codec_id)
+{
+ for (int n = 0; mp_av_codec_id_list[n].name; n++) {
+ if (mp_av_codec_id_list[n].codec_id == codec_id)
+ return mp_av_codec_id_list[n].name;
+ }
+ AVCodec *avcodec = avcodec_find_decoder(codec_id);
+ return avcodec ? avcodec->name : NULL;
+}
+
+#endif
diff --git a/core/av_common.h b/core/av_common.h
new file mode 100644
index 0000000000..4fbe592f11
--- /dev/null
+++ b/core/av_common.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MP_AVCOMMON_H
+#define MP_AVCOMMON_H
+
+#include <libavutil/avutil.h>
+#include <libavcodec/avcodec.h>
+
+struct mp_decoder_list;
+
+void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type);
+int mp_codec_to_av_codec_id(const char *codec);
+const char *mp_codec_from_av_codec_id(int codec_id);
+
+#endif
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index 78d85aa9ed..1c0f269e90 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -439,11 +439,9 @@ const m_option_t common_opts[] = {
{"af-adv", (void *) audio_filter_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
OPT_SETTINGSLIST("vf*", vf_settings, 0, &vf_obj_list),
- // select audio/video codec (by name) or codec family (by number):
- {"afm", &audio_fm_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
- {"vfm", &video_fm_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
- {"ac", &audio_codec_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
- {"vc", &video_codec_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
+
+ OPT_STRING("ad", audio_decoders, 0),
+ OPT_STRING("vd", video_decoders, 0),
OPT_CHOICE("hwdec", hwdec_api, 0,
({"no", 0},
@@ -473,7 +471,6 @@ const m_option_t common_opts[] = {
{"lavdopts", (void *) lavc_decode_opts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
{"lavfdopts", (void *) lavfdopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
- OPT_STRING("codecs-file", codecs_file, 0),
// ------------------------- subtitles options --------------------
OPT_STRINGLIST("sub", sub_name, 0),
diff --git a/core/codec-cfg.c b/core/codec-cfg.c
deleted file mode 100644
index ac875a8a82..0000000000
--- a/core/codec-cfg.c
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * codecs.conf parser
- *
- * Copyright (C) 2001 Szabolcs Berecz <szabi@inf.elte.hu>
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
-#include <stdint.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-#include "video/img_format.h"
-#include "codec-cfg.h"
-#include "core/bstr.h"
-#include "stream/stream.h"
-#include "core/path.h"
-
-static const char embedded_file[] =
-#include "codecs.conf.h"
- ;
-static const struct bstr builtin_codecs_conf = {
- .start = (char *)embedded_file, .len = sizeof(embedded_file) - 1
-};
-
-#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
- ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
- ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
-
-#define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
-
-#define MAX_NR_TOKEN 16
-
-#define RET_EOF -1
-#define RET_EOL -2
-
-#define TYPE_VIDEO 0
-#define TYPE_AUDIO 1
-
-static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
- unsigned int *map)
-{
- int i, j, freeslots;
- unsigned int tmp;
-
- /* find first unused slot */
- for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
- /* NOTHING */;
- freeslots = CODECS_MAX_FOURCC - i;
- if (!freeslots)
- goto err_out_too_many;
-
- do {
- if (strlen(s) < 4)
- goto err_out_parse_error;
- tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
- for (j = 0; j < i; j++)
- if (tmp == fourcc[j])
- goto err_out_duplicated;
- fourcc[i] = tmp;
- map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
- s += 4;
- i++;
- } while ((*(s++) == ',') && --freeslots);
-
- if (!freeslots)
- goto err_out_too_many;
- if (*(--s) != '\0')
- goto err_out_parse_error;
- return 1;
-err_out_duplicated:
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
- return 0;
-err_out_too_many:
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
- return 0;
-err_out_parse_error:
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
- return 0;
-}
-
-static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
-{
- int i, j;
- char *endptr;
-
- /* find first unused slot */
- for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
- /* NOTHING */;
- if (i == CODECS_MAX_FOURCC) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
- return 0;
- }
-
- fourcc[i]=strtoul(s,&endptr,0);
- if (*endptr != '\0') {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
- return 0;
- }
-
- if(alias){
- fourccmap[i]=strtoul(alias,&endptr,0);
- if (*endptr != '\0') {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
- return 0;
- }
- } else
- fourccmap[i]=fourcc[i];
-
- for (j = 0; j < i; j++)
- if (fourcc[j] == fourcc[i]) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
- return 0;
- }
-
- return 1;
-}
-
-static int validate_codec(codecs_t *c, int type)
-{
- unsigned int i;
- char *tmp_name = c->name;
-
- for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
- /* NOTHING */;
-
- if (i < strlen(tmp_name)) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
- return 0;
- }
-
- if (!c->info)
- c->info = strdup(c->name);
-
- if (!c->drv) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
- return 0;
- }
-
- return 1;
-}
-
-static int add_comment(char *s, char **d)
-{
- int pos;
-
- if (!*d)
- pos = 0;
- else {
- pos = strlen(*d);
- (*d)[pos++] = '\n';
- }
- if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
- mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
- return 0;
- }
- strcpy(*d + pos, s);
- return 1;
-}
-
-static struct bstr filetext;
-static int line_num = 0;
-static char *line;
-static char *token[MAX_NR_TOKEN];
-static int read_nextline = 1;
-
-static int get_token(int min, int max)
-{
- static int line_pos;
- int i;
- char c;
-
- if (max >= MAX_NR_TOKEN) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_MR_TOKEN!");
- goto out_eof;
- }
-
- memset(token, 0x00, sizeof(*token) * max);
-
- if (read_nextline) {
- if (!filetext.len)
- goto out_eof;
- struct bstr nextline = bstr_getline(filetext, &filetext);
- line = nextline.start;
- line[nextline.len - 1] = 0;
- line_pos = 0;
- ++line_num;
- read_nextline = 0;
- }
- for (i = 0; i < max; i++) {
- while (isspace(line[line_pos]))
- ++line_pos;
- if (line[line_pos] == '\0' || line[line_pos] == '#' ||
- line[line_pos] == ';') {
- read_nextline = 1;
- if (i >= min)
- goto out_ok;
- goto out_eol;
- }
- token[i] = line + line_pos;
- c = line[line_pos];
- if (c == '"' || c == '\'') {
- token[i]++;
- while (line[++line_pos] != c && line[line_pos])
- /* NOTHING */;
- } else {
- for (/* NOTHING */; !isspace(line[line_pos]) &&
- line[line_pos]; line_pos++)
- /* NOTHING */;
- }
- if (!line[line_pos]) {
- read_nextline = 1;
- if (i >= min - 1)
- goto out_ok;
- goto out_eol;
- }
- line[line_pos] = '\0';
- line_pos++;
- }
-out_ok:
- return i;
-out_eof:
- read_nextline = 1;
- return RET_EOF;
-out_eol:
- return RET_EOL;
-}
-
-static codecs_t *video_codecs=NULL;
-static codecs_t *audio_codecs=NULL;
-static int nr_vcodecs = 0;
-static int nr_acodecs = 0;
-
-int parse_codec_cfg(const char *cfgfile)
-{
- codecs_t *codec = NULL; // current codec
- codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
- char *endptr; // strtoul()...
- int *nr_codecsp;
- int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
- int tmp, i;
- int codec_cfg_min;
-
- for (struct bstr s = builtin_codecs_conf; ; bstr_getline(s, &s)) {
- if (!s.len)
- abort();
- if (bstr_eatstart0(&s, "release ")) {
- codec_cfg_min = atoi(s.start);
- break;
- }
- }
-
- // in case we call it a second time
- codecs_uninit_free();
-
- nr_vcodecs = 0;
- nr_acodecs = 0;
-
- if (cfgfile) {
- // Avoid printing errors from open_stream when trying optional files
- if (!mp_path_exists(cfgfile)) {
- mp_tmsg(MSGT_CODECCFG, MSGL_V,
- "No optional codecs config file: %s\n", cfgfile);
- return 0;
- }
- mp_msg(MSGT_CODECCFG, MSGL_V, "Reading codec config file: %s\n",
- cfgfile);
- struct stream *s = open_stream(cfgfile, NULL, NULL);
- if (!s)
- return 0;
- filetext = stream_read_complete(s, NULL, 10000000, 1);
- free_stream(s);
- if (!filetext.start)
- return 0;
- } else
- // Parsing modifies the data
- filetext = bstrdup(NULL, builtin_codecs_conf);
- void *tmpmem = filetext.start;
-
- read_nextline = 1;
-
- /*
- * this only catches release lines at the start of
- * codecs.conf, before audiocodecs and videocodecs.
- */
- while ((tmp = get_token(1, 1)) == RET_EOL)
- /* NOTHING */;
- if (tmp == RET_EOF)
- goto out;
- if (!strcmp(token[0], "release")) {
- if (get_token(1, 2) < 0)
- goto err_out_parse_error;
- tmp = atoi(token[0]);
- if (tmp < codec_cfg_min)
- goto err_out_release_num;
- while ((tmp = get_token(1, 1)) == RET_EOL)
- /* NOTHING */;
- if (tmp == RET_EOF)
- goto out;
- } else
- goto err_out_release_num;
-
- /*
- * check if the next block starts with 'audiocodec' or
- * with 'videocodec'
- */
- if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
- goto loop_enter;
- goto err_out_parse_error;
-
- while ((tmp = get_token(1, 1)) != RET_EOF) {
- if (tmp == RET_EOL)
- continue;
- if (!strcmp(token[0], "audiocodec") ||
- !strcmp(token[0], "videocodec")) {
- if (!validate_codec(codec, codec_type))
- goto err_out_not_valid;
- loop_enter:
- if (*token[0] == 'v') {
- codec_type = TYPE_VIDEO;
- nr_codecsp = &nr_vcodecs;
- codecsp = &video_codecs;
- } else {
- assert(*token[0] == 'a');
- codec_type = TYPE_AUDIO;
- nr_codecsp = &nr_acodecs;
- codecsp = &audio_codecs;
- }
- if (!(*codecsp = realloc(*codecsp,
- sizeof(codecs_t) * (*nr_codecsp + 2)))) {
- mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
- goto err_out;
- }
- codec=*codecsp + *nr_codecsp;
- ++*nr_codecsp;
- memset(codec,0,sizeof(codecs_t));
- memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
-
- if (get_token(1, 1) < 0)
- goto err_out_parse_error;
- for (i = 0; i < *nr_codecsp - 1; i++) {
- if(( (*codecsp)[i].name!=NULL) &&
- (!strcmp(token[0], (*codecsp)[i].name)) ) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
- goto err_out_print_linenum;
- }
- }
- if (!(codec->name = strdup(token[0]))) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
- goto err_out;
- }
- } else if (!strcmp(token[0], "info")) {
- if (codec->info || get_token(1, 1) < 0)
- goto err_out_parse_error;
- if (!(codec->info = strdup(token[0]))) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
- goto err_out;
- }
- } else if (!strcmp(token[0], "comment")) {
- if (get_token(1, 1) < 0)
- goto err_out_parse_error;
- add_comment(token[0], &codec->comment);
- } else if (!strcmp(token[0], "fourcc")) {
- if (get_token(1, 2) < 0)
- goto err_out_parse_error;
- if (!add_to_fourcc(token[0], token[1],
- codec->fourcc,
- codec->fourccmap))
- goto err_out_print_linenum;
- } else if (!strcmp(token[0], "format")) {
- if (get_token(1, 2) < 0)
- goto err_out_parse_error;
- if (!add_to_format(token[0], token[1],
- codec->fourcc,codec->fourccmap))
- goto err_out_print_linenum;
- } else if (!strcmp(token[0], "driver")) {
- if (get_token(1, 1) < 0)
- goto err_out_parse_error;
- if (!(codec->drv = strdup(token[0]))) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
- goto err_out;
- }
- } else if (!strcmp(token[0], "dll")) {
- if (get_token(1, 1) < 0)
- goto err_out_parse_error;
- if (!(codec->dll = strdup(token[0]))) {
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s", strerror(errno));
- goto err_out;
- }
- } else if (!strcmp(token[0], "guid")) {
- if (get_token(11, 11) < 0)
- goto err_out_parse_error;
- codec->guid.f1=strtoul(token[0],&endptr,0);
- if ((*endptr != ',' || *(endptr + 1) != '\0') &&
- *endptr != '\0')
- goto err_out_parse_error;
- codec->guid.f2=strtoul(token[1],&endptr,0);
- if ((*endptr != ',' || *(endptr + 1) != '\0') &&
- *endptr != '\0')
- goto err_out_parse_error;
- codec->guid.f3=strtoul(token[2],&endptr,0);
- if ((*endptr != ',' || *(endptr + 1) != '\0') &&
- *endptr != '\0')
- goto err_out_parse_error;
- for (i = 0; i < 8; i++) {
- codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
- if ((*endptr != ',' || *(endptr + 1) != '\0') &&
- *endptr != '\0')
- goto err_out_parse_error;
- }
- } else if (!strcmp(token[0], "flags")) {
- if (get_token(1, 1) < 0)
- goto err_out_parse_error;
- if (!strcmp(token[0], "flip"))
- codec->flags |= CODECS_FLAG_FLIP;
- else
- goto err_out_parse_error;
- } else if (!strcmp(token[0], "status")) {
- if (get_token(1, 1) < 0)
- goto err_out_parse_error;
- if (!strcasecmp(token[0], "working"))
- codec->status = CODECS_STATUS_WORKING;
- else if (!strcasecmp(token[0], "crashing"))
- codec->status = CODECS_STATUS_NOT_WORKING;
- else if (!strcasecmp(token[0], "untested"))
- codec->status = CODECS_STATUS_UNTESTED;
- else if (!strcasecmp(token[0], "buggy"))
- codec->status = CODECS_STATUS_PROBLEMS;
- else
- goto err_out_parse_error;
- } else if (!strcmp(token[0], "anyinput")) {
- codec->anyinput = true;
- } else
- goto err_out_parse_error;
- }
- if (!validate_codec(codec, codec_type))
- goto err_out_not_valid;
- mp_tmsg(MSGT_CODECCFG, MSGL_V, "%d audio & %d video codecs\n", nr_acodecs,
- nr_vcodecs);
- if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
- if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
-out:
- talloc_free(tmpmem);
- line=NULL;
- return 1;
-
-err_out_parse_error:
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
-err_out_print_linenum:
- PRINT_LINENUM;
-err_out:
- codecs_uninit_free();
-
- talloc_free(tmpmem);
- line=NULL;
- line_num = 0;
- return 0;
-err_out_not_valid:
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
- goto err_out_print_linenum;
-err_out_release_num:
- mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
- goto err_out_print_linenum;
-}
-
-static void codecs_free(codecs_t* codecs,int count) {
- int i;
- for ( i = 0; i < count; i++)
- if ( codecs[i].name ) {
- free(codecs[i].name);
- free(codecs[i].info);
- free(codecs[i].comment);
- free(codecs[i].dll);
- free(codecs[i].drv);
- }
- free(codecs);
-}
-
-void codecs_uninit_free(void) {
- if (video_codecs)
- codecs_free(video_codecs,nr_vcodecs);
- video_codecs=NULL;
- if (audio_codecs)
- codecs_free(audio_codecs,nr_acodecs);
- audio_codecs=NULL;
-}
-
-codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
- codecs_t *start, int force)
-{
- return find_codec(fourcc, fourccmap, start, 1, force);
-}
-
-codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
- codecs_t *start, int force)
-{
- return find_codec(fourcc, fourccmap, start, 0, force);
-}
-
-struct codecs *find_codec(unsigned int fourcc, unsigned int *fourccmap,
- codecs_t *start, int audioflag, int force)
-{
- struct codecs *c, *end;
-
- if (audioflag) {
- c = audio_codecs;
- end = c + nr_acodecs;
- } else {
- c = video_codecs;
- end = c + nr_vcodecs;
- }
- if (start)
- c = start + 1; // actually starts from the next one after the given one
- for (; c < end; c++) {
- for (int j = 0; j < CODECS_MAX_FOURCC; j++) {
- if (c->fourcc[j] == -1)
- break;
- if (c->fourcc[j] == fourcc) {
- if (fourccmap)
- *fourccmap = c->fourccmap[j];
- return c;
- }
- }
- if (c->anyinput || force)
- return c;
- }
- return NULL;
-}
-
-void stringset_init(stringset_t *set) {
- *set = calloc(1, sizeof(char *));
-}
-
-void stringset_free(stringset_t *set) {
- int count = 0;
- while ((*set)[count]) free((*set)[count++]);
- free(*set);
- *set = NULL;
-}
-
-void stringset_add(stringset_t *set, const char *str) {
- int count = 0;
- while ((*set)[count]) count++;
- count++;
- *set = realloc(*set, sizeof(char *) * (count + 1));
- (*set)[count - 1] = strdup(str);
- (*set)[count] = NULL;
-}
-
-int stringset_test(stringset_t *set, const char *str) {
- stringset_t s;
- for (s = *set; *s; s++)
- if (strcmp(*s, str) == 0)
- return 1;
- return 0;
-}
-
-void list_codecs(int audioflag){
- int i;
- codecs_t *c;
-
- if (audioflag) {
- i = nr_acodecs;
- c = audio_codecs;
- mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
- } else {
- i = nr_vcodecs;
- c = video_codecs;
- mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
- }
- if(!i) return;
- for (/* NOTHING */; i--; c++) {
- char* s="unknown ";
- switch(c->status){
- case CODECS_STATUS_WORKING: s="working ";break;
- case CODECS_STATUS_PROBLEMS: s="problems";break;
- case CODECS_STATUS_NOT_WORKING: s="crashing";break;
- case CODECS_STATUS_UNTESTED: s="untested";break;
- }
- if(c->dll)
- mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
- else
- mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
- }
-}
diff --git a/core/codec-cfg.h b/core/codec-cfg.h
deleted file mode 100644
index 01af497c3d..0000000000
--- a/core/codec-cfg.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_CODEC_CFG_H
-#define MPLAYER_CODEC_CFG_H
-
-#include <stdbool.h>
-
-#define CODECS_MAX_FOURCC 92
-
-// Global flags:
-#define CODECS_FLAG_FLIP (1<<0)
-
-#define CODECS_STATUS__MIN 0
-#define CODECS_STATUS_NOT_WORKING -1
-#define CODECS_STATUS_PROBLEMS 0
-#define CODECS_STATUS_WORKING 1
-#define CODECS_STATUS_UNTESTED 2
-#define CODECS_STATUS__MAX 2
-
-
-#if !defined(GUID_TYPE) && !defined(GUID_DEFINED)
-#define GUID_TYPE 1
-#define GUID_DEFINED 1
-typedef struct {
- unsigned long f1;
- unsigned short f2;
- unsigned short f3;
- unsigned char f4[8];
-} GUID;
-#endif
-
-
-typedef struct codecs {
- unsigned int fourcc[CODECS_MAX_FOURCC];
- unsigned int fourccmap[CODECS_MAX_FOURCC];
- char *name;
- char *info;
- char *comment;
- char *dll;
- char* drv;
- GUID guid;
- short flags;
- short status;
- bool anyinput;
-} codecs_t;
-
-int parse_codec_cfg(const char *cfgfile);
-codecs_t* find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
- codecs_t *start, int force);
-codecs_t* find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
- codecs_t *start, int force);
-codecs_t* find_codec(unsigned int fourcc, unsigned int *fourccmap,
- codecs_t *start, int audioflag, int force);
-void list_codecs(int audioflag);
-void codecs_uninit_free(void);
-
-typedef char ** stringset_t;
-void stringset_init(stringset_t *set);
-void stringset_free(stringset_t *set);
-void stringset_add(stringset_t *set, const char *str);
-int stringset_test(stringset_t *set, const char *str);
-
-#endif /* MPLAYER_CODEC_CFG_H */
diff --git a/core/codecs.c b/core/codecs.c
new file mode 100644
index 0000000000..943860a70b
--- /dev/null
+++ b/core/codecs.c
@@ -0,0 +1,147 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include "core/mp_talloc.h"
+#include "core/bstr.h"
+#include "core/mp_msg.h"
+#include "codecs.h"
+
+void mp_add_decoder(struct mp_decoder_list *list, const char *family,
+ const char *codec, const char *decoder, const char *desc)
+{
+ struct mp_decoder_entry entry = {
+ .family = talloc_strdup(list, family),
+ .codec = talloc_strdup(list, codec),
+ .decoder = talloc_strdup(list, decoder),
+ .desc = talloc_strdup(list, desc),
+ };
+ MP_TARRAY_APPEND(list, list->entries, list->num_entries, entry);
+}
+
+static void mp_add_decoder_entry(struct mp_decoder_list *list,
+ struct mp_decoder_entry *entry)
+{
+ mp_add_decoder(list, entry->family, entry->codec, entry->decoder,
+ entry->desc);
+}
+
+static struct mp_decoder_entry *find_decoder(struct mp_decoder_list *list,
+ bstr family, bstr decoder)
+{
+ for (int n = 0; n < list->num_entries; n++) {
+ struct mp_decoder_entry *cur = &list->entries[n];
+ if (bstr_equals0(decoder, cur->decoder) &&
+ bstr_equals0(family, cur->family))
+ return cur;
+ }
+ return NULL;
+}
+
+// Add entry, but only if it's not yet on the list, and if the codec matches.
+// If codec == NULL, don't compare codecs.
+static void add_new(struct mp_decoder_list *to, struct mp_decoder_entry *entry,
+ const char *codec)
+{
+ if (!entry || (codec && strcmp(entry->codec, codec) != 0))
+ return;
+ if (!find_dec