summaryrefslogtreecommitdiffstats
path: root/video/out/vo_lavc.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/vo_lavc.c')
-rw-r--r--video/out/vo_lavc.c70
1 files changed, 46 insertions, 24 deletions
diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c
index 5140720f92..ca3f1c5a5f 100644
--- a/video/out/vo_lavc.c
+++ b/video/out/vo_lavc.c
@@ -48,6 +48,8 @@ struct priv {
double lastpts;
int64_t lastipts;
int64_t lastframeipts;
+ int64_t lastencodedipts;
+ int64_t mindeltapts;
double expected_next_pts;
mp_image_t *lastimg;
int lastimg_wants_osd;
@@ -64,7 +66,7 @@ static int preinit(struct vo *vo, const char *arg)
struct priv *vc;
if (!encode_lavc_available(vo->encode_lavc_ctx)) {
mp_msg(MSGT_ENCODE, MSGL_ERR,
- "vo-lavc: the option -o (output file) must be specified\n");
+ "vo-lavc: the option --o (output file) must be specified\n");
return -1;
}
vo->priv = talloc_zero(vo, struct priv);
@@ -136,6 +138,7 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
vc->lastipts = MP_NOPTS_VALUE;
vc->lastframeipts = MP_NOPTS_VALUE;
+ vc->lastencodedipts = MP_NOPTS_VALUE;
if (pix_fmt == PIX_FMT_NONE)
goto error; /* imgfmt2pixfmt already prints something */
@@ -207,7 +210,7 @@ static void write_packet(struct vo *vo, int size, AVPacket *packet)
vc->stream->codec->time_base,
vc->stream->time_base);
} else {
- mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: codec did not provide pts\n");
+ mp_msg(MSGT_ENCODE, MSGL_V, "vo-lavc: codec did not provide pts\n");
packet->pts = av_rescale_q(vc->lastipts, vc->worst_time_base,
vc->stream->time_base);
}
@@ -317,6 +320,11 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
vc->worst_time_base = vc->stream->time_base;
vc->worst_time_base_is_stream = 1;
}
+ if (ectx->options->maxfps)
+ vc->mindeltapts = ceil(vc->worst_time_base.den /
+ (vc->worst_time_base.num * ectx->options->maxfps));
+ else
+ vc->mindeltapts = 0;
// NOTE: we use the following "axiom" of av_rescale_q:
// if time base A is worse than time base B, then
@@ -387,11 +395,15 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
}
// never-drop mode
- if (ectx->options->neverdrop && frameipts <= vc->lastipts) {
- mp_msg(MSGT_ENCODE, MSGL_INFO, "vo-lavc: -oneverdrop increased pts by %d\n",
- (int) (vc->lastipts - frameipts + 1));
- frameipts = vc->lastipts + 1;
- vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream);
+ if (ectx->options->neverdrop) {
+ int64_t step = vc->mindeltapts ? vc->mindeltapts : 1;
+ if (frameipts < vc->lastipts + step) {
+ mp_msg(MSGT_ENCODE, MSGL_INFO,
+ "vo-lavc: --oneverdrop increased pts by %d\n",
+ (int) (vc->lastipts - frameipts + step));
+ frameipts = vc->lastipts + step;
+ vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream);
+ }
}
if (vc->lastipts != MP_NOPTS_VALUE) {
@@ -402,26 +414,36 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
int64_t thisduration = vc->harddup ? 1 : (frameipts - vc->lastipts);
AVPacket packet;
- avcodec_get_frame_defaults(frame);
-
- // this is a nop, unless the worst time base is the STREAM time base
- frame->pts = av_rescale_q(vc->lastipts, vc->worst_time_base,
- avc->time_base);
-
- for (i = 0; i < 4; i++) {
- frame->data[i] = vc->lastimg->planes[i];
- frame->linesize[i] = vc->lastimg->stride[i];
+ // we will ONLY encode this frame if it can be encoded at at least
+ // vc->mindeltapts after the last encoded frame!
+ int64_t skipframes =
+ vc->lastencodedipts + vc->mindeltapts - vc->lastipts;
+ if (skipframes < 0)
+ skipframes = 0;
+
+ if (thisduration > skipframes) {
+ avcodec_get_frame_defaults(frame);
+
+ // this is a nop, unless the worst time base is the STREAM time base
+ frame->pts = av_rescale_q(vc->lastipts + skipframes,
+ vc->worst_time_base, avc->time_base);
+
+ for (i = 0; i < 4; i++) {
+ frame->data[i] = vc->lastimg->planes[i];
+ frame->linesize[i] = vc->lastimg->stride[i];
+ }
+ frame->quality = avc->global_quality;
+
+ av_init_packet(&packet);
+ packet.data = vc->buffer;
+ packet.size = vc->buffer_size;
+ size = encode_video(vo, frame, &packet);
+ write_packet(vo, size, &packet);
+ ++vc->lastdisplaycount;
+ vc->lastencodedipts = vc->lastipts + skipframes;
}
- frame->quality = avc->global_quality;
-
- av_init_packet(&packet);
- packet.data = vc->buffer;
- packet.size = vc->buffer_size;
- size = encode_video(vo, frame, &packet);
- write_packet(vo, size, &packet);
vc->lastipts += thisduration;
- ++vc->lastdisplaycount;
}
avcodec_free_frame(&frame);