summaryrefslogtreecommitdiffstats
path: root/libmpcodecs
diff options
context:
space:
mode:
Diffstat (limited to 'libmpcodecs')
-rw-r--r--libmpcodecs/dec_video.c29
-rw-r--r--libmpcodecs/vd.h2
-rw-r--r--libmpcodecs/vd_ffmpeg.c30
3 files changed, 54 insertions, 7 deletions
diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c
index 0a258fabcb..e010715c4a 100644
--- a/libmpcodecs/dec_video.c
+++ b/libmpcodecs/dec_video.c
@@ -149,6 +149,8 @@ void resync_video_stream(sh_video_t *sh_video)
const struct vd_functions *vd = sh_video->vd_driver;
if (vd)
vd->control(sh_video, VDCTRL_RESYNC_STREAM, NULL);
+ sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
+ sh_video->prev_sorted_pts = MP_NOPTS_VALUE;
}
int get_current_video_decoder_lag(sh_video_t *sh_video)
@@ -307,6 +309,8 @@ static int init_video(sh_video_t *sh_video, char *codecname, char *vfm,
}
// Yeah! We got it!
sh_video->initialized = 1;
+ sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
+ sh_video->prev_sorted_pts = MP_NOPTS_VALUE;
return 1;
}
return 0;
@@ -411,7 +415,14 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
}
}
- mpi = sh_video->vd_driver->decode(sh_video, start, in_size, drop_frame);
+ if (sh_video->vd_driver->decode2) {
+ mpi = sh_video->vd_driver->decode2(sh_video, start, in_size,
+ drop_frame, &pts);
+ } else {
+ mpi = sh_video->vd_driver->decode(sh_video, start, in_size,
+ drop_frame);
+ pts = MP_NOPTS_VALUE;
+ }
//------------------------ frame decoded. --------------------
@@ -438,16 +449,28 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
else if (field_dominance == 1)
mpi->fields &= ~MP_IMGFIELD_TOP_FIRST;
+ double prevpts = sh_video->codec_reordered_pts;
+ sh_video->prev_codec_reordered_pts = prevpts;
+ sh_video->codec_reordered_pts = pts;
+ if (prevpts != MP_NOPTS_VALUE && pts <= prevpts
+ || pts == MP_NOPTS_VALUE)
+ sh_video->num_reordered_pts_problems++;
+ prevpts = sh_video->sorted_pts;
if (opts->correct_pts) {
if (sh_video->num_buffered_pts) {
sh_video->num_buffered_pts--;
- sh_video->pts = sh_video->buffered_pts[sh_video->num_buffered_pts];
+ sh_video->sorted_pts =
+ sh_video->buffered_pts[sh_video->num_buffered_pts];
} else {
mp_msg(MSGT_CPLAYER, MSGL_ERR,
"No pts value from demuxer to " "use for frame!\n");
- sh_video->pts = MP_NOPTS_VALUE;
+ sh_video->sorted_pts = MP_NOPTS_VALUE;
}
}
+ pts = sh_video->sorted_pts;
+ if (prevpts != MP_NOPTS_VALUE && pts <= prevpts
+ || pts == MP_NOPTS_VALUE)
+ sh_video->num_sorted_pts_problems++;
return mpi;
}
diff --git a/libmpcodecs/vd.h b/libmpcodecs/vd.h
index df71970f7d..30e61c68b3 100644
--- a/libmpcodecs/vd.h
+++ b/libmpcodecs/vd.h
@@ -15,6 +15,8 @@ typedef struct vd_functions
void (*uninit)(sh_video_t *sh);
int (*control)(sh_video_t *sh,int cmd,void* arg, ...);
mp_image_t* (*decode)(sh_video_t *sh,void* data,int len,int flags);
+ struct mp_image *(*decode2)(struct sh_video *sh, void *data, int len,
+ int flags, double *reordered_pts);
} vd_functions_t;
// NULL terminated array of all drivers
diff --git a/libmpcodecs/vd_ffmpeg.c b/libmpcodecs/vd_ffmpeg.c
index 5e22bc6c81..eb53c6e830 100644
--- a/libmpcodecs/vd_ffmpeg.c
+++ b/libmpcodecs/vd_ffmpeg.c
@@ -14,7 +14,10 @@
#include "mpbswap.h"
#include "fmt-conversion.h"
-#include "vd_internal.h"
+#include "vd.h"
+#include "img_format.h"
+#include "libmpdemux/stheader.h"
+#include "codec-cfg.h"
static const vd_info_t info = {
"FFmpeg's libavcodec codec family",
@@ -24,8 +27,6 @@ static const vd_info_t info = {
"native codecs"
};
-LIBVD_EXTERN(ffmpeg)
-
#include "libavcodec/avcodec.h"
#if CONFIG_XVMC
@@ -62,6 +63,7 @@ static void draw_slice(struct AVCodecContext *s, const AVFrame *src,
static enum PixelFormat get_format(struct AVCodecContext *avctx,
const enum PixelFormat *pix_fmt);
+static void uninit(struct sh_video *sh);
const m_option_t lavc_decode_opts_conf[]={
OPT_INTRANGE("bug", lavc_param.workaround_bugs, 0, -1, 999999),
@@ -627,6 +629,13 @@ else
ctx->b_age=1;
}
pic->type= FF_BUFFER_TYPE_USER;
+
+ /* The libavcodec reordered_opaque functionality is implemented by
+ * a similar copy in avcodec_default_get_buffer() and without a
+ * workaround like this it'd stop working when a custom buffer
+ * callback is used.
+ */
+ pic->reordered_opaque = avctx->reordered_opaque;
return 0;
}
@@ -691,7 +700,9 @@ static void swap_palette(void *pal) {
}
// decode a frame
-static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
+static struct mp_image *decode(struct sh_video *sh, void *data, int len,
+ int flags, double *reordered_pts)
+{
int got_picture=0;
int ret;
vd_ffmpeg_ctx *ctx = sh->context;
@@ -726,7 +737,10 @@ static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
pkt.size = len;
// HACK: make PNGs decode normally instead of as CorePNG delta frames
pkt.flags = PKT_FLAG_KEY;
+ // The avcodec opaque field stupidly supports only int64_t type
+ *(double *)&avctx->reordered_opaque = *reordered_pts;
ret = avcodec_decode_video2(avctx, pic, &got_picture, &pkt);
+ *reordered_pts = *(double *)&pic->reordered_opaque;
dr1= ctx->do_dr1;
if(ret<0) mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Error while decoding frame!\n");
@@ -877,3 +891,11 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
return selected_format;
}
#endif /* CONFIG_XVMC || CONFIG_VDPAU */
+
+const struct vd_functions mpcodecs_vd_ffmpeg = {
+ .info = &info,
+ .init = init,
+ .uninit = uninit,
+ .control = control,
+ .decode2 = decode
+};