demux: add --autocreate-playlist

This commit is contained in:
Kacper Michajłow 2024-07-15 23:22:39 +02:00
parent 4b97c23dac
commit bb9b862f0c
4 changed files with 42 additions and 9 deletions

View File

@ -67,6 +67,7 @@ static const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_disc, &demuxer_desc_disc,
&demuxer_desc_edl, &demuxer_desc_edl,
&demuxer_desc_cue, &demuxer_desc_cue,
&demuxer_desc_playlist,
&demuxer_desc_rawaudio, &demuxer_desc_rawaudio,
&demuxer_desc_rawvideo, &demuxer_desc_rawvideo,
&demuxer_desc_matroska, &demuxer_desc_matroska,
@ -75,7 +76,6 @@ static const demuxer_desc_t *const demuxer_list[] = {
#endif #endif
&demuxer_desc_lavf, &demuxer_desc_lavf,
&demuxer_desc_mf, &demuxer_desc_mf,
&demuxer_desc_playlist,
&demuxer_desc_null, &demuxer_desc_null,
NULL NULL
}; };
@ -117,6 +117,7 @@ const struct m_sub_options demux_conf = {
{"demuxer-backward-playback-step", OPT_DOUBLE(back_seek_size), {"demuxer-backward-playback-step", OPT_DOUBLE(back_seek_size),
M_RANGE(0, DBL_MAX)}, M_RANGE(0, DBL_MAX)},
{"metadata-codepage", OPT_STRING(meta_cp)}, {"metadata-codepage", OPT_STRING(meta_cp)},
{"autocreate-playlist", OPT_BOOL(autocreate_playlist)},
{0} {0}
}, },
.size = sizeof(struct demux_opts), .size = sizeof(struct demux_opts),

View File

@ -86,6 +86,7 @@ struct demux_opts {
double back_seek_size; double back_seek_size;
char *meta_cp; char *meta_cp;
bool force_retry_eof; bool force_retry_eof;
bool autocreate_playlist;
}; };
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1] #define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
@ -211,6 +212,7 @@ struct demuxer_params {
bool stream_record; // if true, enable stream recording if option is set bool stream_record; // if true, enable stream recording if option is set
int stream_flags; int stream_flags;
struct stream *external_stream; // if set, use this, don't open or close streams struct stream *external_stream; // if set, use this, don't open or close streams
bool has_playlist;
// result // result
bool demuxer_failed; bool demuxer_failed;
}; };

View File

@ -85,6 +85,7 @@ struct pl_parser {
bool force; bool force;
bool add_base; bool add_base;
bool line_allocated; bool line_allocated;
bool create_dir_playlist;
enum demux_check check_level; enum demux_check check_level;
struct stream *real_stream; struct stream *real_stream;
char *format; char *format;
@ -463,14 +464,25 @@ static bool scan_dir(struct pl_parser *p, char *path,
static int parse_dir(struct pl_parser *p) static int parse_dir(struct pl_parser *p)
{ {
if (!p->real_stream->is_directory) int ret = -1;
return -1; struct stream *stream = p->real_stream;
if (p->probing) if (p->create_dir_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) {
return 0; int flags = STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY |
STREAM_LESS_NOISE;
bstr dir = mp_dirname(p->real_stream->url);
if (dir.len)
stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);
}
if (!stream->is_directory)
goto done;
if (p->probing) {
ret = 0;
goto done;
}
char *path = mp_file_get_path(p, bstr0(p->real_stream->url)); char *path = mp_file_get_path(p, bstr0(stream->url));
if (!path) if (!path)
return -1; goto done;
struct stat dir_stack[MAX_DIR_STACK]; struct stat dir_stack[MAX_DIR_STACK];
@ -483,8 +495,12 @@ static int parse_dir(struct pl_parser *p)
scan_dir(p, path, dir_stack, 0); scan_dir(p, path, dir_stack, 0);
p->add_base = false; p->add_base = false;
ret = p->pl->num_entries > 0 ? 0 : -1;
return p->pl->num_entries > 0 ? 0 : -1; done:
if (stream != p->real_stream)
free_stream(stream);
return ret;
} }
#define MIME_TYPES(...) \ #define MIME_TYPES(...) \
@ -497,7 +513,6 @@ struct pl_format {
}; };
static const struct pl_format formats[] = { static const struct pl_format formats[] = {
{"directory", parse_dir},
{"m3u", parse_m3u, {"m3u", parse_m3u,
MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")}, MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")},
{"ini", parse_ref_init}, {"ini", parse_ref_init},
@ -505,6 +520,7 @@ static const struct pl_format formats[] = {
MIME_TYPES("audio/x-scpls")}, MIME_TYPES("audio/x-scpls")},
{"url", parse_url}, {"url", parse_url},
{"txt", parse_txt}, {"txt", parse_txt},
{"directory", parse_dir},
}; };
static const struct pl_format *probe_pl(struct pl_parser *p) static const struct pl_format *probe_pl(struct pl_parser *p)
@ -549,6 +565,8 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
p->force = force; p->force = force;
p->check_level = check; p->check_level = check;
p->probing = true; p->probing = true;
p->create_dir_playlist = !demuxer->params->has_playlist && opts->autocreate_playlist;
const struct pl_format *fmt = probe_pl(p); const struct pl_format *fmt = probe_pl(p);
free_stream(p->s); free_stream(p->s);
playlist_clear(p->pl); playlist_clear(p->pl);

View File

@ -1041,6 +1041,17 @@ void prepare_playlist(struct MPContext *mpctx, struct playlist *pl)
if (opts->playlist_pos >= 0) if (opts->playlist_pos >= 0)
pl->current = playlist_entry_from_index(pl, opts->playlist_pos); pl->current = playlist_entry_from_index(pl, opts->playlist_pos);
for (int i = 0; i < pl->num_entries; ++i) {
if (!pl->entries[i]->playlist_path)
continue;
// If playlist_path exists as an element in the playlist itself, it means
// playlist was autogenerated.
if (!strcmp(pl->entries[i]->filename, pl->entries[i]->playlist_path)) {
pl->current = pl->entries[i];
break;
}
}
if (opts->shuffle) if (opts->shuffle)
playlist_shuffle(pl); playlist_shuffle(pl);
@ -1144,6 +1155,7 @@ static MP_THREAD_VOID open_demux_thread(void *ctx)
.stream_flags = mpctx->open_url_flags, .stream_flags = mpctx->open_url_flags,
.stream_record = true, .stream_record = true,
.is_top_level = true, .is_top_level = true,
.has_playlist = mpctx->playlist->num_entries > 1,
}; };
struct demuxer *demux = struct demuxer *demux =
demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global); demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);