1
mirror of https://github.com/mpv-player/mpv synced 2024-11-14 22:48:35 +01:00

player: add automatic loading of external cover art files

Picks up files like "cover.jpg". It's made part of normal external file
loading, so I'm adding 3 new options that are direct equivalents for the
options that control loading of external subtitle and audio files. Even
though I bet nobody wants them and they just increase confusion... I
guess the world is actually hell, so this outcome should be fine.

It prefers non-specific external files like "cover.jpg" over embedded
cover art. Not sure if that's wanted or unwanted.

There's some pain over explicitly marking such files as external
pictures. This is basically an optimization: in most cases, a heuristic
would treat an image file loaded with --external-file the same (it's a
heuristic because ffmpeg can't tell us whether something is an image or
a video). However, even with this heuristic, it would decode the cover
art picture again on each seek, which would essentially slow down
seeking in audio files. This bothered me greatly, which is why I'm
adding these additional options at all, and bothered with the previous
commit.

Fixes: #3056
This commit is contained in:
wm4 2020-09-28 00:12:52 +02:00
parent 102a4a8b06
commit 55d7f9ded1
6 changed files with 95 additions and 8 deletions

View File

@ -6603,7 +6603,39 @@ Miscellaneous
``--external-file=<file>``
CLI/config file only alias for ``--external-files-append``. Each use of this
option will add a new external files.
option will add a new external file.
``--cover-art-files=<file-list>``
Use an external file as cover art while playing audio. This makes it appear
on the track list and subject to automatic track selection. Options like
``--audio-display`` control whether such tracks are supposed to be selected.
(The difference to loading a file with ``--external-files`` is that video
tracks will be marked as being pictures, which affects the auto-selection
method. If the passed file is a video, only the first frame will be decoded
and displayed. Enabling the cover art track during playback may show a
random frame if the source file is a video. Normally you're not supposed to
pass videos to this option, so this paragraph describes the behavior
coincidentally resulting from implementation details.)
This is a path list option. See `List Options`_ for details.
``--cover-art-file=<file>``
CLI/config file only alias for ``--cover-art-files-append``. Each use of this
option will add a new external file.
``--cover-art-auto=<no|fuzzy>``
Whether to load _external_ cover art automatically (default: fuzzy). Similar
to ``--sub-auto`` and ``--audio-file-auto``. However, it's currently limited
to picking up a whitelist of "album art" filenames (such as ``cover.jpg``),
so currently only the ``fuzzy`` choice is available. In addition, if a video
already has tracks (which are not marked as cover art), external cover art
will not be loaded.
See ``--cover-art-files`` for details about what constitutes cover art.
See ``--audio-display`` how to control display of cover art (this can be
used to disable cover art that is part of the file).
``--autoload-files=<yes|no>``
Automatically load/select external files (default: yes).

View File

