diff options
Diffstat (limited to 'libmpcodecs')
-rw-r--r-- | libmpcodecs/dec_video.c | 29 | ||||
-rw-r--r-- | libmpcodecs/vd.h | 2 | ||||
-rw-r--r-- | libmpcodecs/vd_ffmpeg.c | 30 |
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 +}; |