summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authorRudolf Polzer <divverent@xonotic.org>2012-09-25 11:53:29 +0200
committerRudolf Polzer <divverent@alientrap.org>2012-09-29 15:02:36 +0200
commita89a6f40c7ada04db2f85869d8d50166e0e7f905 (patch)
tree2527a1e0fff447b9d5c09bd94ba8075cee598a10 /libvo
parentc22482e08d4ca0514685e73b68479f0427b1f28f (diff)
downloadmpv-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.c106
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