@ -512,8 +512,6 @@ static const m_option_t mp_opts[] = {
#endif
// demuxer.c - select audio/sub file/demuxer
{"audio-files", OPT_PATHLIST(audio_files), .flags = M_OPT_FILE},
{"audio-file", OPT_CLI_ALIAS("audio-files-append")},
{"demuxer", OPT_STRING(demuxer_name)},
{"audio-demuxer", OPT_STRING(audio_demuxer_name)},
{"sub-demuxer", OPT_STRING(sub_demuxer_name)},
@ -573,15 +571,24 @@ static const m_option_t mp_opts[] = {
{"sub-files", OPT_PATHLIST(sub_name), .flags = M_OPT_FILE},
{"sub-file", OPT_CLI_ALIAS("sub-files-append")},
{"audio-files", OPT_PATHLIST(audio_files), .flags = M_OPT_FILE},
{"audio-file", OPT_CLI_ALIAS("audio-files-append")},
{"cover-art-files", OPT_PATHLIST(coverart_files), .flags = M_OPT_FILE},
{"cover-art-file", OPT_CLI_ALIAS("covert-art-files-append")},
{"sub-file-paths", OPT_PATHLIST(sub_paths), .flags = M_OPT_FILE},
{"audio-file-paths", OPT_PATHLIST(audiofile_paths), .flags = M_OPT_FILE},
{"external-files", OPT_PATHLIST(external_files), .flags = M_OPT_FILE},
{"external-file", OPT_CLI_ALIAS("external-files-append")},
{"autoload-files", OPT_FLAG(autoload_files)},
{"sub-auto", OPT_CHOICE(sub_auto,
{"no", -1}, {"exact", 0}, {"fuzzy", 1}, {"all", 2})},
{"audio-file-auto", OPT_CHOICE(audiofile_auto,
{"no", -1}, {"exact", 0}, {"fuzzy", 1}, {"all", 2})},
{"cover-art-auto", OPT_CHOICE(coverart_auto,
{"no", -1}, {"fuzzy", 1})},
{"", OPT_SUBSTRUCT(subs_rend, mp_subtitle_sub_opts)},
{"", OPT_SUBSTRUCT(subs_filt, mp_sub_filter_opts)},
@ -1002,6 +1009,7 @@ static const struct MPOpts mp_default_opts = {
.pitch_correction = 1,
.sub_auto = 0,
.audiofile_auto = -1,
.coverart_auto = 1,
.osd_bar_visible = 1,
.screenshot_template = "mpv-shot%n",
.play_dir = 1,

View File

@ -291,10 +291,12 @@ typedef struct MPOpts {
char **sub_name;
char **sub_paths;
char **audiofile_paths;
char **coverart_files;
char **external_files;
int autoload_files;
int sub_auto;
int audiofile_auto;
int coverart_auto;
int osd_bar_visible;
int w32_priority;

View File

@ -42,6 +42,25 @@ static const char *const audio_exts[] = {"mp3", "aac", "mka", "dts", "flac",
"wv",
NULL};
// Stolen from: vlc/-/blob/master/modules/meta_engine/folder.c#L40
static const char *const cover_files[] = {
"Folder.jpg",
"Folder.png",
"AlbumArtSmall.jpg",
"AlbumArt.jpg",
"Album.jpg",
".folder.png",
"cover.jpg",
"cover.png",
"cover.gif",
"front.jpg",
"front.png",
"front.gif",
"front.bmp",
"thumb.jpg",
NULL
};
static bool test_ext_list(bstr ext, const char *const *list)
{
for (int n = 0; list[n]; n++) {
@ -60,6 +79,15 @@ static int test_ext(bstr ext)
return -1;
}
static int test_filename(bstr fname)
{
for (int n = 0; cover_files[n]; n++) {
if (bstrcasecmp(bstr0(cover_files[n]), fname) == 0)
return STREAM_VIDEO;
}
return -1;
}
bool mp_might_be_subtitle_file(const char *filename)
{
return test_ext(bstr_get_ext(bstr0(filename))) == STREAM_SUB;
@ -159,6 +187,8 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
// check what it is (most likely)
int type = test_ext(tmp_fname_ext);
if (type < 0)
type = test_filename(dename);
char **langs = NULL;
int fuzz = -1;
switch (type) {
@ -170,6 +200,9 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
langs = opts->stream_lang[type];
fuzz = opts->audiofile_auto;
break;
case STREAM_VIDEO:
fuzz = opts->coverart_auto;
break;
}
if (fuzz < 0 || (limit_type >= 0 && limit_type != type))
@ -210,6 +243,10 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
if (!limit_fuzziness && fuzz >= 2)
prio |= 1;
// cover art: just accept it
if (type == STREAM_VIDEO && fuzz >= 1)
prio |= 1;
mp_dbg(log, "Potential external file: \"%s\" Priority: %d\n",
de->d_name, prio);

View File

@ -21,7 +21,7 @@
#include <stdbool.h>
struct subfn {
int type; // STREAM_SUB/STREAM_AUDIO
int type; // STREAM_SUB/STREAM_AUDIO/STREAM_VIDEO(coverart)
int priority;
char *fname;
char *lang;

View File

@ -827,6 +827,8 @@ int mp_add_external_file(struct MPContext *mpctx, char *filename,
t->external_filename = talloc_strdup(t, filename);
t->no_default = sh->type != filter;
t->no_auto_select = t->no_default;
// filter==STREAM_VIDEO always means cover art.
t->attached_picture = t->type == STREAM_VIDEO && filter == STREAM_VIDEO;
if (first_num < 0 && (filter == STREAM_TYPE_COUNT || sh->type == filter))
first_num = mpctx->num_tracks - 1;
}
@ -859,14 +861,15 @@ static void open_external_files(struct MPContext *mpctx, char **files,
// See mp_add_external_file() for meaning of cancel parameter.
void autoload_external_files(struct MPContext *mpctx, struct mp_cancel *cancel)
{
if (mpctx->opts->sub_auto < 0 && mpctx->opts->audiofile_auto < 0)
struct MPOpts *opts = mpctx->opts;
if (opts->sub_auto < 0 && opts->audiofile_auto < 0 && opts->coverart_auto < 0)
return;
if (!mpctx->opts->autoload_files || strcmp(mpctx->filename, "-") == 0)
if (!opts->autoload_files || strcmp(mpctx->filename, "-") == 0)
return;
void *tmp = talloc_new(NULL);
struct subfn *list = find_external_files(mpctx->global, mpctx->filename,
mpctx->opts);
struct subfn *list = find_external_files(mpctx->global, mpctx->filename, opts);
talloc_steal(tmp, list);
int sc[STREAM_TYPE_COUNT] = {0};
@ -887,6 +890,8 @@ void autoload_external_files(struct MPContext *mpctx, struct mp_cancel *cancel)
goto skip;
if (list[i].type == STREAM_AUDIO && !sc[STREAM_VIDEO])
goto skip;
if (list[i].type == STREAM_VIDEO && (sc[STREAM_VIDEO] || !sc[STREAM_AUDIO]))
goto skip;
int first = mp_add_external_file(mpctx, filename, list[i].type, cancel);
if (first < 0)
goto skip;
@ -894,6 +899,8 @@ void autoload_external_files(struct MPContext *mpctx, struct mp_cancel *cancel)
for (int n = first; n < mpctx->num_tracks; n++) {
struct track *t = mpctx->tracks[n];
t->auto_loaded = true;
t->attached_picture =
t->type == STREAM_VIDEO && list[i].type == STREAM_VIDEO;
if (!t->lang)
t->lang = talloc_strdup(t, lang);
}
@ -1364,6 +1371,7 @@ static void load_external_opts_thread(void *p)
load_chapters(mpctx);
open_external_files(mpctx, mpctx->opts->audio_files, STREAM_AUDIO);
open_external_files(mpctx, mpctx->opts->sub_name, STREAM_SUB);
open_external_files(mpctx, mpctx->opts->coverart_files, STREAM_VIDEO);
open_external_files(mpctx, mpctx->opts->external_files, STREAM_TYPE_COUNT);
autoload_external_files(mpctx, mpctx->playback_abort);