From af0c41e162725b0edcd6c3d066a2dbef05a3b896 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 7 Jul 2013 23:54:11 +0200 Subject: Remove old demuxers Delete demux_avi, demux_asf, demux_mpg, demux_ts. libavformat does better than them (except in rare corner cases), and the demuxers have a bad influence on the rest of the code. Often they don't output proper packets, and require additional audio and video parsing. Most work only in --no-correct-pts mode. Remove them to facilitate further cleanups. --- core/options.c | 13 +++++-------- core/options.h | 1 + 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'core') diff --git a/core/options.c b/core/options.c index b00f79c003..c0e64b0dcd 100644 --- a/core/options.c +++ b/core/options.c @@ -25,6 +25,7 @@ #include #include +#include #include "core/options.h" #include "config.h" @@ -369,12 +370,9 @@ const m_option_t mp_opts[] = { OPT_FLAG("pause", pause, 0), OPT_FLAG("keep-open", keep_open, 0), - // AVI specific: force non-interleaved mode - {"avi-ni", &force_ni, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - // AVI and Ogg only: (re)build index at startup - {"idx", &index_mode, CONF_TYPE_FLAG, 0, -1, 1, NULL}, - {"forceidx", &index_mode, CONF_TYPE_FLAG, 0, -1, 2, NULL}, + OPT_FLAG_CONSTANTS("idx", index_mode, 0, -1, 1), + OPT_FLAG_STORE("forceidx", index_mode, 0, 2), // select audio/video/subtitle stream OPT_TRACKCHOICE("aid", audio_id), @@ -419,9 +417,6 @@ const m_option_t mp_opts[] = { // ------------------------- a-v sync options -------------------- - // AVI specific: A-V sync mode (bps vs. interleaving) - {"bps", &pts_from_bps, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - // set A-V sync correction speed (0=disables it): OPT_FLOATRANGE("mc", default_max_pts_correction, 0, 0, 100), @@ -804,6 +799,8 @@ const struct MPOpts mp_default_opts = { .hwdec_codecs = "all", + .index_mode = -1, + .ad_lavc_param = { .ac3drc = 1., .downmix = 1, diff --git a/core/options.h b/core/options.h index 1eb111e33e..f7be4adb02 100644 --- a/core/options.h +++ b/core/options.h @@ -160,6 +160,7 @@ typedef struct MPOpts { char *screenshot_template; double force_fps; + int index_mode; // -1=untouched 0=don't use index 1=use (generate) index struct mp_chmap audio_output_channels; int audio_output_format; -- cgit v1.2.3 From 90813f340250a3848f66f13a644e74a92ca5d907 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 00:39:29 +0200 Subject: demux: remove video_read_properties --- core/mplayer.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 79626fdc80..16277d2e60 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2357,25 +2357,20 @@ int reinit_video_chain(struct MPContext *mpctx) goto no_video; } - if (!video_read_properties(mpctx->sh_video)) { - mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Video: Cannot read properties.\n"); - goto err_out; - } else { - mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] filefmt:%d fourcc:0x%X " - "size:%dx%d fps:%5.3f ftime:=%6.4f\n", - mpctx->master_demuxer->file_format, mpctx->sh_video->format, - mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, - mpctx->sh_video->fps, mpctx->sh_video->frametime); - if (opts->force_fps) { - mpctx->sh_video->fps = opts->force_fps; - mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps; - } - update_fps(mpctx); + mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] filefmt:%d fourcc:0x%X " + "size:%dx%d fps:%5.3f ftime:=%6.4f\n", + mpctx->master_demuxer->file_format, mpctx->sh_video->format, + mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, + mpctx->sh_video->fps, mpctx->sh_video->frametime); + if (opts->force_fps) { + mpctx->sh_video->fps = opts->force_fps; + mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps; + } + update_fps(mpctx); - if (!mpctx->sh_video->fps && !opts->force_fps && !opts->correct_pts) { - mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "FPS not specified in the " - "header or invalid, use the -fps option.\n"); - } + if (!mpctx->sh_video->fps && !opts->force_fps && !opts->correct_pts) { + mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "FPS not specified in the " + "header or invalid, use the -fps option.\n"); } double ar = -1.0; -- cgit v1.2.3 From 05ae5afd6249af9770eb1e55104fbd4f510c2342 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 01:26:13 +0200 Subject: demux: remove separate arrays for audio/video/sub streams, simplify These separate arrays were used by the old demuxers and are not needed anymore. We can simplify track switching as well. One interesting thing is that stream/tv.c (which is a demuxer) won't respect --no-audio anymore. It will probably work as expected, but it will still open an audio device etc. - this is because track selection is now always done with the runtime track switching mechanism. Maybe the TV code could be updated to do proper runtime switching, but I can't test this stuff. --- core/command.c | 8 ++++---- core/mplayer.c | 15 ++++++--------- 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'core') diff --git a/core/command.c b/core/command.c index 80f6f5d9d2..fb21d7bc41 100644 --- a/core/command.c +++ b/core/command.c @@ -566,13 +566,13 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg, case M_PROPERTY_SET: angle = demuxer_set_angle(demuxer, *(int *)arg); if (angle >= 0) { - struct sh_video *sh_video = demuxer->video->sh; + struct sh_stream *sh_video = demuxer->video->gsh; if (sh_video) - resync_video_stream(sh_video); + resync_video_stream(sh_video->video); - struct sh_audio *sh_audio = demuxer->audio->sh; + struct sh_stream *sh_audio = demuxer->audio->gsh; if (sh_audio) - resync_audio_stream(sh_audio); + resync_audio_stream(sh_audio->audio); } return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: { diff --git a/core/mplayer.c b/core/mplayer.c index 16277d2e60..78fb8c9a8e 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -375,7 +375,7 @@ static double get_main_demux_pts(struct MPContext *mpctx) if (mpctx->demuxer) { for (int type = 0; type < STREAM_TYPE_COUNT; type++) { struct demux_stream *ds = mpctx->demuxer->ds[type]; - if (ds->sh && main_new_pos == MP_NOPTS_VALUE) { + if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) { demux_fill_buffer(mpctx->demuxer, ds); if (ds->first) main_new_pos = ds->first->pts; @@ -445,11 +445,11 @@ static void preselect_demux_streams(struct MPContext *mpctx) static void uninit_subs(struct demuxer *demuxer) { - for (int i = 0; i < MAX_S_STREAMS; i++) { - struct sh_sub *sh = demuxer->s_streams[i]; - if (sh) { - sub_destroy(sh->dec_sub); - sh->dec_sub = NULL; + for (int i = 0; i < demuxer->num_streams; i++) { + struct sh_stream *sh = demuxer->streams[i]; + if (sh->sub) { + sub_destroy(sh->sub->dec_sub); + sh->sub->dec_sub = NULL; } } } @@ -1938,9 +1938,6 @@ static void reinit_subs(struct MPContext *mpctx) // which makes the demuxer create the sh_stream, and contains the first // subtitle event. - // demux_mpg - maps IDs directly to the logical stream number - track->demuxer->sub->id = track->demuxer_id; - // demux_lavf - IDs are essentially random, have to use MPEG IDs int id = map_id_to_demuxer(track->demuxer, track->type, track->demuxer_id); -- cgit v1.2.3 From 73c76de91edbf8a55eb725196ff54583e3428510 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 01:37:30 +0200 Subject: demux: simplify demux_open() calls The demux_open as well as demux_open_withparams calls don't use the stream selection parameters anymore, so remove them everywhere. Completes the previous commit. --- core/mplayer.c | 11 +---------- core/timeline/tl_cue.c | 12 ++---------- core/timeline/tl_edl.c | 3 --- core/timeline/tl_matroska.c | 3 +-- 4 files changed, 4 insertions(+), 25 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 78fb8c9a8e..019d37081d 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -3890,20 +3890,12 @@ static struct track *open_external_file(struct MPContext *mpctx, char *filename, stream_enable_cache_percent(&stream, stream_cache, opts->stream_cache_min_percent, opts->stream_cache_seek_min_percent); - // deal with broken demuxers: preselect streams - int vs = -2, as = -2, ss = -2; - switch (filter) { - case STREAM_VIDEO: vs = -1; break; - case STREAM_AUDIO: as = -1; break; - case STREAM_SUB: ss = -1; break; - } - vs = -1; // avi can't go without video struct demuxer_params params = { .ass_library = mpctx->ass_library, // demux_libass requires it }; struct demuxer *demuxer = demux_open_withparams(&mpctx->opts, stream, format, demuxer_name, - as, vs, ss, filename, ¶ms); + filename, ¶ms); if (!demuxer) { free_stream(stream); goto err_out; @@ -4219,7 +4211,6 @@ goto_reopen_demuxer: ; mpctx->audio_delay = opts->audio_delay; mpctx->demuxer = demux_open(opts, mpctx->stream, file_format, - opts->audio_id, opts->video_id, opts->sub_id, mpctx->filename); mpctx->master_demuxer = mpctx->demuxer; diff --git a/core/timeline/tl_cue.c b/core/timeline/tl_cue.c index d9160e0b8e..a965cfd877 100644 --- a/core/timeline/tl_cue.c +++ b/core/timeline/tl_cue.c @@ -192,11 +192,7 @@ static bool try_open(struct MPContext *mpctx, char *filename) struct stream *s = open_stream(filename, &mpctx->opts, &format); if (!s) return false; - struct demuxer *d = demux_open(&mpctx->opts, s, format, - mpctx->opts.audio_id, - mpctx->opts.video_id, - mpctx->opts.sub_id, - filename); + struct demuxer *d = demux_open(&mpctx->opts, s, format, filename); // Since .bin files are raw PCM data with no headers, we have to explicitly // open them. Also, try to avoid to open files that are most likely not .bin // files, as that would only play noise. Checking the file extension is @@ -205,11 +201,7 @@ static bool try_open(struct MPContext *mpctx, char *filename) // CD sector size (2352 bytes) if (!d && bstr_case_endswith(bfilename, bstr0(".bin"))) { mp_msg(MSGT_CPLAYER, MSGL_WARN, "CUE: Opening as BIN file!\n"); - d = demux_open(&mpctx->opts, s, DEMUXER_TYPE_RAWAUDIO, - mpctx->opts.audio_id, - mpctx->opts.video_id, - mpctx->opts.sub_id, - filename); + d = demux_open(&mpctx->opts, s, DEMUXER_TYPE_RAWAUDIO, filename); } if (d) { add_source(mpctx, d); diff --git a/core/timeline/tl_edl.c b/core/timeline/tl_edl.c index 5ec04ac716..0303956513 100644 --- a/core/timeline/tl_edl.c +++ b/core/timeline/tl_edl.c @@ -360,9 +360,6 @@ void build_edl_timeline(struct MPContext *mpctx) if (!s) goto openfail; struct demuxer *d = demux_open(&mpctx->opts, s, format, - mpctx->opts.audio_id, - mpctx->opts.video_id, - mpctx->opts.sub_id, edl_ids[i].filename); if (!d) { free_stream(s); diff --git a/core/timeline/tl_matroska.c b/core/timeline/tl_matroska.c index 11fcc67583..6752b5ff4c 100644 --- a/core/timeline/tl_matroska.c +++ b/core/timeline/tl_matroska.c @@ -117,8 +117,7 @@ static struct demuxer *open_demuxer(struct stream *stream, struct MPContext *mpctx, char *filename, struct demuxer_params *params) { return demux_open_withparams(&mpctx->opts, stream, - DEMUXER_TYPE_MATROSKA, NULL, mpctx->opts.audio_id, - mpctx->opts.video_id, mpctx->opts.sub_id, filename, params); + DEMUXER_TYPE_MATROSKA, NULL, filename, params); } static int enable_cache(struct MPContext *mpctx, struct stream **stream, -- cgit v1.2.3 From 9bb7935ce186d55aaaafd708e7559345082ecabc Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 21:59:44 +0200 Subject: options: remove --ignore-start This was used only with demux_avi. --- core/mplayer.c | 9 --------- core/options.c | 3 --- core/options.h | 1 - 3 files changed, 13 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 019d37081d..bb6a87642e 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -4298,15 +4298,6 @@ goto_reopen_demuxer: ; //================ SETUP STREAMS ========================== - if (mpctx->sh_video) { - if (!opts->ignore_start) - mpctx->audio_delay += mpctx->sh_video->stream_delay; - } - if (mpctx->sh_audio) { - if (!opts->ignore_start) - mpctx->audio_delay -= mpctx->sh_audio->stream_delay; - } - if (opts->force_fps && mpctx->sh_video) { mpctx->sh_video->fps = opts->force_fps; mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps; diff --git a/core/options.c b/core/options.c index c0e64b0dcd..d676cb4948 100644 --- a/core/options.c +++ b/core/options.c @@ -430,9 +430,6 @@ const m_option_t mp_opts[] = { // set a-v distance OPT_FLOATRANGE("audio-delay", audio_delay, 0, -100.0, 100.0), - // ignore header-specified delay (dwStart) - OPT_FLAG("ignore-start", ignore_start, 0), - // ------------------------- codec/vfilter options -------------------- {"af*", &af_cfg.list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL}, diff --git a/core/options.h b/core/options.h index f7be4adb02..d46435bf9e 100644 --- a/core/options.h +++ b/core/options.h @@ -105,7 +105,6 @@ typedef struct MPOpts { float hr_seek_demuxer_offset; float audio_delay; float default_max_pts_correction; - int ignore_start; int autosync; int softsleep; int frame_dropping; -- cgit v1.2.3 From 9200538b398a2f6d1be6bca107c58fd1a4070b01 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 23:32:44 +0200 Subject: audio: remove decoder input buffer This was unused. --- core/mplayer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index bb6a87642e..b1a7209a97 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1708,11 +1708,9 @@ static double written_audio_pts(struct MPContext *mpctx) return a_pts; // ds_tell_pts returns bytes read after last timestamp from - // demuxing layer, decoder might use sh_audio->a_in_buffer for bytes - // it has read but not decoded + // demuxing layer if (sh_audio->i_bps) - a_pts += (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len) / - (double)sh_audio->i_bps; + a_pts += ds_tell_pts(d_audio) / (double)sh_audio->i_bps; } // Now a_pts hopefully holds the pts for end of audio from decoder. // Substract data in buffers between decoder and audio out. -- cgit v1.2.3 From 186f6021b1aebd84dbb625d8747d5edaaf87dd38 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 10 Jul 2013 02:07:26 +0200 Subject: core: move code from demux/video.c to mplayer.c Although I don't like putting even more crap into mplayer.c, this is a bit better, especially with coming cleanups in mind. --- core/mplayer.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index b1a7209a97..2f5e103dd1 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2483,6 +2483,69 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame) filter_output_queued_frame(mpctx); } + +static int video_read_frame(sh_video_t *sh_video, float *frame_time_ptr, + unsigned char **start, int force_fps) +{ + demux_stream_t *d_video = sh_video->ds; + demuxer_t *demuxer = d_video->demuxer; + float frame_time = 1; + float pts1 = d_video->pts; + int in_size = 0; + + *start = NULL; + + // frame-based file formats: (AVI,ASF,MOV) + in_size = ds_get_packet(d_video, start); + if (in_size < 0) + return -1; // EOF + + frame_time *= sh_video->frametime; + + // override frame_time for variable/unknown FPS formats: + if (!force_fps) { + switch (demuxer->file_format) { + case DEMUXER_TYPE_MATROSKA: + case DEMUXER_TYPE_MNG: + if (d_video->pts > 0 && pts1 > 0 && d_video->pts>pts1) + frame_time = d_video->pts-pts1; + break; + case DEMUXER_TYPE_TV: { + double next_pts = ds_get_next_pts(d_video); + double d= (next_pts != MP_NOPTS_VALUE) ? next_pts - d_video->pts : d_video->pts-pts1; + if (d >= 0) { + if(d > 0){ + if ((int)sh_video->fps == 1000) + mp_msg(MSGT_CPLAYER,MSGL_V,"\navg. framerate: %d fps \n",(int)(1.0f/d)); + sh_video->frametime = d; // 1ms + sh_video->fps = 1.0f/d; + } + frame_time = d; + } else { + mp_msg(MSGT_CPLAYER,MSGL_WARN,"\nInvalid frame duration value (%5.3f/%5.3f => %5.3f). Defaulting to %5.3f sec.\n",d_video->pts,next_pts,d,frame_time); + // frame_time = 1/25.0; + } + break; + } + case DEMUXER_TYPE_LAVF: + if ((int)sh_video->fps == 1000 || (int)sh_video->fps <= 1) { + double next_pts = ds_get_next_pts(d_video); + double d = (next_pts != MP_NOPTS_VALUE) ? next_pts - d_video->pts : d_video->pts - pts1; + if(d>=0){ + frame_time = d; + } + } + break; + } + } + + sh_video->pts = d_video->pts; + + if (frame_time_ptr) + *frame_time_ptr=frame_time; + return in_size; +} + static double update_video_nocorrect_pts(struct MPContext *mpctx) { struct sh_video *sh_video = mpctx->sh_video; -- cgit v1.2.3 From 5ec611e7bab8afda8e0242d1754df9b552c368ad Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 10 Jul 2013 02:07:47 +0200 Subject: core: simplify some no-correct-pts code Remove the special handling for mng/mkv. These don't profit at all from no-correct-pts mode, and even removing the mkv specific code makes mkv work better (wow!). Don't check for (int)fps == 1000. I don't know where this value comes from. Maybe it was once a special value which triggered certain behavior, but the code for that must have gone away. The only way to trigger this value would be by coincidence if two frames are 1 ms apart. Otherwise, the behavior should be exactly the same, except for some removed messages. --- core/mplayer.c | 46 +++++++++++++--------------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 2f5e103dd1..8470a29295 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2484,12 +2484,11 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame) } -static int video_read_frame(sh_video_t *sh_video, float *frame_time_ptr, +static int video_read_frame(sh_video_t *sh_video, unsigned char **start, int force_fps) { demux_stream_t *d_video = sh_video->ds; demuxer_t *demuxer = d_video->demuxer; - float frame_time = 1; float pts1 = d_video->pts; int in_size = 0; @@ -2500,49 +2499,30 @@ static int video_read_frame(sh_video_t *sh_video, float *frame_time_ptr, if (in_size < 0) return -1; // EOF - frame_time *= sh_video->frametime; + float frame_time = sh_video->frametime; // override frame_time for variable/unknown FPS formats: if (!force_fps) { - switch (demuxer->file_format) { - case DEMUXER_TYPE_MATROSKA: - case DEMUXER_TYPE_MNG: - if (d_video->pts > 0 && pts1 > 0 && d_video->pts>pts1) - frame_time = d_video->pts-pts1; - break; - case DEMUXER_TYPE_TV: { - double next_pts = ds_get_next_pts(d_video); - double d= (next_pts != MP_NOPTS_VALUE) ? next_pts - d_video->pts : d_video->pts-pts1; - if (d >= 0) { - if(d > 0){ - if ((int)sh_video->fps == 1000) - mp_msg(MSGT_CPLAYER,MSGL_V,"\navg. framerate: %d fps \n",(int)(1.0f/d)); - sh_video->frametime = d; // 1ms - sh_video->fps = 1.0f/d; + double next_pts = ds_get_next_pts(d_video); + double d = next_pts == MP_NOPTS_VALUE ? d_video->pts - pts1 + : next_pts - d_video->pts; + if (d >= 0) { + if (demuxer->file_format == DEMUXER_TYPE_TV) { + if (d > 0) { + sh_video->frametime = d; + sh_video->fps = 1.0f / d; } frame_time = d; } else { - mp_msg(MSGT_CPLAYER,MSGL_WARN,"\nInvalid frame duration value (%5.3f/%5.3f => %5.3f). Defaulting to %5.3f sec.\n",d_video->pts,next_pts,d,frame_time); - // frame_time = 1/25.0; - } - break; - } - case DEMUXER_TYPE_LAVF: - if ((int)sh_video->fps == 1000 || (int)sh_video->fps <= 1) { - double next_pts = ds_get_next_pts(d_video); - double d = (next_pts != MP_NOPTS_VALUE) ? next_pts - d_video->pts : d_video->pts - pts1; - if(d>=0){ + if ((int)sh_video->fps <= 1) frame_time = d; - } } - break; } } sh_video->pts = d_video->pts; - if (frame_time_ptr) - *frame_time_ptr=frame_time; + sh_video->next_frame_time = frame_time; return in_size; } @@ -2563,7 +2543,7 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) frame_time = 0; int in_size = 0; while (!in_size) - in_size = video_read_frame(sh_video, &sh_video->next_frame_time, + in_size = video_read_frame(sh_video, &packet, mpctx->opts.force_fps); if (in_size < 0) return -1; -- cgit v1.2.3 From 07c5327fa0c3411bcb8caad17d70b014d6b022dd Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 10 Jul 2013 02:09:10 +0200 Subject: core: remove demux_mpg subtitle PTS hack This code used to be part of the demux_mpg and vobsub specific code path. Then (just recently) the different code paths for subtitles were merged, so this code became active even for demux_lavf and demux_mkv. As far as I can tell, this code won't help much, and at least sd_lavc (which will be used for DVD subs and other potentially weird things) can deal with NOPTS values. --- core/mplayer.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 8470a29295..217e99ed5c 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1792,20 +1792,6 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) if (!d_sub->first) break; double subpts_s = ds_get_next_pts(d_sub); - if (subpts_s == MP_NOPTS_VALUE) { - // Try old method of getting PTS. This is only needed in the - // DVD playback case with demux_mpg. - // XXX This is wrong, sh_video->pts can be arbitrarily - // much behind demuxing position. Unfortunately using - // d_video->pts which would have been the simplest - // improvement doesn't work because mpeg specific hacks - // in video.c set d_video->pts to 0. - float x = d_sub->pts - refpts_s; - if (x > -20 && x < 20) // prevent missing subs on pts reset - subpts_s = d_sub->pts; - else - subpts_s = curpts_s; - } if (subpts_s > curpts_s) { mp_dbg(MSGT_CPLAYER, MSGL_DBG2, "Sub early: c_pts=%5.3f s_pts=%5.3f\n", @@ -1817,16 +1803,11 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) if (non_interleaved && subpts_s > curpts_s + 1) break; } - struct demux_packet pkt; - struct demux_packet *orig = ds_get_packet_sub(d_sub); - if (!orig) - break; - pkt = *orig; - pkt.pts = subpts_s; + struct demux_packet *pkt = ds_get_packet_sub(d_sub); mp_dbg(MSGT_CPLAYER, MSGL_V, "Sub: c_pts=%5.3f s_pts=%5.3f " - "duration=%5.3f len=%d\n", curpts_s, pkt.pts, pkt.duration, - pkt.len); - sub_decode(dec_sub, &pkt); + "duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration, + pkt->len); + sub_decode(dec_sub, pkt); } } -- cgit v1.2.3 From a5224836293ac02bd13f688cfc848aae6818e963 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:10:33 +0200 Subject: demux: remove facility for partial packet reads Partial packet reads were needed because the video/audio parsers were working on top of them. So it could happen that a parser read a part of a packet, and returned that to the decoder. With libavformat/libavcodec, packets are already parsed, and everything is much simpler. Most of the simplifications in ad_spdif could have been done earlier. Remove some other stuff as well, like the questionable slave mode start time reporting (could be replaced by proper code, but we don't bother). Remove the unused skip_audio_frame() functionality as well (it was used by old demuxers). Some functions become private to demux.c, like demux_fill_buffer(). Introduce new packet read functions, which have simpler semantics. Packets returned from them are owned by the caller, and all packets in the demux.c packet queue are considered unread. Remove special code that dropped subtitle packets with size 0. This used to be needed because it caused special cases in the old code. --- core/mplayer.c | 86 ++++++++++++++++++++-------------------------------------- 1 file changed, 30 insertions(+), 56 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 217e99ed5c..0d07b518d8 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -288,8 +288,6 @@ static void print_stream(struct MPContext *mpctx, struct track *t) static void print_file_properties(struct MPContext *mpctx, const char *filename) { - double start_pts = MP_NOPTS_VALUE; - double video_start_pts = MP_NOPTS_VALUE; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILENAME=%s\n", filename); if (mpctx->sh_video) { @@ -310,7 +308,6 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename) "ID_VIDEO_FPS=%5.3f\n", mpctx->sh_video->fps); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n", mpctx->sh_video->aspect); - video_start_pts = ds_get_next_pts(mpctx->sh_video->ds); } if (mpctx->sh_audio) { /* Assume FOURCC if all bytes >= 0x20 (' ') */ @@ -326,17 +323,7 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename) "ID_AUDIO_RATE=%d\n", mpctx->sh_audio->samplerate); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_NCH=%d\n", mpctx->sh_audio->channels.num); - start_pts = ds_get_next_pts(mpctx->sh_audio->ds); } - if (video_start_pts != MP_NOPTS_VALUE) { - if (start_pts == MP_NOPTS_VALUE || !mpctx->sh_audio || - (mpctx->sh_video && video_start_pts < start_pts)) - start_pts = video_start_pts; - } - if (start_pts != MP_NOPTS_VALUE) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=%.2f\n", start_pts); - else - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=unknown\n"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_LENGTH=%.2f\n", get_time_length(mpctx)); int chapter_count = get_chapter_count(mpctx); @@ -375,11 +362,8 @@ static double get_main_demux_pts(struct MPContext *mpctx) if (mpctx->demuxer) { for (int type = 0; type < STREAM_TYPE_COUNT; type++) { struct demux_stream *ds = mpctx->demuxer->ds[type]; - if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) { - demux_fill_buffer(mpctx->demuxer, ds); - if (ds->first) - main_new_pos = ds->first->pts; - } + if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) + main_new_pos = demux_get_next_pts(ds->gsh); } } return main_new_pos; @@ -1703,14 +1687,14 @@ static double written_audio_pts(struct MPContext *mpctx) // ratio is not constant for every audio packet or if it is constant // but not accurately known in sh_audio->i_bps. - a_pts = d_audio->pts; + a_pts = d_audio->last_pts; if (a_pts == MP_NOPTS_VALUE) return a_pts; // ds_tell_pts returns bytes read after last timestamp from // demuxing layer if (sh_audio->i_bps) - a_pts += ds_tell_pts(d_audio) / (double)sh_audio->i_bps; + a_pts += d_audio->last_pts_bytes / (double)sh_audio->i_bps; } // Now a_pts hopefully holds the pts for end of audio from decoder. // Substract data in buffers between decoder and audio out. @@ -1783,15 +1767,14 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) double curpts_s = refpts_s + opts->sub_delay; if (!track->preloaded) { - struct demux_stream *d_sub = sh_sub->ds; bool non_interleaved = is_non_interleaved(mpctx, track); while (1) { - if (non_interleaved) - ds_get_next_pts(d_sub); - if (!d_sub->first) + if (!non_interleaved && !demux_has_packet(sh_sub->gsh)) + break; + double subpts_s = demux_get_next_pts(sh_sub->gsh); + if (!demux_has_packet(sh_sub->gsh)) break; - double subpts_s = ds_get_next_pts(d_sub); if (subpts_s > curpts_s) { mp_dbg(MSGT_CPLAYER, MSGL_DBG2, "Sub early: c_pts=%5.3f s_pts=%5.3f\n", @@ -1803,11 +1786,12 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) if (non_interleaved && subpts_s > curpts_s + 1) break; } - struct demux_packet *pkt = ds_get_packet_sub(d_sub); + struct demux_packet *pkt = demux_read_packet(sh_sub->gsh); mp_dbg(MSGT_CPLAYER, MSGL_V, "Sub: c_pts=%5.3f s_pts=%5.3f " "duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration, pkt->len); sub_decode(dec_sub, pkt); + talloc_free(pkt); } } @@ -2465,28 +2449,24 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame) } -static int video_read_frame(sh_video_t *sh_video, - unsigned char **start, int force_fps) +static struct demux_packet *video_read_frame(struct MPContext *mpctx) { + sh_video_t *sh_video = mpctx->sh_video; demux_stream_t *d_video = sh_video->ds; demuxer_t *demuxer = d_video->demuxer; - float pts1 = d_video->pts; - int in_size = 0; - - *start = NULL; + float pts1 = d_video->last_pts; - // frame-based file formats: (AVI,ASF,MOV) - in_size = ds_get_packet(d_video, start); - if (in_size < 0) - return -1; // EOF + struct demux_packet *pkt = demux_read_packet(sh_video->gsh); + if (!pkt) + return NULL; // EOF float frame_time = sh_video->frametime; // override frame_time for variable/unknown FPS formats: - if (!force_fps) { - double next_pts = ds_get_next_pts(d_video); - double d = next_pts == MP_NOPTS_VALUE ? d_video->pts - pts1 - : next_pts - d_video->pts; + if (!mpctx->opts.force_fps) { + double next_pts = demux_get_next_pts(sh_video->gsh); + double d = next_pts == MP_NOPTS_VALUE ? d_video->last_pts - pts1 + : next_pts - d_video->last_pts; if (d >= 0) { if (demuxer->file_format == DEMUXER_TYPE_TV) { if (d > 0) { @@ -2501,10 +2481,10 @@ static int video_read_frame(sh_video_t *sh_video, } } - sh_video->pts = d_video->pts; + sh_video->pts = d_video->last_pts; sh_video->next_frame_time = frame_time; - return in_size; + return pkt; } static double update_video_nocorrect_pts(struct MPContext *mpctx) @@ -2518,15 +2498,11 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) break; if (filter_output_queued_frame(mpctx)) break; - unsigned char *packet = NULL; frame_time = sh_video->next_frame_time; if (mpctx->restart_playback) frame_time = 0; - int in_size = 0; - while (!in_size) - in_size = video_read_frame(sh_video, - &packet, mpctx->opts.force_fps); - if (in_size < 0) + struct demux_packet *pkt = video_read_frame(mpctx); + if (!pkt) return -1; if (mpctx->sh_audio) mpctx->delay -= frame_time; @@ -2534,13 +2510,9 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) update_fps(mpctx); int framedrop_type = check_framedrop(mpctx, frame_time); - struct demux_packet pkt = {0}; - if (sh_video->ds->current) - pkt = *sh_video->ds->current; - pkt.buffer = packet; - pkt.len = in_size; - void *decoded_frame = decode_video(sh_video, &pkt, framedrop_type, + void *decoded_frame = decode_video(sh_video, pkt, framedrop_type, sh_video->pts); + talloc_free(pkt); if (decoded_frame) { filter_video(mpctx, decoded_frame); } @@ -2599,12 +2571,13 @@ static double update_video(struct MPContext *mpctx, double endpts) pts = MP_NOPTS_VALUE; struct demux_packet *pkt; while (1) { - pkt = ds_get_packet2(mpctx->sh_video->ds, false); + pkt = demux_read_packet(mpctx->sh_video->gsh); if (!pkt || pkt->len) break; /* Packets with size 0 are assumed to not correspond to frames, * but to indicate the absence of a frame in formats like AVI * that must have packets at fixed timecode intervals. */ + talloc_free(pkt); } if (pkt) pts = pkt->pts; @@ -2616,6 +2589,7 @@ static double update_video(struct MPContext *mpctx, double endpts) 1 : check_framedrop(mpctx, sh_video->frametime); struct mp_image *decoded_frame = decode_video(sh_video, pkt, framedrop_type, pts); + talloc_free(pkt); if (decoded_frame) { determine_frame_pts(mpctx); filter_video(mpctx, decoded_frame); @@ -2773,7 +2747,7 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac) // Not all demuxers set d_video->pts during seek, so this value // (which was used by at least vobsub code below) may be completely // wrong (probably 0). - mpctx->sh_video->pts = mpctx->sh_video->ds->pts + mpctx->video_offset; + mpctx->sh_video->pts = mpctx->sh_video->ds->last_pts + mpctx->video_offset; mpctx->video_pts = mpctx->sh_video->pts; } -- cgit v1.2.3 From 8a3615f2d8a902bc5aaf12550eb26f4d3f40c7ae Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:13:22 +0200 Subject: mplayer: don't set bogus video pts after seek reset As the comment n the removed code says, this was once needed for something subtitle related. This code has been cleaned up long ago, so at least the original reason for it is gone. --- core/mplayer.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 0d07b518d8..97bde0bc4d 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2742,13 +2742,10 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac) vf_chain_seek_reset(mpctx->sh_video->vfilter); mpctx->sh_video->num_buffered_pts = 0; mpctx->sh_video->last_pts = MP_NOPTS_VALUE; + mpctx->sh_video->pts = MP_NOPTS_VALUE; + mpctx->video_pts = MP_NOPTS_VALUE; mpctx->delay = 0; mpctx->time_frame = 0; - // Not all demuxers set d_video->pts during seek, so this value - // (which was used by at least vobsub code below) may be completely - // wrong (probably 0). - mpctx->sh_video->pts = mpctx->sh_video->ds->last_pts + mpctx->video_offset; - mpctx->video_pts = mpctx->sh_video->pts; } if (mpctx->sh_audio && reset_ac) { -- cgit v1.2.3 From 995fe05254449e71f3cb93f58e03e119685bdced Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:13:44 +0200 Subject: mplayer: remove "old" audio PTS calculation code Removing this code doesn't change anything. All remaining audio decoders are well-behaved enough to not overwrite sh_audio->pts if they don't know the PTS. And if they don't know the PTS, the d_audio->last_pts field can't contain any usable value either, because both fields contain theame value: the last known valid PTS found in an audio packet. --- core/mplayer.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 97bde0bc4d..87bef0e3c5 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1668,36 +1668,18 @@ static double written_audio_pts(struct MPContext *mpctx) sh_audio_t *sh_audio = mpctx->sh_audio; if (!sh_audio) return MP_NOPTS_VALUE; - demux_stream_t *d_audio = mpctx->sh_audio->ds; // first calculate the end pts of audio that has been output by decoder double a_pts = sh_audio->pts; - if (a_pts != MP_NOPTS_VALUE) - // Good, decoder supports new way of calculating audio pts. - // sh_audio->pts is the timestamp of the latest input packet with - // known pts that the decoder has decoded. sh_audio->pts_bytes is - // the amount of bytes the decoder has written after that timestamp. - a_pts += sh_audio->pts_bytes / (double) sh_audio->o_bps; - else { - // Decoder doesn't support new way of calculating pts (or we're - // being called before it has decoded anything with known timestamp). - // Use the old method of audio pts calculation: take the timestamp - // of last packet with known pts the decoder has read data from, - // and add amount of bytes read after the beginning of that packet - // divided by input bps. This will be inaccurate if the input/output - // ratio is not constant for every audio packet or if it is constant - // but not accurately known in sh_audio->i_bps. - - a_pts = d_audio->last_pts; - if (a_pts == MP_NOPTS_VALUE) - return a_pts; - - // ds_tell_pts returns bytes read after last timestamp from - // demuxing layer - if (sh_audio->i_bps) - a_pts += d_audio->last_pts_bytes / (double)sh_audio->i_bps; - } + if (a_pts == MP_NOPTS_VALUE) + return MP_NOPTS_VALUE; + + // sh_audio->pts is the timestamp of the latest input packet with + // known pts that the decoder has decoded. sh_audio->pts_bytes is + // the amount of bytes the decoder has written after that timestamp. + a_pts += sh_audio->pts_bytes / (double) sh_audio->o_bps; + // Now a_pts hopefully holds the pts for end of audio from decoder. - // Substract data in buffers between decoder and audio out. + // Subtract data in buffers between decoder and audio out. // Decoded but not filtered a_pts -= sh_audio->a_buffer_len / (double)sh_audio->o_bps; -- cgit v1.2.3 From 23e303859aa93572f00b17e3b2bc0a552ad7c348 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:15:09 +0200 Subject: mplayer: fix incorrect audio sync after format changes This is not directly related to the handling of format changes itself, but playing audio normally after the change. This was broken: the output byte rate was not recalculated, so audio-video sync was simply broken. Fix this by calculating the byte rate on the fly, instead of storing it in sh_audio. Format changes are relatively common (switches between stereo and 5.1 in TV recordings), so this fixes a somewhat critical bug. --- core/mplayer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 87bef0e3c5..7b3cf65026 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1668,6 +1668,10 @@ static double written_audio_pts(struct MPContext *mpctx) sh_audio_t *sh_audio = mpctx->sh_audio; if (!sh_audio) return MP_NOPTS_VALUE; + + double bps = sh_audio->channels.num * sh_audio->samplerate * + sh_audio->samplesize; + // first calculate the end pts of audio that has been output by decoder double a_pts = sh_audio->pts; if (a_pts == MP_NOPTS_VALUE) @@ -1676,13 +1680,13 @@ static double written_audio_pts(struct MPContext *mpctx) // sh_audio->pts is the timestamp of the latest input packet with // known pts that the decoder has decoded. sh_audio->pts_bytes is // the amount of bytes the decoder has written after that timestamp. - a_pts += sh_audio->pts_bytes / (double) sh_audio->o_bps; + a_pts += sh_audio->pts_bytes / bps; // Now a_pts hopefully holds the pts for end of audio from decoder. // Subtract data in buffers between decoder and audio out. // Decoded but not filtered - a_pts -= sh_audio->a_buffer_len / (double)sh_audio->o_bps; + a_pts -= sh_audio->a_buffer_len / bps; // Data buffered in audio filters, measured in bytes of "missing" output double buffered_output = af_calc_delay(sh_audio->afilter); -- cgit v1.2.3 From 29cc249173687b72bebe75b0244f17ed33265f06 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:16:25 +0200 Subject: mplayer: invert negated boolean variable Boolean variables shouldn't carry a negated meaning, so rename non_interleaved to interleaved. --- core/mplayer.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 7b3cf65026..00d9ad91ac 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1711,21 +1711,21 @@ double playing_audio_pts(struct MPContext *mpctx) return pts - mpctx->opts.playback_speed *ao_get_delay(mpctx->ao); } -// When reading subtitles from a demuxer, and we don't read video or audio -// from the demuxer, we must explicitly read subtitle packets. (Normally, -// subs are interleaved with video and audio, so we get them automatically.) -static bool is_non_interleaved(struct MPContext *mpctx, struct track *track) +// When reading subtitles from a demuxer, and we read video or audio from the +// demuxer, we should not explicitly read subtitle packets. (With external +// subs, we have to.) +static bool is_interleaved(struct MPContext *mpctx, struct track *track) { if (track->is_external || !track->demuxer) - return true; + return false; struct demuxer *demuxer = track->demuxer; for (int type = 0; type < STREAM_TYPE_COUNT; type++) { struct track *other = mpctx->current_track[type]; if (other && other != track && other->demuxer && other->demuxer == demuxer) - return false; + return true; } - return true; + return false; } static void reset_subtitles(struct MPContext *mpctx) @@ -1753,10 +1753,10 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) double curpts_s = refpts_s + opts->sub_delay; if (!track->preloaded) { - bool non_interleaved = is_non_interleaved(mpctx, track); + bool interleaved = is_interleaved(mpctx, track); while (1) { - if (!non_interleaved && !demux_has_packet(sh_sub->gsh)) + if (interleaved && !demux_has_packet(sh_sub->gsh)) break; double subpts_s = demux_get_next_pts(sh_sub->gsh); if (!demux_has_packet(sh_sub->gsh)) @@ -1769,7 +1769,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) if (!sub_accept_packets_in_advance(dec_sub)) break; // Try to avoid demuxing whole file at once - if (non_interleaved && subpts_s > curpts_s + 1) + if (subpts_s > curpts_s + 1 && !interleaved) break; } struct demux_packet *pkt = demux_read_packet(sh_sub->gsh); -- cgit v1.2.3 From 6ede485e4b2ea1093e84d8589a1c321fe8a8462a Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:17:51 +0200 Subject: core: don't access demux_stream outside of demux.c, make it private Generally remove all accesses to demux_stream from all the code, except inside of demux.c. Make it completely private to demux.c. This simplifies the code because it removes an extra concept. In demux.c it is reduced to a simple packet queue. There were other uses of demux_stream, but they were removed or are removed with this commit. Remove the extra "ds" argument to demux fill_buffer callback. It was used by demux_avi and the TV pseudo-demuxer only. Remove usage of d_video->last_pts from the no-correct-pts code. This field contains the last PTS retrieved after a packet that is not NOPTS. We can easily get this value manually because we read the packets ourselves. Reuse sh_video->last_pts to store the packet PTS values. It was used only by the correct-pts code before, and like d_video->last_pts, it is reset on seek. The behavior should be exactly the same. --- core/command.c | 10 ++++------ core/mplayer.c | 32 +++++++++++++++++--------------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'core') diff --git a/core/command.c b/core/command.c index 5a68a228bc..cba9ef5a9a 100644 --- a/core/command.c +++ b/core/command.c @@ -566,13 +566,11 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg, case M_PROPERTY_SET: angle = demuxer_set_angle(demuxer, *(int *)arg); if (angle >= 0) { - struct sh_stream *sh_video = demuxer->video->gsh; - if (sh_video) - resync_video_stream(sh_video->video); + if (mpctx->sh_video) + resync_video_stream(mpctx->sh_video); - struct sh_stream *sh_audio = demuxer->audio->gsh; - if (sh_audio) - resync_audio_stream(sh_audio->audio); + if (mpctx->sh_audio) + resync_audio_stream(mpctx->sh_audio); } return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: { diff --git a/core/mplayer.c b/core/mplayer.c index 00d9ad91ac..f5dbfb4e41 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -360,10 +360,9 @@ static double get_main_demux_pts(struct MPContext *mpctx) { double main_new_pos = MP_NOPTS_VALUE; if (mpctx->demuxer) { - for (int type = 0; type < STREAM_TYPE_COUNT; type++) { - struct demux_stream *ds = mpctx->demuxer->ds[type]; - if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) - main_new_pos = demux_get_next_pts(ds->gsh); + for (int n = 0; n < mpctx->demuxer->num_streams; n++) { + if (main_new_pos == MP_NOPTS_VALUE) + main_new_pos = demux_get_next_pts(mpctx->demuxer->streams[n]); } } return main_new_pos; @@ -1789,7 +1788,9 @@ static int check_framedrop(struct MPContext *mpctx, double frame_time) { struct MPOpts *opts = &mpctx->opts; // check for frame-drop: - if (mpctx->sh_audio && !mpctx->ao->untimed && !mpctx->sh_audio->ds->eof) { + if (mpctx->sh_audio && !mpctx->ao->untimed && + !demux_stream_eof(mpctx->sh_audio->gsh)) + { float delay = opts->playback_speed * ao_get_delay(mpctx->ao); float d = delay - mpctx->delay; // we should avoid dropping too many frames in sequence unless we @@ -2205,7 +2206,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) return -1; } else if (res == ASYNC_PLAY_DONE) return 0; - else if (mpctx->sh_audio->ds->eof) + else if (demux_stream_eof(mpctx->sh_audio->gsh)) audio_eof = true; } @@ -2338,7 +2339,7 @@ int reinit_video_chain(struct MPContext *mpctx) vo_update_window_title(mpctx); - if (stream_control(mpctx->sh_video->ds->demuxer->stream, + if (stream_control(mpctx->sh_video->gsh->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) mpctx->sh_video->stream_aspect = ar; @@ -2438,21 +2439,23 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame) static struct demux_packet *video_read_frame(struct MPContext *mpctx) { sh_video_t *sh_video = mpctx->sh_video; - demux_stream_t *d_video = sh_video->ds; - demuxer_t *demuxer = d_video->demuxer; - float pts1 = d_video->last_pts; + demuxer_t *demuxer = sh_video->gsh->demuxer; + float pts1 = sh_video->last_pts; struct demux_packet *pkt = demux_read_packet(sh_video->gsh); if (!pkt) return NULL; // EOF + if (pkt->pts != MP_NOPTS_VALUE) + sh_video->last_pts = pkt->pts; + float frame_time = sh_video->frametime; // override frame_time for variable/unknown FPS formats: if (!mpctx->opts.force_fps) { double next_pts = demux_get_next_pts(sh_video->gsh); - double d = next_pts == MP_NOPTS_VALUE ? d_video->last_pts - pts1 - : next_pts - d_video->last_pts; + double d = next_pts == MP_NOPTS_VALUE ? sh_video->last_pts - pts1 + : next_pts - sh_video->last_pts; if (d >= 0) { if (demuxer->file_format == DEMUXER_TYPE_TV) { if (d > 0) { @@ -2467,8 +2470,7 @@ static struct demux_packet *video_read_frame(struct MPContext *mpctx) } } - sh_video->pts = d_video->last_pts; - + sh_video->pts = sh_video->last_pts; sh_video->next_frame_time = frame_time; return pkt; } @@ -2515,7 +2517,7 @@ static void determine_frame_pts(struct MPContext *mpctx) if (opts->user_pts_assoc_mode) sh_video->pts_assoc_mode = opts->user_pts_assoc_mode; else if (sh_video->pts_assoc_mode == 0) { - if (mpctx->sh_video->ds->demuxer->timestamp_type == TIMESTAMP_TYPE_PTS + if (mpctx->sh_video->gsh->demuxer->timestamp_type == TIMESTAMP_TYPE_PTS && sh_video->codec_reordered_pts != MP_NOPTS_VALUE) sh_video->pts_assoc_mode = 1; else -- cgit v1.2.3 From a6706c41d8d89bc1a72dd21e215885e79a766db2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:21:45 +0200 Subject: video: eliminate frametime variable --- core/mplayer.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index f5dbfb4e41..275795defb 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1793,6 +1793,8 @@ static int check_framedrop(struct MPContext *mpctx, double frame_time) { float delay = opts->playback_speed * ao_get_delay(mpctx->ao); float d = delay - mpctx->delay; + if (frame_time < 0) + frame_time = mpctx->sh_video->fps > 0 ? 1.0 / mpctx->sh_video->fps : 0; // we should avoid dropping too many frames in sequence unless we // are too late. and we allow 100ms A-V delay here: if (d < -mpctx->dropped_frames * frame_time - 0.100 && !mpctx->paused @@ -2305,14 +2307,12 @@ int reinit_video_chain(struct MPContext *mpctx) } mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] filefmt:%d fourcc:0x%X " - "size:%dx%d fps:%5.3f ftime:=%6.4f\n", + "size:%dx%d fps:%5.3f\n", mpctx->master_demuxer->file_format, mpctx->sh_video->format, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, - mpctx->sh_video->fps, mpctx->sh_video->frametime); - if (opts->force_fps) { + mpctx->sh_video->fps); + if (opts->force_fps) mpctx->sh_video->fps = opts->force_fps; - mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps; - } update_fps(mpctx); if (!mpctx->sh_video->fps && !opts->force_fps && !opts->correct_pts) { @@ -2449,7 +2449,7 @@ static struct demux_packet *video_read_frame(struct MPContext *mpctx) if (pkt->pts != MP_NOPTS_VALUE) sh_video->last_pts = pkt->pts; - float frame_time = sh_video->frametime; + float frame_time = sh_video->fps > 0 ? 1.0f / sh_video->fps : 0; // override frame_time for variable/unknown FPS formats: if (!mpctx->opts.force_fps) { @@ -2458,10 +2458,8 @@ static struct demux_packet *video_read_frame(struct MPContext *mpctx) : next_pts - sh_video->last_pts; if (d >= 0) { if (demuxer->file_format == DEMUXER_TYPE_TV) { - if (d > 0) { - sh_video->frametime = d; + if (d > 0) sh_video->fps = 1.0f / d; - } frame_time = d; } else { if ((int)sh_video->fps <= 1) @@ -2574,7 +2572,7 @@ static double update_video(struct MPContext *mpctx, double endpts) if (pts >= mpctx->hrseek_pts - .005) mpctx->hrseek_framedrop = false; int framedrop_type = mpctx->hrseek_active && mpctx->hrseek_framedrop ? - 1 : check_framedrop(mpctx, sh_video->frametime); + 1 : check_framedrop(mpctx, -1); struct mp_image *decoded_frame = decode_video(sh_video, pkt, framedrop_type, pts); talloc_free(pkt); @@ -4281,10 +4279,8 @@ goto_reopen_demuxer: ; if (opts->force_fps && mpctx->sh_video) { mpctx->sh_video->fps = opts->force_fps; - mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps; mp_tmsg(MSGT_CPLAYER, MSGL_INFO, - "FPS forced to be %5.3f (ftime: %5.3f).\n", - mpctx->sh_video->fps, mpctx->sh_video->frametime); + "FPS forced to be %5.3f.\n", mpctx->sh_video->fps); } //==================== START PLAYING ======================= -- cgit v1.2.3 From e5544e2da38522674edb1eb5d4cfdf179c4328db Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:22:24 +0200 Subject: demux: improve DVD sub auto-selection hack The code touched by this commit makes sure that DVD subtitle tracks known by libdvdread but not known by demux_lavf can be selected and displayed properly. These subtitle tracks have the first packet some time late in the packet stream, so that libavformat won't immediately recognize them, and will add the track as soon as the first packet is seen during normal demuxing. demux_mpg used to handle this elegantly: you just set the MPEG ID of the stream you wanted. demux_lavf couldn't do this, so it was emulated with a DEMUXER_CTRL. This commit changes it so that new streams are selected by default (if autoselect is enabled), and the playloop simply can take appropriate action before the lower layer throws away the first packet. This also changes the demux_lavf behavior that subtitle packets are always demuxed, even if not needed. (They were immediately thrown away, so there was no advantage to this.) Further, this adds the ability to demux.c to deal with demuxing more than one stream of a kind at once. (Though currently it's not useful.) --- core/mplayer.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'core') diff --git a/core/mplayer.c b/core/mplayer.c index 275795defb..2cc4659eef 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -913,12 +913,6 @@ static int map_id_from_demuxer(struct demuxer *d, enum stream_type type, int id) id = id & 0x1F; return id; } -static int map_id_to_demuxer(struct demuxer *d, enum stream_type type, int id) -{ - if (d->stream->uncached_type == STREAMTYPE_DVD && type == STREAM_SUB) - id = id | 0x20; - return id; -} static struct track *add_stream_track(struct MPContext *mpctx, struct sh_stream *stream, @@ -937,7 +931,9 @@ static struct track *add_stream_track(struct MPContext *mpctx, track->stream = stream; track->demuxer_id = stream->demuxer_id; // Initialize lazily selected track - if (track == mpctx->current_track[STREAM_SUB]) + bool selected = track == mpctx->current_track[STREAM_SUB]; + demuxer_select_track(track->demuxer, stream, selected); + if (selected) reinit_subs(mpctx); return track; } @@ -973,6 +969,8 @@ static struct track *add_stream_track(struct MPContext *mpctx, track->lang = talloc_strdup(track, req.name); } + demuxer_select_track(track->demuxer, stream, false); + return track; } @@ -1004,6 +1002,7 @@ static void add_dvd_tracks(struct MPContext *mpctx) track->lang = talloc_strdup(track, req.name); } } + demuxer_enable_autoselect(demuxer); #endif } @@ -1885,18 +1884,9 @@ static void reinit_subs(struct MPContext *mpctx) mpctx->sh_sub->dec_sub = sub_create(opts); assert(track->demuxer); - if (!track->stream) { - // Lazily added DVD track - we must not miss the first subtitle packet, - // which makes the demuxer create the sh_stream, and contains the first - // subtitle event. - - // demux_lavf - IDs are essentially random, have to use MPEG IDs - int id = map_id_to_demuxer(track->demuxer, track->type, - track->demuxer_id); - demux_control(track->demuxer, DEMUXER_CTRL_AUTOSELECT_SUBTITLE, &id); - + // Lazily added DVD track - will be created on first sub packet + if (!track->stream) return; - } mpctx->initialized_flags |= INITIALIZED_SUB; -- cgit v1.2.3 From 4cda1d113e0d9d34d7c39cf3d8861c7079f965d8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:23:56 +0200 Subject: core: completely change handling of attached picture pseudo video Before this commit, we tried to play along with libavformat and tried to pretend that attached pictures are video streams with a single frame, and that the frame magically appeared at the seek position when seeking. The playback core would then switch to a mode where the video has ended, and the "remaining" audio is played. This didn't work very well: - we needed a hack in demux.c, because we tried to read more packets in order to find the "next" video frame (libavformat doesn't tell us if a stream has ended) - switching the video stream didn't work, because we can't tell libavformat to send the packet again - seeking and resuming after was hacky (for some reason libavformat sets the returned packet's PTS to that of the previously returned audio packet in generic code not related to attached pictures, and this happened to work) - if the user did something stupid and e.g. inserted a deinterlacer by default, a picture was never displayed, only an inactive VO window) - same when using a command that reconfigured the VO (like switching aspect or video filters) - hr-seek didn't work For this reason, handle attached pictures as separate case with a separate video decoding function, which doesn't read packets. Also, do not synchronize audio to video start in this case. --- core/mp_core.h | 3 +++ core/mplayer.c | 65 +++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 16 deletions(-) (limited to 'core') diff --git a/core/mp_core.h b/core/mp_core.h index b9c835e497..6bd51cb85c 100644 --- a/core/mp_core.h +++ b/core/mp_core.h @@ -172,6 +172,9 @@ typedef struct MPContext { /* We're starting playback from scratch or after a seek. Show first * video frame immediately and reinitialize sync. */ bool restart_playback; + /* Set if audio should be timed to start with video frame after seeking, + * not set when e.g. playing cover art */ + bool sync_audio_to_video; /* After playback restart (above) or audio stream change, adjust audio * stream by cutting samples or adding silence at the beginning to make * audio playback position match video position. */ diff --git a/core/mplayer.c b/core/mplayer.c index 2cc4659eef..026af6a989 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -467,6 +467,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) if (mpctx->sh_video) uninit_video(mpctx->sh_video); cleanup_demux_stream(mpctx, STREAM_VIDEO); + mpctx->sync_audio_to_video = false; } if (mask & INITIALIZED_DEMUXER) { @@ -946,7 +947,7 @@ static struct track *add_stream_track(struct MPContext *mpctx, .demuxer_id = stream->demuxer_id, .title = stream->title, .default_track = stream->default_track, - .attached_picture = stream->attached_picture, + .attached_picture = stream->attached_picture != NULL, .lang = stream->lang, .under_timeline = under_timeline, .demuxer = stream->demuxer, @@ -1134,7 +1135,7 @@ static void print_status(struct MPContext *mpctx) saddf(&line, " x%4.2f", opts->playback_speed); // A-V sync - if (mpctx->sh_audio && sh_video) { + if (mpctx->sh_audio && sh_video && mpctx->sync_audio_to_video) { if (mpctx->last_av_difference != MP_NOPTS_VALUE) saddf(&line, " A-V:%7.3f", mpctx->last_av_difference); else @@ -2173,7 +2174,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) playsize = ao_get_space(ao); // Coming here with hrseek_active still set means audio-only - if (!mpctx->sh_video) + if (!mpctx->sh_video || !mpctx->sync_audio_to_video) mpctx->syncing_audio = false; if (!opts->initial_audio_sync || !modifiable_audio_format) { mpctx->syncing_audio = false; @@ -2353,6 +2354,7 @@ int reinit_video_chain(struct MPContext *mpctx) sh_video->num_buffered_pts = 0; sh_video->next_frame_time = 0; mpctx->restart_playback = true; + mpctx->sync_audio_to_video = !sh_video->gsh->attached_picture; mpctx->delay = 0; mpctx->vo_pts_history_seek_ts++; @@ -2365,6 +2367,7 @@ err_out: cleanup_demux_stream(mpctx, STREAM_VIDEO); no_video: mpctx->current_track[STREAM_VIDEO] = NULL; + mpctx->sync_audio_to_video = false; mp_tmsg(MSGT_CPLAYER, MSGL_INFO, "Video: no video\n"); return 0; } @@ -2416,6 +2419,15 @@ static bool filter_output_queued_frame(struct MPContext *mpctx) return !!img; } +static bool load_next_vo_frame(struct MPContext *mpctx, bool eof) +{ + if (vo_get_buffered_frame(mpctx->video_out, eof) >= 0) + return true; +