diff options
author | Rudolf Polzer <divverent@xonotic.org> | 2012-09-25 11:53:29 +0200 |
---|---|---|
committer | Rudolf Polzer <divverent@alientrap.org> | 2012-09-29 15:02:36 +0200 |
commit | a89a6f40c7ada04db2f85869d8d50166e0e7f905 (patch) | |
tree | 2527a1e0fff447b9d5c09bd94ba8075cee598a10 /libvo | |
parent | c22482e08d4ca0514685e73b68479f0427b1f28f (diff) | |
download | mpv-a89a6f40c7ada04db2f85869d8d50166e0e7f905.tar.bz2 mpv-a89a6f40c7ada04db2f85869d8d50166e0e7f905.tar.xz |
encode: fix -ocopyts with certain DVD images
When timestamps jump by more than 30 seconds, assume an unexpected
discontinuity. Fixes encoding aborts (i.e. no more frames written) at
DVD cell switches.
Diffstat (limited to 'libvo')
-rw-r--r-- | libvo/vo_lavc.c | 106 |
1 files changed, 50 insertions, 56 deletions
diff --git a/libvo/vo_lavc.c b/libvo/vo_lavc.c index 4a1af15eb0..5b467f1f6a 100644 --- a/libvo/vo_lavc.c +++ b/libvo/vo_lavc.c @@ -47,6 +47,7 @@ struct priv { double lastpts; int64_t lastipts; int64_t lastframeipts; + double expected_next_pts; mp_image_t *lastimg; int lastdisplaycount; @@ -347,6 +348,11 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts) mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: NOTE: skipped initial video frame (probably because audio is not there yet)\n"); return; } + if (pts == MP_NOPTS_VALUE) { + if (mpi) + mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: frame without pts, please report; synthesizing pts instead\n"); + pts = vc->expected_next_pts; + } avc = vc->stream->codec; @@ -390,65 +396,53 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts) double timeunit = (double)vc->worst_time_base.num / vc->worst_time_base.den; - // fix the discontinuity pts offset - if (ectx->discontinuity_pts_offset == MP_NOPTS_VALUE) { + double outpts; + if (ectx->options->rawts) + outpts = pts; + else if (ectx->options->copyts) { + // fix the discontinuity pts offset nextpts = pts; - ectx->discontinuity_pts_offset = ectx->next_in_pts - nextpts; - } - - // set next allowed output pts value - nextpts = pts + ectx->discontinuity_pts_offset + timeunit; - if (nextpts > ectx->next_in_pts) - ectx->next_in_pts = nextpts; - - // vc->lastipts is MP_NOPTS_VALUE, or the start time of vc->lastframe - if (mpi) { - if (pts == MP_NOPTS_VALUE) { - // NOTE: this even applies to ectx->options->copyts! - if (vc->lastipts == MP_NOPTS_VALUE) - frameipts = 0; - else - frameipts = vc->lastipts + 1; - - mp_msg(MSGT_ENCODE, MSGL_INFO, "vo-lavc: pts was missing, using %d - " - "consider using -ofps or -vf fixpts\n", (int) frameipts); - - if (ectx->last_video_in_pts != MP_NOPTS_VALUE) - ectx->last_video_in_pts += timeunit; + if (ectx->discontinuity_pts_offset == MP_NOPTS_VALUE) { + ectx->discontinuity_pts_offset = ectx->next_in_pts - nextpts; + } + else if (fabs(nextpts + ectx->discontinuity_pts_offset - ectx->next_in_pts) > 30) { + mp_msg(MSGT_ENCODE, MSGL_WARN, + "vo-lavc: detected an unexpected discontinuity (pts jumped by " + "%f seconds)\n", + nextpts + ectx->discontinuity_pts_offset - ectx->next_in_pts); + ectx->discontinuity_pts_offset = ectx->next_in_pts - nextpts; + } - // calculate backwards to set vc->lastpts matchingly - vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream); - } else { - double outpts; - if (ectx->options->rawts) - outpts = pts; - else if (ectx->options->copyts) - outpts = pts + ectx->discontinuity_pts_offset; - else { - double duration = 0; - if (ectx->last_video_in_pts != MP_NOPTS_VALUE) - duration = pts - ectx->last_video_in_pts; - if (duration < 0) - duration = timeunit; // XXX warn about discontinuity? - outpts = vc->lastpts + duration; - if (ectx->audio_pts_offset != MP_NOPTS_VALUE) { - double adj = outpts - pts - ectx->audio_pts_offset; - adj = FFMIN(adj, duration * 0.1); - adj = FFMAX(adj, -duration * 0.1); - outpts -= adj; - } - } - vc->lastpts = outpts; - ectx->last_video_in_pts = pts; - frameipts = floor((outpts + encode_lavc_getoffset(ectx, vc->stream)) - / timeunit + 0.5); + outpts = pts + ectx->discontinuity_pts_offset; + } + else { + // adjust pts by knowledge of audio pts vs audio playback time + double duration = 0; + if (ectx->last_video_in_pts != MP_NOPTS_VALUE) + duration = pts - ectx->last_video_in_pts; + if (duration < 0) + duration = timeunit; // XXX warn about discontinuity? + outpts = vc->lastpts + duration; + if (ectx->audio_pts_offset != MP_NOPTS_VALUE) { + double adj = outpts - pts - ectx->audio_pts_offset; + adj = FFMIN(adj, duration * 0.1); + adj = FFMAX(adj, -duration * 0.1); + outpts -= adj; } - } else { - if (vc->lastipts == MP_NOPTS_VALUE) - frameipts = 0; - else - frameipts = vc->lastipts + 1; - vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream); + } + vc->lastpts = outpts; + ectx->last_video_in_pts = pts; + frameipts = floor((outpts + encode_lavc_getoffset(ectx, vc->stream)) + / timeunit + 0.5); + + // calculate expected pts of next video frame + vc->expected_next_pts = pts + timeunit; + + if (!ectx->options->rawts && ectx->options->copyts) { + // set next allowed output pts value + nextpts = vc->expected_next_pts + ectx->discontinuity_pts_offset; + if (nextpts > ectx->next_in_pts) + ectx->next_in_pts = nextpts; } // never-drop mode |