mirror of
https://github.com/mpv-player/mpv
synced 2025-02-17 21:27:08 +00:00
player: remove old timeline/ordered chapters support
This commit is contained in:
parent
65f9af1d40
commit
ae55896f42
@ -390,14 +390,14 @@ static int mp_property_media_title(void *ctx, struct m_property *prop,
|
||||
name = mpctx->opts->media_title;
|
||||
if (name && name[0])
|
||||
return m_property_strdup_ro(action, arg, name);
|
||||
if (mpctx->master_demuxer) {
|
||||
name = mp_tags_get_str(mpctx->master_demuxer->metadata, "service_name");
|
||||
if (mpctx->demuxer) {
|
||||
name = mp_tags_get_str(mpctx->demuxer->metadata, "service_name");
|
||||
if (name && name[0])
|
||||
return m_property_strdup_ro(action, arg, name);
|
||||
name = mp_tags_get_str(mpctx->master_demuxer->metadata, "title");
|
||||
name = mp_tags_get_str(mpctx->demuxer->metadata, "title");
|
||||
if (name && name[0])
|
||||
return m_property_strdup_ro(action, arg, name);
|
||||
name = mp_tags_get_str(mpctx->master_demuxer->metadata, "icy-title");
|
||||
name = mp_tags_get_str(mpctx->demuxer->metadata, "icy-title");
|
||||
if (name && name[0])
|
||||
return m_property_strdup_ro(action, arg, name);
|
||||
}
|
||||
@ -439,7 +439,7 @@ static int mp_property_demuxer(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
return m_property_strdup_ro(action, arg, demuxer->desc->name);
|
||||
@ -449,7 +449,7 @@ static int mp_property_file_format(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
const char *name = demuxer->filetype ? demuxer->filetype : demuxer->desc->name;
|
||||
@ -734,7 +734,7 @@ static int mp_property_disc_title(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *d = mpctx->master_demuxer;
|
||||
struct demuxer *d = mpctx->demuxer;
|
||||
if (!d)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
unsigned int title = -1;
|
||||
@ -887,7 +887,7 @@ static int mp_property_edition(void *ctx, struct m_property *prop,
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct MPOpts *opts = mpctx->opts;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
if (demuxer->num_editions <= 0)
|
||||
@ -926,7 +926,7 @@ static int get_edition_entry(int item, int action, void *arg, void *ctx)
|
||||
{
|
||||
struct MPContext *mpctx = ctx;
|
||||
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
struct demux_edition *ed = &demuxer->editions[item];
|
||||
|
||||
char *title = mp_tags_get_str(ed->metadata, "title");
|
||||
@ -946,7 +946,7 @@ static int property_list_editions(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
@ -987,7 +987,7 @@ static int mp_property_disc_titles(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
unsigned int num_titles;
|
||||
if (!demuxer || demux_stream_control(demuxer, STREAM_CTRL_GET_NUM_TITLES,
|
||||
&num_titles) < 1)
|
||||
@ -998,7 +998,7 @@ static int mp_property_disc_titles(void *ctx, struct m_property *prop,
|
||||
static int get_disc_title_entry(int item, int action, void *arg, void *ctx)
|
||||
{
|
||||
struct MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
|
||||
double len = item;
|
||||
if (demux_stream_control(demuxer, STREAM_CTRL_GET_TITLE_LENGTH, &len) < 1)
|
||||
@ -1018,7 +1018,7 @@ static int mp_property_list_disc_titles(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
unsigned int num_titles;
|
||||
if (!demuxer || demux_stream_control(demuxer, STREAM_CTRL_GET_NUM_TITLES,
|
||||
&num_titles) < 1)
|
||||
@ -1042,7 +1042,7 @@ static int mp_property_editions(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
if (demuxer->num_editions <= 0)
|
||||
@ -1055,7 +1055,7 @@ static int mp_property_angle(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
@ -1196,7 +1196,7 @@ static int mp_property_metadata(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
@ -2016,7 +2016,7 @@ static int property_list_tracks(void *ctx, struct m_property *prop,
|
||||
res = talloc_asprintf_append(res, "\n");
|
||||
}
|
||||
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (demuxer && demuxer->num_editions > 1)
|
||||
res = talloc_asprintf_append(res, "\nEdition: %d of %d\n",
|
||||
demuxer->edition + 1,
|
||||
@ -2061,7 +2061,7 @@ static int mp_property_program(void *ctx, struct m_property *prop,
|
||||
MPContext *mpctx = ctx;
|
||||
demux_program_t prog;
|
||||
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "common/common.h"
|
||||
#include "options/options.h"
|
||||
#include "sub/osd.h"
|
||||
#include "demux/timeline.h"
|
||||
#include "audio/audio.h"
|
||||
#include "video/mp_image.h"
|
||||
#include "video/out/vo.h"
|
||||
@ -133,13 +132,6 @@ struct track {
|
||||
char *external_filename;
|
||||
bool auto_loaded;
|
||||
|
||||
// If the track's stream changes with the timeline (ordered chapters).
|
||||
bool under_timeline;
|
||||
|
||||
// Does not change with under_timeline, but is useless for most purposes.
|
||||
struct sh_stream *original_stream;
|
||||
|
||||
// Value can change if under_timeline==true.
|
||||
struct demuxer *demuxer;
|
||||
// Invariant: !stream || stream->demuxer == demuxer
|
||||
struct sh_stream *stream;
|
||||
@ -285,14 +277,10 @@ typedef struct MPContext {
|
||||
struct demuxer **sources; // all open demuxers
|
||||
int num_sources;
|
||||
|
||||
struct timeline *tl;
|
||||
struct timeline_part *timeline;
|
||||
int num_timeline_parts;
|
||||
int timeline_part;
|
||||
struct demux_chapter *chapters;
|
||||
int num_chapters;
|
||||
|
||||
struct demuxer *demuxer; // can change with timeline
|
||||
struct demuxer *demuxer;
|
||||
struct mp_tags *filtered_tags;
|
||||
|
||||
struct track **tracks;
|
||||
@ -307,11 +295,6 @@ typedef struct MPContext {
|
||||
|
||||
struct lavfi *lavfi;
|
||||
|
||||
// Uses: accessing metadata (consider ordered chapters case, where the main
|
||||
// demuxer defines metadata), or special purpose demuxers like TV.
|
||||
struct demuxer *master_demuxer;
|
||||
struct demuxer *track_layout; // complication for ordered chapters
|
||||
|
||||
struct mixer *mixer;
|
||||
struct ao *ao;
|
||||
struct mp_audio *ao_decoder_fmt; // for weak gapless audio check
|
||||
@ -475,8 +458,6 @@ void mp_switch_track_n(struct MPContext *mpctx, int order,
|
||||
void mp_deselect_track(struct MPContext *mpctx, struct track *track);
|
||||
struct track *mp_track_by_tid(struct MPContext *mpctx, enum stream_type type,
|
||||
int tid);
|
||||
bool timeline_switch_to_time(struct MPContext *mpctx, double pts);
|
||||
int timeline_get_for_time(struct MPContext *mpctx, double pts);
|
||||
void add_demuxer_tracks(struct MPContext *mpctx, struct demuxer *demuxer);
|
||||
bool mp_remove_track(struct MPContext *mpctx, struct track *track);
|
||||
struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction,
|
||||
|
@ -64,8 +64,6 @@ static void uninit_demuxer(struct MPContext *mpctx)
|
||||
for (int t = 0; t < STREAM_TYPE_COUNT; t++)
|
||||
mpctx->current_track[r][t] = NULL;
|
||||
}
|
||||
mpctx->track_layout = NULL;
|
||||
mpctx->demuxer = NULL;
|
||||
talloc_free(mpctx->chapters);
|
||||
mpctx->chapters = NULL;
|
||||
mpctx->num_chapters = 0;
|
||||
@ -81,13 +79,8 @@ static void uninit_demuxer(struct MPContext *mpctx)
|
||||
}
|
||||
mpctx->num_tracks = 0;
|
||||
|
||||
mpctx->timeline = NULL;
|
||||
mpctx->num_timeline_parts = 0;
|
||||
timeline_destroy(mpctx->tl);
|
||||
mpctx->tl = NULL;
|
||||
|
||||
free_demuxer_and_stream(mpctx->master_demuxer);
|
||||
mpctx->master_demuxer = NULL;
|
||||
free_demuxer_and_stream(mpctx->demuxer);
|
||||
mpctx->demuxer = NULL;
|
||||
|
||||
talloc_free(mpctx->sources);
|
||||
mpctx->sources = NULL;
|
||||
@ -152,7 +145,7 @@ void print_track_list(struct MPContext *mpctx, const char *msg)
|
||||
|
||||
void update_demuxer_properties(struct MPContext *mpctx)
|
||||
{
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return;
|
||||
demux_update(demuxer);
|
||||
@ -171,7 +164,7 @@ void update_demuxer_properties(struct MPContext *mpctx)
|
||||
MP_INFO(mpctx, "%s\n", b);
|
||||
}
|
||||
}
|
||||
struct demuxer *tracks = mpctx->track_layout;
|
||||
struct demuxer *tracks = mpctx->demuxer;
|
||||
if (tracks->events & DEMUX_EVENT_STREAMS) {
|
||||
add_demuxer_tracks(mpctx, tracks);
|
||||
print_track_list(mpctx, NULL);
|
||||
@ -242,23 +235,6 @@ void reselect_demux_streams(struct MPContext *mpctx)
|
||||
}
|
||||
}
|
||||
|
||||
static struct sh_stream *select_fallback_stream(struct demuxer *d,
|
||||
enum stream_type type,
|
||||
int index)
|
||||
{
|
||||
struct sh_stream *best_stream = NULL;
|
||||
for (int n = 0; n < demux_get_num_stream(d); n++) {
|
||||
struct sh_stream *s = demux_get_stream(d, n);
|
||||
if (s->type == type) {
|
||||
best_stream = s;
|
||||
if (index == 0)
|
||||
break;
|
||||
index -= 1;
|
||||
}
|
||||
}
|
||||
return best_stream;
|
||||
}
|
||||
|
||||
// Called from the demuxer thread if a new packet is available.
|
||||
static void wakeup_demux(void *pctx)
|
||||
{
|
||||
@ -283,80 +259,6 @@ static void enable_demux_thread(struct MPContext *mpctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether reinitialization is required (i.e. it switched to a new part)
|
||||
bool timeline_switch_to_time(struct MPContext *mpctx, double pts)
|
||||
{
|
||||
if (!mpctx->timeline)
|
||||
return false;
|
||||
|
||||
int new_part = mpctx->num_timeline_parts - 1;
|
||||
for (int i = 0; i < mpctx->num_timeline_parts; i++) {
|
||||
if (pts < mpctx->timeline[i + 1].start) {
|
||||
new_part = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mpctx->timeline_part == new_part)
|
||||
return false;
|
||||
mpctx->timeline_part = new_part;
|
||||
struct timeline_part *n = mpctx->timeline + mpctx->timeline_part;
|
||||
|
||||
uninit_audio_chain(mpctx);
|
||||
uninit_video_chain(mpctx);
|
||||
uninit_sub_all(mpctx);
|
||||
if (mpctx->ao && !mpctx->opts->gapless_audio) {
|
||||
ao_drain(mpctx->ao);
|
||||
uninit_audio_out(mpctx);
|
||||
}
|
||||
|
||||
if (mpctx->demuxer) {
|
||||
demux_stop_thread(mpctx->demuxer);
|
||||
for (int i = 0; i < demux_get_num_stream(mpctx->demuxer); i++) {
|
||||
struct sh_stream *sh = demux_get_stream(mpctx->demuxer, i);
|
||||
demuxer_select_track(mpctx->demuxer, sh, false);
|
||||
}
|
||||
}
|
||||
|
||||
mpctx->demuxer = n->source;
|
||||
demux_set_ts_offset(mpctx->demuxer, n->start - n->source_start);
|
||||
|
||||
// While another timeline was active, the selection of active tracks might
|
||||
// have been changed - possibly we need to update this source.
|
||||
for (int x = 0; x < mpctx->num_tracks; x++) {
|
||||
struct track *track = mpctx->tracks[x];
|
||||
if (track->under_timeline) {
|
||||
track->demuxer = mpctx->demuxer;
|
||||
track->stream = demuxer_stream_by_demuxer_id(track->demuxer,
|
||||
track->type,
|
||||
track->demuxer_id);
|
||||
// EDL can have mismatched files in the same timeline
|
||||
if (!track->stream) {
|
||||
track->stream = select_fallback_stream(track->demuxer,
|
||||
track->type,
|
||||
track->user_tid - 1);
|
||||
}
|
||||
|
||||
if (track->d_sub) {
|
||||
for (int order = 0; order < 2; order++) {
|
||||
struct track *cur = mpctx->current_track[order][STREAM_SUB];
|
||||
if (cur && cur->d_sub == track->d_sub)
|
||||
osd_set_sub(mpctx->osd, OSDTYPE_SUB + order, NULL);
|
||||
}
|
||||
sub_destroy(track->d_sub);
|
||||
track->d_sub = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mpctx->playback_initialized) {
|
||||
reselect_demux_streams(mpctx);
|
||||
enable_demux_thread(mpctx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int find_new_tid(struct MPContext *mpctx, enum stream_type t)
|
||||
{
|
||||
int new_id = 0;
|
||||
@ -370,12 +272,11 @@ static int find_new_tid(struct MPContext *mpctx, enum stream_type t)
|
||||
|
||||
static struct track *add_stream_track(struct MPContext *mpctx,
|
||||
struct demuxer *demuxer,
|
||||
struct sh_stream *stream,
|
||||
bool under_timeline)
|
||||
struct sh_stream *stream)
|
||||
{
|
||||
for (int i = 0; i < mpctx->num_tracks; i++) {
|
||||
struct track *track = mpctx->tracks[i];
|
||||
if (track->original_stream == stream)
|
||||
if (track->stream == stream)
|
||||
return track;
|
||||
}
|
||||
|
||||
@ -390,10 +291,8 @@ static struct track *add_stream_track(struct MPContext *mpctx,
|
||||
.forced_track = stream->forced_track,
|
||||
.attached_picture = stream->attached_picture != NULL,
|
||||
.lang = stream->lang,
|
||||
.under_timeline = under_timeline,
|
||||
.demuxer = demuxer,
|
||||
.stream = stream,
|
||||
.original_stream = stream,
|
||||
};
|
||||
MP_TARRAY_APPEND(mpctx, mpctx->tracks, mpctx->num_tracks, track);
|
||||
|
||||
@ -406,10 +305,8 @@ static struct track *add_stream_track(struct MPContext *mpctx,
|
||||
|
||||
void add_demuxer_tracks(struct MPContext *mpctx, struct demuxer *demuxer)
|
||||
{
|
||||
for (int n = 0; n < demux_get_num_stream(demuxer); n++) {
|
||||
add_stream_track(mpctx, demuxer, demux_get_stream(demuxer, n),
|
||||
!!mpctx->timeline);
|
||||
}
|
||||
for (int n = 0; n < demux_get_num_stream(demuxer); n++)
|
||||
add_stream_track(mpctx, demuxer, demux_get_stream(demuxer, n));
|
||||
}
|
||||
|
||||
// Result numerically higher => better match. 0 == no match.
|
||||
@ -658,7 +555,6 @@ bool mp_remove_track(struct MPContext *mpctx, struct track *track)
|
||||
{
|
||||
if (!track->is_external)
|
||||
return false;
|
||||
assert(!track->under_timeline);
|
||||
|
||||
mp_deselect_track(mpctx, track);
|
||||
if (track->selected)
|
||||
@ -675,8 +571,7 @@ bool mp_remove_track(struct MPContext *mpctx, struct track *track)
|
||||
talloc_free(track);
|
||||
|
||||
// Close the demuxer, unless there is still a track using it. These are
|
||||
// all external tracks, so there are no complications due to the timeline
|
||||
// mechanism switching the track's demuxer dynamically.
|
||||
// all external tracks.
|
||||
bool in_use = false;
|
||||
for (int n = mpctx->num_tracks - 1; n >= 0 && !in_use; n--)
|
||||
in_use |= mpctx->tracks[n]->demuxer == d;
|
||||
@ -732,7 +627,7 @@ struct track *mp_add_external_file(struct MPContext *mpctx, char *filename,
|
||||
for (int n = 0; n < demux_get_num_stream(demuxer); n++) {
|
||||
struct sh_stream *sh = demux_get_stream(demuxer, n);
|
||||
if (filter == STREAM_TYPE_COUNT || sh->type == filter) {
|
||||
struct track *t = add_stream_track(mpctx, demuxer, sh, false);
|
||||
struct track *t = add_stream_track(mpctx, demuxer, sh);
|
||||
t->is_external = true;
|
||||
t->title = talloc_strdup(t, mp_basename(disp_filename));
|
||||
t->external_filename = talloc_strdup(t, filename);
|
||||
@ -892,32 +787,9 @@ static void process_unload_hooks(struct MPContext *mpctx)
|
||||
mp_idle(mpctx);
|
||||
}
|
||||
|
||||
static void print_timeline(struct MPContext *mpctx)
|
||||
{
|
||||
if (mpctx->timeline) {
|
||||
int part_count = mpctx->num_timeline_parts;
|
||||
MP_VERBOSE(mpctx, "Timeline contains %d parts from %d "
|
||||
"sources. Total length %.3f seconds.\n", part_count,
|
||||
mpctx->num_sources, mpctx->timeline[part_count].start);
|
||||
MP_VERBOSE(mpctx, "Source files:\n");
|
||||
for (int i = 0; i < mpctx->num_sources; i++)
|
||||
MP_VERBOSE(mpctx, "%d: %s\n", i,
|
||||
mpctx->sources[i]->filename);
|
||||
MP_VERBOSE(mpctx, "Timeline parts: (number, start, "
|
||||
"source_start, source):\n");
|
||||
for (int i = 0; i < part_count; i++) {
|
||||
struct timeline_part *p = mpctx->timeline + i;
|
||||
MP_VERBOSE(mpctx, "%3d %9.3f %9.3f %p/%s\n", i, p->start,
|
||||
p->source_start, p->source, p->source->filename);
|
||||
}
|
||||
MP_VERBOSE(mpctx, "END %9.3f\n",
|
||||
mpctx->timeline[part_count].start);
|
||||
}
|
||||
}
|
||||
|
||||
static void load_chapters(struct MPContext *mpctx)
|
||||
{
|
||||
struct demuxer *src = mpctx->master_demuxer;
|
||||
struct demuxer *src = mpctx->demuxer;
|
||||
bool free_src = false;
|
||||
char *chapter_file = mpctx->opts->chapter_file;
|
||||
if (chapter_file && chapter_file[0]) {
|
||||
@ -961,7 +833,6 @@ struct demux_open_args {
|
||||
struct mp_log *log;
|
||||
// results
|
||||
struct demuxer *demux;
|
||||
struct timeline *tl;
|
||||
int err;
|
||||
};
|
||||
|
||||
@ -982,11 +853,8 @@ static void open_demux_thread(void *pctx)
|
||||
args->err = MPV_ERROR_LOADING_FAILED;
|
||||
}
|
||||
}
|
||||
if (args->demux) {
|
||||
args->tl = timeline_load(global, args->log, args->demux);
|
||||
if (global->opts->rebase_start_time)
|
||||
demux_set_ts_offset(args->demux, -args->demux->start_time);
|
||||
}
|
||||
if (args->demux && global->opts->rebase_start_time)
|
||||
demux_set_ts_offset(args->demux, -args->demux->start_time);
|
||||
}
|
||||
|
||||
static void open_demux_reentrant(struct MPContext *mpctx)
|
||||
@ -1003,8 +871,7 @@ static void open_demux_reentrant(struct MPContext *mpctx)
|
||||
mpctx_run_reentrant(mpctx, open_demux_thread, &args);
|
||||
if (args.demux) {
|
||||
talloc_steal(args.demux, args.global);
|
||||
mpctx->master_demuxer = args.demux;
|
||||
mpctx->tl = args.tl;
|
||||
mpctx->demuxer = args.demux;
|
||||
} else {
|
||||
mpctx->error_playing = args.err;
|
||||
talloc_free(args.global);
|
||||
@ -1012,31 +879,6 @@ static void open_demux_reentrant(struct MPContext *mpctx)
|
||||
talloc_free(args.url);
|
||||
}
|
||||
|
||||
static void load_timeline(struct MPContext *mpctx)
|
||||
{
|
||||
mpctx->track_layout = mpctx->master_demuxer;
|
||||
|
||||
MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources,
|
||||
mpctx->master_demuxer);
|
||||
|
||||
if (mpctx->tl) {
|
||||
mpctx->timeline = mpctx->tl->parts;
|
||||
mpctx->num_timeline_parts = mpctx->tl->num_parts;
|
||||
mpctx->num_chapters = mpctx->tl->num_chapters;
|
||||
mpctx->chapters = demux_copy_chapter_data(mpctx->tl->chapters,
|
||||
mpctx->tl->num_chapters);
|
||||
mpctx->track_layout = mpctx->tl->track_layout;
|
||||
for (int n = 0; n < mpctx->tl->num_sources; n++) {
|
||||
if (mpctx->tl->sources[n] != mpctx->master_demuxer) {
|
||||
MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources,
|
||||
mpctx->tl->sources[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_timeline(mpctx);
|
||||
}
|
||||
|
||||
static bool init_complex_filters(struct MPContext *mpctx)
|
||||
{
|
||||
assert(!mpctx->lavfi);
|
||||
@ -1046,11 +888,6 @@ static bool init_complex_filters(struct MPContext *mpctx)
|
||||
if (!graph || !graph[0])
|
||||
return true;
|
||||
|
||||
if (mpctx->tl) {
|
||||
MP_ERR(mpctx, "complex filters not supported with timeline\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
mpctx->lavfi = lavfi_create(mpctx->log, graph);
|
||||
if (!mpctx->lavfi)
|
||||
return false;
|
||||
@ -1234,11 +1071,8 @@ reopen_file:
|
||||
}
|
||||
|
||||
open_demux_reentrant(mpctx);
|
||||
if (!mpctx->master_demuxer || mpctx->stop_play)
|
||||
if (!mpctx->demuxer || mpctx->stop_play)
|
||||
goto terminate_playback;
|
||||
mpctx->demuxer = mpctx->master_demuxer;
|
||||
|
||||
load_timeline(mpctx);
|
||||
|
||||
if (mpctx->demuxer->playlist) {
|
||||
struct playlist *pl = mpctx->demuxer->playlist;
|
||||
@ -1257,10 +1091,7 @@ reopen_file:
|
||||
}
|
||||
|
||||
load_chapters(mpctx);
|
||||
add_demuxer_tracks(mpctx, mpctx->track_layout);
|
||||
|
||||
mpctx->timeline_part = mpctx->num_timeline_parts;
|
||||
timeline_switch_to_time(mpctx, 0);
|
||||
add_demuxer_tracks(mpctx, mpctx->demuxer);
|
||||
|
||||
open_external_files(mpctx, opts->audio_files, STREAM_AUDIO);
|
||||
open_external_files(mpctx, opts->sub_name, STREAM_SUB);
|
||||
@ -1352,14 +1183,13 @@ reopen_file:
|
||||
goto terminate_playback;
|
||||
}
|
||||
|
||||
// If there's a timeline force an absolute seek to initialize state
|
||||
double startpos = rel_time_to_abs(mpctx, opts->play_start);
|
||||
if (startpos == MP_NOPTS_VALUE && opts->chapterrange[0] > 0) {
|
||||
double start = chapter_start_time(mpctx, opts->chapterrange[0] - 1);
|
||||
if (start != MP_NOPTS_VALUE)
|
||||
startpos = start;
|
||||
}
|
||||
if (startpos == MP_NOPTS_VALUE && mpctx->timeline)
|
||||
if (startpos == MP_NOPTS_VALUE)
|
||||
startpos = 0;
|
||||
if (startpos != MP_NOPTS_VALUE) {
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, startpos, 0, true);
|
||||
|
@ -467,13 +467,11 @@ static void add_seek_osd_messages(struct MPContext *mpctx)
|
||||
"Chapter: %s", chapter);
|
||||
talloc_free(chapter);
|
||||
}
|
||||
if ((mpctx->add_osd_seek_info & OSD_SEEK_INFO_EDITION)
|
||||
&& mpctx->master_demuxer)
|
||||
{
|
||||
if ((mpctx->add_osd_seek_info & OSD_SEEK_INFO_EDITION) && mpctx->demuxer) {
|
||||
set_osd_msg(mpctx, 1, mpctx->opts->osd_duration,
|
||||
"Playing edition %d of %d.",
|
||||
mpctx->master_demuxer->edition + 1,
|
||||
mpctx->master_demuxer->num_editions);
|
||||
mpctx->demuxer->edition + 1,
|
||||
mpctx->demuxer->num_editions);
|
||||
}
|
||||
if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_CURRENT_FILE) {
|
||||
if (mpctx->filename) {
|
||||
|
@ -181,11 +181,9 @@ void reset_playback_state(struct MPContext *mpctx)
|
||||
}
|
||||
|
||||
// return -1 if seek failed (non-seekable stream?), 0 otherwise
|
||||
static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
bool timeline_fallthrough)
|
||||
static int mp_seek(MPContext *mpctx, struct seek_params seek)
|
||||
{
|
||||
struct MPOpts *opts = mpctx->opts;
|
||||
int prev_step = mpctx->step_frames;
|
||||
|
||||
if (!mpctx->demuxer)
|
||||
return -1;
|
||||
@ -254,11 +252,6 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
hr_seek &= seek.type == MPSEEK_ABSOLUTE; // otherwise, no target PTS known
|
||||
|
||||
double demuxer_amount = seek.amount;
|
||||
if (timeline_switch_to_time(mpctx, seek.amount)) {
|
||||
reinit_video_chain(mpctx);
|
||||
reinit_audio_chain(mpctx);
|
||||
reinit_sub_all(mpctx);
|
||||
}
|
||||
|
||||
int demuxer_style = 0;
|
||||
switch (seek.type) {
|
||||
@ -292,30 +285,24 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
}
|
||||
}
|
||||
|
||||
if (!timeline_fallthrough)
|
||||
clear_audio_output_buffers(mpctx);
|
||||
clear_audio_output_buffers(mpctx);
|
||||
|
||||
reset_playback_state(mpctx);
|
||||
|
||||
if (timeline_fallthrough)
|
||||
mpctx->step_frames = prev_step;
|
||||
|
||||
/* Use the target time as "current position" for further relative
|
||||
* seeks etc until a new video frame has been decoded */
|
||||
mpctx->last_seek_pts = target_time;
|
||||
|
||||
// The hr_seek==false case is for skipping frames with PTS before the
|
||||
// current timeline chapter start. It's not really known where the demuxer
|
||||
// It's not really known where the demuxer
|
||||
// level seek will end up, so the hrseek mechanism is abused to skip all
|
||||
// frames before chapter start by setting hrseek_pts to the chapter start.
|
||||
// It does nothing when the seek is inside of the current chapter, and
|
||||
// seeking past the chapter is handled elsewhere.
|
||||
if (hr_seek || mpctx->timeline) {
|
||||
if (hr_seek) {
|
||||
mpctx->hrseek_active = true;
|
||||
mpctx->hrseek_framedrop = !hr_seek_very_exact && opts->hr_seek_framedrop;
|
||||
mpctx->hrseek_backstep = backstep;
|
||||
mpctx->hrseek_pts = hr_seek ? seek.amount
|
||||
: mpctx->timeline[mpctx->timeline_part].start;
|
||||
mpctx->hrseek_pts = seek.amount;
|
||||
|
||||
MP_VERBOSE(mpctx, "hr-seek, skipping to %f%s%s\n", mpctx->hrseek_pts,
|
||||
mpctx->hrseek_framedrop ? "" : " (no framedrop)",
|
||||
@ -382,7 +369,7 @@ void execute_queued_seek(struct MPContext *mpctx)
|
||||
if (!mpctx->seek.immediate && mpctx->video_status < STATUS_READY &&
|
||||
mp_time_sec() - mpctx->start_timestamp < 0.3)
|
||||
return;
|
||||
mp_seek(mpctx, mpctx->seek, false);
|
||||
mp_seek(mpctx, mpctx->seek);
|
||||
mpctx->seek = (struct seek_params){0};
|
||||
}
|
||||
}
|
||||
@ -394,9 +381,6 @@ double get_time_length(struct MPContext *mpctx)
|
||||
if (!demuxer)
|
||||
return -1;
|
||||
|
||||
if (mpctx->timeline)
|
||||
return mpctx->timeline[mpctx->num_timeline_parts].start;
|
||||
|
||||
double len = demuxer_get_time_length(demuxer);
|
||||
if (len >= 0)
|
||||
return len;
|
||||
@ -739,7 +723,7 @@ void seek_to_last_frame(struct MPContext *mpctx)
|
||||
.type = MPSEEK_ABSOLUTE,
|
||||
.amount = end,
|
||||
.exact = MPSEEK_VERY_EXACT,
|
||||
}, false);
|
||||
});
|
||||
// Make it exact: stop seek only if last frame was reached.
|
||||
if (mpctx->hrseek_active) {
|
||||
mpctx->hrseek_pts = 1e99; // "infinite"
|
||||
@ -902,9 +886,7 @@ static void handle_playback_restart(struct MPContext *mpctx, double endpts)
|
||||
}
|
||||
}
|
||||
|
||||
// Determines whether the end of the current segment is reached, and switch to
|
||||
// the next one if required. Also handles regular playback end.
|
||||
static void handle_segment_switch(struct MPContext *mpctx, bool end_is_new_segment)
|
||||
static void handle_eof(struct MPContext *mpctx)
|
||||
{
|
||||
/* Don't quit while paused and we're displaying the last video frame. On the
|
||||
* other hand, if we don't have a video frame, then the user probably seeked
|
||||
@ -917,18 +899,10 @@ static void handle_segment_switch(struct MPContext *mpctx, bool end_is_new_segme
|
||||
*/
|
||||
if ((mpctx->ao_chain || mpctx->vo_chain) && !prevent_eof &&
|
||||
mpctx->audio_status == STATUS_EOF &&
|
||||
mpctx->video_status == STATUS_EOF)
|
||||
mpctx->video_status == STATUS_EOF &&
|
||||
!mpctx->stop_play)
|
||||
{
|
||||
int new_part = mpctx->timeline_part + 1;
|
||||
if (end_is_new_segment && new_part < mpctx->num_timeline_parts) {
|
||||
mp_seek(mpctx, (struct seek_params){
|
||||
.type = MPSEEK_ABSOLUTE,
|
||||
.amount = mpctx->timeline[new_part].start
|
||||
}, true);
|
||||
} else {
|
||||
if (!mpctx->stop_play)
|
||||
mpctx->stop_play = AT_END_OF_FILE;
|
||||
}
|
||||
mpctx->stop_play = AT_END_OF_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -969,7 +943,6 @@ static void handle_complex_filter_decoders(struct MPContext *mpctx)
|
||||
void run_playloop(struct MPContext *mpctx)
|
||||
{
|
||||
double endpts = get_play_end_pts(mpctx);
|
||||
bool end_is_new_segment = false;
|
||||
|
||||
#if HAVE_ENCODING
|
||||
if (encode_lavc_didfail(mpctx->encode_lavc_ctx)) {
|
||||
@ -980,14 +953,6 @@ void run_playloop(struct MPContext *mpctx)
|
||||
|
||||
update_demuxer_properties(mpctx);
|
||||
|
||||
if (mpctx->timeline) {
|
||||
double end = mpctx->timeline[mpctx->timeline_part + 1].start;
|
||||
if (endpts == MP_NOPTS_VALUE || end < endpts) {
|
||||
end_is_new_segment = true;
|
||||
endpts = end;
|
||||
}
|
||||
}
|
||||
|
||||
handle_complex_filter_decoders(mpctx);
|
||||
|
||||
handle_cursor_autohide(mpctx);
|
||||
@ -1021,7 +986,7 @@ void run_playloop(struct MPContext *mpctx)
|
||||
if (!mpctx->video_out)
|
||||
update_subtitles(mpctx, mpctx->playback_pts);
|
||||
|
||||
handle_segment_switch(mpctx, end_is_new_segment);
|
||||
handle_eof(mpctx);
|
||||
|
||||
handle_loop_file(mpctx);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user