summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-11-16 04:18:13 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-11-16 04:18:13 +0200
commit507f4fe6c7811558b1367e4b64855ae7f9bc8da8 (patch)
tree416b70358bf4b13871cda60fd8e8f64c5e9a2392
parent8bbb79c03a594e452fb9109dd6fda781d390a798 (diff)
parentb8861ce8e28080b151467827f65bdc3707a74511 (diff)
downloadmpv-507f4fe6c7811558b1367e4b64855ae7f9bc8da8.tar.bz2
mpv-507f4fe6c7811558b1367e4b64855ae7f9bc8da8.tar.xz
Merge branch 'vdpau'
-rw-r--r--DOCS/man/en/mplayer.137
-rw-r--r--TOOLS/vdpau_functions.py3
-rw-r--r--codec-cfg.c1
-rw-r--r--command.c45
-rw-r--r--etc/codecs.conf31
-rw-r--r--fmt-conversion.c1
-rw-r--r--input/input.c1
-rw-r--r--libmenu/vf_menu.c2
-rw-r--r--libmpcodecs/img_format.c1
-rw-r--r--libmpcodecs/img_format.h1
-rw-r--r--libmpcodecs/vf.h3
-rw-r--r--libmpcodecs/vf_tfields.c6
-rw-r--r--libmpcodecs/vf_vo.c10
-rw-r--r--libmpcodecs/vf_yadif.c2
-rw-r--r--libvo/vdpau_template.c3
-rw-r--r--libvo/video_out.c9
-rw-r--r--libvo/video_out.h9
-rw-r--r--libvo/vo_vdpau.c492
-rw-r--r--libvo/vo_xv.c11
-rw-r--r--libvo/x11_common.c18
-rw-r--r--libvo/x11_common.h1
-rw-r--r--mencoder.c2
-rw-r--r--mplayer.c30
23 files changed, 585 insertions, 134 deletions
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1
index 29cbff4a4f..50757d6bbe 100644
--- a/DOCS/man/en/mplayer.1
+++ b/DOCS/man/en/mplayer.1
@@ -282,8 +282,10 @@ Show filename on the OSD.
Seek to the beginning of the previous/next chapter.
.IPs "D (\-vo xvmc, \-vo vdpau, \-vf yadif, \-vf kerndeint only)"
Activate/deactivate deinterlacer.
-.IPs "A"
+.IPs "A\ \ \ \ "
Cycle through the available DVD angles.
+.IPs "c (currently -vo vdpau and -vo xv only)"
+Change YUV colorspace.
.RE
.PD 1
.PP
@@ -3408,7 +3410,8 @@ Select the driver to use as source to overlay on top of X11.
.PD 1
.
.TP
-.B vdpau (with \-vc ffmpeg12vdpau, ffwmv3vdpau, ffvc1vdpau or ffh264vdpau)
+.B vdpau (with \-vc ffmpeg12vdpau, ffwmv3vdpau, ffvc1vdpau or ffh264vdpau or
+ffodivxvdpau)
Video output that uses VDPAU to decode video via hardware.
Also supports displaying of software-decoded video.
.PD 0
@@ -3442,6 +3445,36 @@ Use nochroma\-deint to solely use luma and speed up advanced deinterlacing.
Useful with slow video memory.
.IPs pullup
Try to apply inverse telecine, needs motion adaptive temporal deinterlacing.
+.IPs colorspace
+Select the color space for YUV to RGB conversion (default: 1, BT.601).
+In general BT.601 should be used for standard definition (SD) content and
+BT.709 for high definition (HD) content.
+Using incorrect color space results in slightly under or over saturated and
+shifted colors.
+.RSss
+.IPs 0
+Guess the color space based on video resolution.
+Video with width >= 1280 or height > 576 is assumed to be HD and BT.709 color
+space will be used.
+.IPs 1
+Use ITU-R BT.601 color space (default).
+.IPs 2
+Use ITU-R BT.709 color space.
+.IPs 3
+Use SMPTE-240M color space.
+.RE
+IPs hqscaling
+.RSss
+.IPs 0
+Use default VDPAU scaling (default).
+.IPs 1\-9
+Apply high quality VDPAU scaling (needs capable hardware).
+.RE
+.IPs fps=<number>
+Override autodetected display refresh rate value (the value is needed for framedrop to allow video playback rates higher than display refresh rate, and for vsync-aware frame timing adjustments).
+Default 0 means use autodetected value.
+A positive value is interpreted as a refresh rate in Hz and overrides the autodetected value.
+A negative value disables all timing adjustment and framedrop logic.
.RE
.PD 1
.
diff --git a/TOOLS/vdpau_functions.py b/TOOLS/vdpau_functions.py
index e628cb00c3..098e30a251 100644
--- a/TOOLS/vdpau_functions.py
+++ b/TOOLS/vdpau_functions.py
@@ -25,10 +25,13 @@ presentation_queue_block_until_surface_idle
presentation_queue_create
presentation_queue_destroy
presentation_queue_display
+presentation_queue_get_time
+presentation_queue_query_surface_status
presentation_queue_target_create_x11
presentation_queue_target_destroy
video_mixer_create
video_mixer_destroy
+video_mixer_query_feature_support
video_mixer_render
video_mixer_set_attribute_values
video_mixer_set_feature_enables
diff --git a/codec-cfg.c b/codec-cfg.c
index 6e90c06fa8..27e07c92ac 100644
--- a/codec-cfg.c
+++ b/codec-cfg.c
@@ -195,6 +195,7 @@ static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int
{"VDPAU_H264",IMGFMT_VDPAU_H264},
{"VDPAU_WMV3",IMGFMT_VDPAU_WMV3},
{"VDPAU_VC1",IMGFMT_VDPAU_VC1},
+ {"VDPAU_MPEG4",IMGFMT_VDPAU_MPEG4},
{NULL, 0}
};
diff --git a/command.c b/command.c
index 9738377dd3..b52cfaf07d 100644
--- a/command.c
+++ b/command.c
@@ -1051,6 +1051,48 @@ static int mp_property_deinterlace(m_option_t *prop, int action,
return m_property_flag_ro(prop, action, arg, value);
}
+static int mp_property_yuv_colorspace(m_option_t *prop, int action,
+ void *arg, MPContext *mpctx)
+{
+ if (!mpctx->sh_video || !mpctx->sh_video->vfilter)
+ return M_PROPERTY_UNAVAILABLE;
+
+ struct vf_instance *vf = mpctx->sh_video->vfilter;
+ int colorspace;
+ switch (action) {
+ case M_PROPERTY_GET:
+ if (!arg)
+ return M_PROPERTY_ERROR;
+ if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, arg) != true)
+ return M_PROPERTY_UNAVAILABLE;
+ return M_PROPERTY_OK;
+ case M_PROPERTY_PRINT:
+ if (!arg)
+ return M_PROPERTY_ERROR;
+ if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &colorspace) != true)
+ return M_PROPERTY_UNAVAILABLE;
+ char * const names[] = {"BT.601 (SD)", "BT.709 (HD)", "SMPTE-240M"};
+ if (colorspace < 0 || colorspace >= sizeof(names) / sizeof(names[0]))
+ *(char **)arg = strdup("Unknown");
+ else
+ *(char**)arg = strdup(names[colorspace]);
+ return M_PROPERTY_OK;
+ case M_PROPERTY_SET:
+ if (!arg)
+ return M_PROPERTY_ERROR;
+ M_PROPERTY_CLAMP(prop, *(int *) arg);
+ vf->control(vf, VFCTRL_SET_YUV_COLORSPACE, arg);
+ return M_PROPERTY_OK;
+ case M_PROPERTY_STEP_UP:;
+ if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &colorspace) != true)
+ return M_PROPERTY_UNAVAILABLE;
+ colorspace += 1;
+ vf->control(vf, VFCTRL_SET_YUV_COLORSPACE, &colorspace);
+ return M_PROPERTY_OK;
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
/// Panscan (RW)
static int mp_property_panscan(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
@@ -2058,6 +2100,8 @@ static const m_option_t mp_properties[] = {
M_OPT_RANGE, 0, 1, NULL },
{ "deinterlace", mp_property_deinterlace, CONF_TYPE_FLAG,
M_OPT_RANGE, 0, 1, NULL },
+ { "yuv_colorspace", mp_property_yuv_colorspace, CONF_TYPE_INT,
+ M_OPT_RANGE, 0, 2, NULL },
{ "ontop", mp_property_ontop, CONF_TYPE_FLAG,
M_OPT_RANGE, 0, 1, NULL },
{ "rootwin", mp_property_rootwin, CONF_TYPE_FLAG,
@@ -2217,6 +2261,7 @@ static struct property_osd_display {
{ "border", 0, -1, _("Border: %s") },
{ "framedropping", 0, -1, _("Framedropping: %s") },
{ "deinterlace", 0, -1, _("Deinterlace: %s") },
+ { "yuv_colorspace", 0, -1, _("YUV colorspace: %s") },
{ "gamma", OSD_BRIGHTNESS, -1, _("Gamma") },
{ "brightness", OSD_BRIGHTNESS, -1, _("Brightness") },
{ "contrast", OSD_CONTRAST, -1, _("Contrast") },
diff --git a/etc/codecs.conf b/etc/codecs.conf
index 84660fc82f..68d47e6dea 100644
--- a/etc/codecs.conf
+++ b/etc/codecs.conf
@@ -954,6 +954,37 @@ videocodec ffodivx
dll mpeg4 ;opendivx
out YV12,I420,IYUV
+videocodec ffodivxvdpau
+ info "FFmpeg MPEG-4,DIVX-4/5 (VDPAU)"
+ status working
+ fourcc FMP4,fmp4
+ fourcc DIVX,divx
+ fourcc DIV1,div1 divx
+ fourcc MP4S,mp4s ; ISO MPEG-4 Video V1
+ fourcc M4S2,m4s2
+ fourcc xvid,XVID,XviD,XVIX
+ fourcc DX50,dx50,BLZ0 DX50
+ fourcc mp4v,MP4V
+ format 0x4
+ fourcc UMP4
+ fourcc RMP4
+ fourcc 3IV2,3iv2 ; 3ivx Delta 4
+ fourcc DXGM
+ fourcc SEDG ; diskless camcorder Samsung Miniket VP-M110
+ fourcc SMP4,smp4 ; Samsung SMP4 video codec
+ fourcc VIDM ; vidm 4.01 codec
+ format 0x10000004 ; mpeg 4 es
+ fourcc m4cc,M4CC
+ fourcc hdx4,HDX4
+ fourcc FVFW,fvfw
+ fourcc FFDS
+ fourcc DCOD,MVXM,EM4A,PM4V
+ fourcc M4T3,DMK2,DIGI,INMC
+ fourcc EPHV,SN40
+ driver ffmpeg
+ dll mpeg4_vdpau
+ out VDPAU_MPEG4
+
videocodec ffwv1f
info "WV1F MPEG-4"
status working
diff --git a/fmt-conversion.c b/fmt-conversion.c
index 05179d1b29..06699c6ee5 100644
--- a/fmt-conversion.c
+++ b/fmt-conversion.c
@@ -73,6 +73,7 @@ static const struct {
{IMGFMT_VDPAU_H264, PIX_FMT_VDPAU_H264},
{IMGFMT_VDPAU_WMV3, PIX_FMT_VDPAU_WMV3},
{IMGFMT_VDPAU_VC1, PIX_FMT_VDPAU_VC1},
+ {IMGFMT_VDPAU_MPEG4, PIX_FMT_VDPAU_MPEG4},
{0, PIX_FMT_NONE}
};
diff --git a/input/input.c b/input/input.c
index 71dfb38155..7738da8bcf 100644
--- a/input/input.c
+++ b/input/input.c
@@ -426,6 +426,7 @@ static const mp_cmd_bind_t def_cmd_binds[] = {
{ { '8', 0 }, "saturation 1" },
{ { 'd', 0 }, "frame_drop" },
{ { 'D', 0 }, "step_property_osd deinterlace" },
+ { { 'c', 0 }, "step_property_osd yuv_colorspace" },
{ { 'r', 0 }, "sub_pos -1" },
{ { 't', 0 }, "sub_pos +1" },
{ { 'a', 0 }, "sub_alignment" },
diff --git a/libmenu/vf_menu.c b/libmenu/vf_menu.c
index f8ceecc9ca..7f8ae84aca 100644
--- a/libmenu/vf_menu.c
+++ b/libmenu/vf_menu.c
@@ -62,7 +62,7 @@ void vf_menu_pause_update(struct vf_instance* vf) {
put_image(vf,pause_mpi, MP_NOPTS_VALUE);
// Don't draw the osd atm
//vf->control(vf,VFCTRL_DRAW_OSD,NULL);
- vo_flip_page(video_out);
+ vo_flip_page(video_out, 0, -1);
}
}
diff --git a/libmpcodecs/img_format.c b/libmpcodecs/img_format.c
index 4704cf2f6a..7d20a77cc7 100644
--- a/libmpcodecs/img_format.c
+++ b/libmpcodecs/img_format.c
@@ -72,6 +72,7 @@ const char *vo_format_name(int format)
case IMGFMT_VDPAU_MPEG1: return "MPEG1 VDPAU acceleration";
case IMGFMT_VDPAU_MPEG2: return "MPEG2 VDPAU acceleration";
case IMGFMT_VDPAU_H264: return "H.264 VDPAU acceleration";
+ case IMGFMT_VDPAU_MPEG4: return "MPEG-4 Part 2 VDPAU acceleration";
case IMGFMT_VDPAU_WMV3: return "WMV3 VDPAU acceleration";
case IMGFMT_VDPAU_VC1: return "VC1 VDPAU acceleration";
}
diff --git a/libmpcodecs/img_format.h b/libmpcodecs/img_format.h
index 89efb1d6cb..752629175d 100644
--- a/libmpcodecs/img_format.h
+++ b/libmpcodecs/img_format.h
@@ -118,6 +118,7 @@
#define IMGFMT_VDPAU_H264 (IMGFMT_VDPAU|0x03)
#define IMGFMT_VDPAU_WMV3 (IMGFMT_VDPAU|0x04)
#define IMGFMT_VDPAU_VC1 (IMGFMT_VDPAU|0x05)
+#define IMGFMT_VDPAU_MPEG4 (IMGFMT_VDPAU|0x06)
typedef struct {
void* data;
diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h
index 099135c5da..f9dbb8b4fb 100644
--- a/libmpcodecs/vf.h
+++ b/libmpcodecs/vf.h
@@ -81,7 +81,6 @@ typedef struct vf_seteq_s
#define VFCTRL_GET_EQUALIZER 8 /* gset color options (brightness,contrast etc) */
#define VFCTRL_DRAW_OSD 7
#define VFCTRL_CHANGE_RECTANGLE 9 /* Change the rectangle boundaries */
-#define VFCTRL_FLIP_PAGE 10 /* Tell the vo to flip pages */
#define VFCTRL_DUPLICATE_FRAME 11 /* For encoding - encode zero-change frame */
#define VFCTRL_SKIP_NEXT_FRAME 12 /* For encoding - drop the next frame that passes thru */
#define VFCTRL_FLUSH_FRAMES 13 /* For encoding - flush delayed frames */
@@ -94,6 +93,8 @@ typedef struct vf_seteq_s
* the OSD state outside of normal OSD draw time. */
#define VFCTRL_SET_OSD_OBJ 20
#define VFCTRL_REDRAW_OSD 21 /* Change user-visible OSD immediately */
+#define VFCTRL_SET_YUV_COLORSPACE 22
+#define VFCTRL_GET_YUV_COLORSPACE 23
#include "vfcap.h"
diff --git a/libmpcodecs/vf_tfields.c b/libmpcodecs/vf_tfields.c
index 395e55a323..28529d319b 100644
--- a/libmpcodecs/vf_tfields.c
+++ b/libmpcodecs/vf_tfields.c
@@ -368,8 +368,6 @@ static int continue_buffered_image(struct vf_instance *vf)
ret |= vf_next_put_image(vf, dmpi, pts);
if (!under_mencoder)
break;
- else
- if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
}
break;
case 1:
@@ -398,8 +396,6 @@ static int continue_buffered_image(struct vf_instance *vf)
ret |= vf_next_put_image(vf, dmpi, pts);
if (!under_mencoder)
break;
- else
- if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
}
break;
case 2:
@@ -424,8 +420,6 @@ static int continue_buffered_image(struct vf_instance *vf)
ret |= vf_next_put_image(vf, dmpi, pts);
if (!under_mencoder)
break;
- else
- if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
}
break;
}
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index c782a5517b..7026ac93fc 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -88,18 +88,16 @@ static int control(struct vf_instance* vf, int request, void* data)
if(!video_out) return CONTROL_FALSE; // vo not configured?
return vo_control(video_out, VOCTRL_SET_DEINTERLACE, data) == VO_TRUE;
}
+ case VFCTRL_GET_YUV_COLORSPACE:
+ return vo_control(video_out, VOCTRL_GET_YUV_COLORSPACE, data) == true;
+ case VFCTRL_SET_YUV_COLORSPACE:
+ return vo_control(video_out, VOCTRL_SET_YUV_COLORSPACE, data) == true;
case VFCTRL_DRAW_OSD:
if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured?
vo_draw_osd(video_out, data);
return CONTROL_TRUE;
case VFCTRL_REDRAW_OSD:
return vo_control(video_out, VOCTRL_REDRAW_OSD, data) == true;
- case VFCTRL_FLIP_PAGE:
- {
- if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured?
- vo_flip_page(video_out);
- return CONTROL_TRUE;
- }
case VFCTRL_SET_EQUALIZER:
{
vf_equalizer_t *eq=data;
diff --git a/libmpcodecs/vf_yadif.c b/libmpcodecs/vf_yadif.c
index 8c73ebacef..477ea03c9b 100644
--- a/libmpcodecs/vf_yadif.c
+++ b/libmpcodecs/vf_yadif.c
@@ -436,8 +436,6 @@ static int continue_buffered_image(struct vf_instance *vf)
ret |= vf_next_put_image(vf, dmpi, pts /*FIXME*/);
if (!under_mencoder)
break;
- if(i<(vf->priv->mode&1))
- vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
}
vf->priv->buffered_i = 1;
return ret;
diff --git a/libvo/vdpau_template.c b/libvo/vdpau_template.c
index ca1a6f6056..3f9b26c5d8 100644
--- a/libvo/vdpau_template.c
+++ b/libvo/vdpau_template.c
@@ -27,10 +27,13 @@ VDP_FUNCTION(VdpPresentationQueueBlockUntilSurfaceIdle, VDP_FUNC_ID_PRESENTATION
VDP_FUNCTION(VdpPresentationQueueCreate, VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE, presentation_queue_create)
VDP_FUNCTION(VdpPresentationQueueDestroy, VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY, presentation_queue_destroy)
VDP_FUNCTION(VdpPresentationQueueDisplay, VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY, presentation_queue_display)
+VDP_FUNCTION(VdpPresentationQueueGetTime, VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME, presentation_queue_get_time)
+VDP_FUNCTION(VdpPresentationQueueQuerySurfaceStatus, VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS, presentation_queue_query_surface_status)
VDP_FUNCTION(VdpPresentationQueueTargetCreateX11, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, presentation_queue_target_create_x11)
VDP_FUNCTION(VdpPresentationQueueTargetDestroy, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY, presentation_queue_target_destroy)
VDP_FUNCTION(VdpVideoMixerCreate, VDP_FUNC_ID_VIDEO_MIXER_CREATE, video_mixer_create)
VDP_FUNCTION(VdpVideoMixerDestroy, VDP_FUNC_ID_VIDEO_MIXER_DESTROY, video_mixer_destroy)
+VDP_FUNCTION(VdpVideoMixerQueryFeatureSupport, VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT, video_mixer_query_feature_support)
VDP_FUNCTION(VdpVideoMixerRender, VDP_FUNC_ID_VIDEO_MIXER_RENDER, video_mixer_render)
VDP_FUNCTION(VdpVideoMixerSetAttributeValues, VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES, video_mixer_set_attribute_values)
VDP_FUNCTION(VdpVideoMixerSetFeatureEnables, VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES, video_mixer_set_feature_enables)
diff --git a/libvo/video_out.c b/libvo/video_out.c
index 7a41fcf1d4..eb3d0183d6 100644
--- a/libvo/video_out.c
+++ b/libvo/video_out.c
@@ -328,13 +328,16 @@ void vo_draw_osd(struct vo *vo, struct osd_state *osd)
vo->driver->draw_osd(vo, osd);
}
-void vo_flip_page(struct vo *vo)
+void vo_flip_page(struct vo *vo, unsigned int pts_us, int duration)
{
if (!vo->config_ok)
return;
vo->frame_loaded = false;
- vo->next_pts = (-1LL<<63); // MP_NOPTS_VALUE
- vo->driver->flip_page(vo);
+ vo->next_pts = MP_NOPTS_VALUE;
+ if (vo->driver->flip_page_timed)
+ vo->driver->flip_page_timed(vo, pts_us, duration);
+ else
+ vo->driver->flip_page(vo);
}
void vo_check_events(struct vo *vo)
diff --git a/libvo/video_out.h b/libvo/video_out.h
index 9bbfd3dc41..17c387a320 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -30,6 +30,8 @@
#include "libmpcodecs/img_format.h"
//#include "vidix/vidix.h"
+#define MP_NOPTS_VALUE (-1LL<<63)
+
#define VO_EVENT_EXPOSE 1
#define VO_EVENT_RESIZE 2
#define VO_EVENT_KEYPRESS 4
@@ -86,6 +88,9 @@ typedef struct {
#define VOCTRL_UPDATE_SCREENINFO 32
+#define VOCTRL_SET_YUV_COLORSPACE 33
+#define VOCTRL_GET_YUV_COLORSPACE 34
+
// Vo can be used by xover
#define VOCTRL_XOVERLAY_SUPPORT 22
@@ -198,6 +203,7 @@ struct vo_driver {
* Blit/Flip buffer to the screen. Must be called after each frame!
*/
void (*flip_page)(struct vo *vo);
+ void (*flip_page_timed)(struct vo *vo, unsigned int pts_us, int duration);
/*
* This func is called after every frames to handle keyboard and
@@ -231,6 +237,7 @@ struct vo {
bool frame_loaded; // Is there a next frame the VO could flip to?
double next_pts; // pts value of the next frame if any
+ double next_pts2; // optional pts of frame after that
const struct vo_driver *driver;
void *priv;
@@ -274,7 +281,7 @@ int vo_get_buffered_frame(struct vo *vo, bool eof);
int vo_draw_frame(struct vo *vo, uint8_t *src[]);
int vo_draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int x, int y);
void vo_draw_osd(struct vo *vo, struct osd_state *osd);
-void vo_flip_page(struct vo *vo);
+void vo_flip_page(struct vo *vo, unsigned int pts_us, int duration);
void vo_check_events(struct vo *vo);
void vo_seek_reset(struct vo *vo);
void vo_destroy(struct vo *vo);
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c
index e613205834..484b5fc87d 100644
--- a/libvo/vo_vdpau.c
+++ b/libvo/vo_vdpau.c
@@ -2,6 +2,7 @@
* VDPAU video output driver
*
* Copyright (C) 2008 NVIDIA
+ * Copyright (C) 2009 Uoti Urpala
*
* This file is part of MPlayer.
*
@@ -32,6 +33,7 @@
#include <dlfcn.h>
#include <stdint.h>
#include <stdbool.h>
+#include <limits.h>
#include "config.h"
#include "mp_msg.h"
@@ -72,8 +74,9 @@
} while (0)
/* number of video and output surfaces */
-#define NUM_OUTPUT_SURFACES 2
+#define NUM_OUTPUT_SURFACES 3
#define MAX_VIDEO_SURFACES 50
+#define NUM_BUFFERED_VIDEO 4
/* number of palette entries */
#define PALETTE_SIZE 256
@@ -104,27 +107,35 @@ struct vdpctx {
VdpPresentationQueueTarget flip_target;
VdpPresentationQueue flip_queue;
+ uint64_t last_vdp_time;
+ unsigned int last_sync_update;
void *vdpau_lib_handle;
/* output_surfaces[NUM_OUTPUT_SURFACES] is misused for OSD. */
#define osd_surface vc->output_surfaces[NUM_OUTPUT_SURFACES]
VdpOutputSurface output_surfaces[NUM_OUTPUT_SURFACES + 1];
- VdpVideoSurface deint_surfaces[3];
- double deint_pts[3];
+ struct buffered_video_surface {
+ VdpVideoSurface surface;
+ double pts;
+ mp_image_t *mpi;
+ } buffered_video[NUM_BUFFERED_VIDEO];
int deint_queue_pos;
- mp_image_t *deint_mpi[3];
int output_surface_width, output_surface_height;
VdpVideoMixer video_mixer;
+ int user_colorspace;
+ int colorspace;
int deint;
int deint_type;
int deint_counter;
int pullup;
float denoise;
float sharpen;
+ int hqscaling;
int chroma_deint;
int top_field_first;
+ bool flip;
VdpDecoder decoder;
int decoder_max_refs;
@@ -135,6 +146,13 @@ struct vdpctx {
struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES];
int surface_num;
+ VdpTime recent_vsync_time;
+ float user_fps;
+ unsigned int vsync_interval;
+ uint64_t last_queue_time;
+ uint64_t last_ideal_time;
+ bool dropped_frame;
+ uint64_t dropped_time;
uint32_t vid_width, vid_height;
uint32_t image_format;
VdpChromaType vdp_chroma_type;
@@ -169,15 +187,57 @@ struct vdpctx {
// Video equalizer
VdpProcamp procamp;
- bool visible_buf;
+ int num_shown_frames;
bool paused;
// These tell what's been initialized and uninit() should free/uninitialize
bool mode_switched;
};
+static int change_vdptime_sync(struct vdpctx *vc, unsigned int *t)
+{
+ struct vdp_functions *vdp = vc->vdp;
+ VdpStatus vdp_st;
+ VdpTime vdp_time;
+ vdp_st = vdp->presentation_queue_get_time(vc->flip_queue, &vdp_time);
+ CHECK_ST_ERROR("Error when calling vdp_presentation_queue_get_time");
+ unsigned int t1 = *t;
+ unsigned int t2 = GetTimer();
+ uint64_t old = vc->last_vdp_time + (t1 - vc->last_sync_update) * 1000ULL;
+ if (vdp_time > old)
+ if (vdp_time > old + (t2 - t1) * 1000ULL)
+ vdp_time -= (t2 - t1) * 1000ULL;
+ else
+ vdp_time = old;
+ mp_msg(MSGT_VO, MSGL_V, "[vdpau] adjusting VdpTime offset by %f µs\n",
+ (int64_t)(vdp_time - old) / 1000.);
+ vc->last_vdp_time = vdp_time;
+ vc->last_sync_update = t1;
+ *t = t2;
+ return 0;
+}
+
+static uint64_t sync_vdptime(struct vo *vo)
+{
+ struct vdpctx *vc = vo->priv;
+
+ unsigned int t = GetTimer();
+ if (t - vc->last_sync_update > 5000000)
+ change_vdptime_sync(vc, &t);
+ uint64_t now = (t - vc->last_sync_update) * 1000ULL + vc->last_vdp_time;
+ // Make sure nanosecond inaccuracies don't make things inconsistent
+ now = FFMAX(now, vc->recent_vsync_time);
+ return now;
+}
+
+static uint64_t convert_to_vdptime(struct vo *vo, unsigned int t)
+{
+ struct vdpctx *vc = vo->priv;
+ return (int)(t - vc->last_sync_update) * 1000LL + vc->last_vdp_time;
+}
+
+static void flip_page_timed(struct vo *vo, unsigned int pts_us, int duration);
-static void flip_page(struct vo *vo);
static int video_to_output_surface(struct vo *vo)
{
struct vdpctx *vc = vo->priv;
@@ -187,6 +247,7 @@ static int video_to_output_surface(struct vo *vo)
if (vc->deint_queue_pos < 0)
return -1;
+ struct buffered_video_surface *bv = vc->buffered_video;
int field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
unsigned int dp = vc->deint_queue_pos;
// dp==0 means last field of latest frame, 1 earlier field of latest frame,
@@ -196,11 +257,10 @@ static int video_to_output_surface(struct vo *vo)
VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD:
VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
}
- VdpVideoSurface *q = vc->deint_surfaces;
const VdpVideoSurface *past_fields = (const VdpVideoSurface []){
- q[(dp+1)/2], q[(dp+2)/2]};
+ bv[(dp+1)/2].surface, bv[(dp+2)/2].surface};
const VdpVideoSurface *future_fields = (const VdpVideoSurface []){
- q[(dp-1)/2]};
+ dp >= 1 ? bv[(dp-1)/2].surface : VDP_INVALID_HANDLE};
VdpOutputSurface output_surface = vc->output_surfaces[vc->surface_num];
vdp_st = vdp->presentation_queue_block_until_surface_idle(vc->flip_queue,
output_surface,
@@ -210,56 +270,93 @@ static int video_to_output_surface(struct vo *vo)
vdp_st = vdp->video_mixer_render(vc->video_mixer, VDP_INVALID_HANDLE,
0, field, 2, past_fields,
- vc->deint_surfaces[dp/2], 1, future_fields,
+ bv[dp/2].surface, 1, future_fields,
&vc->src_rect_vid, output_surface,
NULL, &vc->out_rect_vid, 0, NULL);
CHECK_ST_WARNING("Error when calling vdp_video_mixer_render");
return 0;
}
-static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface,
- struct mp_image *reserved_mpi, double pts)
+static void get_buffered_frame(struct vo *vo, bool eof)
{
struct vdpctx *vc = vo->priv;
- if (reserved_mpi)
- reserved_mpi->usage_count++;
- if (vc->deint_mpi[2])
- vc->deint_mpi[2]->usage_count--;
-
- for (int i = 2; i > 0; i--) {
- vc->deint_mpi[i] = vc->deint_mpi[i - 1];
- vc->deint_surfaces[i] = vc->deint_surfaces[i - 1];
- vc->deint_pts[i] = vc->deint_pts[i - 1];
- }
- vc->deint_mpi[0] = reserved_mpi;
- vc->deint_surfaces[0] = surface;
- vc->deint_pts[0] = pts;
+ int dqp = vc->deint_queue_pos;
+ if (dqp < 0)
+ dqp += 1000;
+ else
+ dqp = vc->deint >= 2 ? dqp - 1 : dqp - 2 | 1;
+ if (dqp < (eof ? 0 : 3))
+ return;
+ dqp = FFMIN(dqp, 4);
+ vc->deint_queue_pos = dqp;
vo->frame_loaded = true;
- vo->next_pts = pts;
- if (vc->deint >= 2 && vc->deint_queue_pos >= 0) {
- vc->deint_queue_pos = 2;
- double diff = vc->deint_pts[0] - vc->deint_pts[1];
+
+ // Set pts values
+ struct buffered_video_surface *bv = vc->buffered_video;
+ int idx = vc->deint_queue_pos >> 1;
+ if (idx == 0) { // no future frame/pts available
+ vo->next_pts = bv[0].pts;
+ vo->next_pts2 = MP_NOPTS_VALUE;
+ } else if (!(vc->deint >= 2)) { // no field-splitting deinterlace
+ vo->next_pts = bv[idx].pts;
+ vo->next_pts2 = bv[idx - 1].pts;
+ } else { // deinterlace with separate fields
+ double intermediate_pts;
+ double diff = bv[idx - 1].pts - bv[idx].pts;
if (diff > 0 && diff < 0.5)
- vo->next_pts = (vc->deint_pts[0] + vc->deint_pts[1]) / 2;
+ intermediate_pts = (bv[idx].pts + bv[idx - 1].pts) / 2;
else
- vo->next_pts = vc->deint_pts[1];
- } else
- vc->deint_queue_pos = 1;
+ intermediate_pts = bv[idx].pts;
+ if (vc->deint_queue_pos & 1) { // first field
+ vo->next_pts = bv[idx].pts;
+ vo->next_pts2 = intermediate_pts;
+ } else {
+ vo->next_pts = intermediate_pts;
+ vo->next_pts2 = bv[idx - 1].pts;
+ }
+ }
+
video_to_output_surface(vo);
}
+static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface,
+ struct mp_image *reserved_mpi, double pts)
+{
+ struct vdpctx *vc = vo->priv;
+ struct buffered_video_surface *bv = vc->buffered_video;
+
+ if (reserved_mpi)
+ reserved_mpi->usage_count++;
+ if (bv[NUM_BUFFERED_VIDEO - 1].mpi)
+ bv[NUM_BUFFERED_VIDEO - 1].mpi->usage_count--;
+
+ for (int i = NUM_BUFFERED_VIDEO - 1; i > 0; i--)
+ bv[i] = bv[i - 1];
+ bv[0] = (struct buffered_video_surface){
+ .mpi = reserved_mpi,
+ .surface = surface,
+ .pts = pts,
+ };
+
+ vc->deint_queue_pos += 2;
+ get_buffered_frame(vo, false);
+}
+
static void forget_frames(struct vo *vo)
{
struct vdpctx *vc = vo->priv;
- vc->deint_queue_pos = -1;
- for (int i = 0; i < 3; i++) {
- vc->deint_surfaces[i] = VDP_INVALID_HANDLE;
- if (vc->deint_mpi[i])
- vc->deint_mpi[i]->usage_count--;
- vc->deint_mpi[i] = NULL;
+ vc->deint_queue_pos = -1001;
+ vc->dropped_frame = false;
+ for (int i = 0; i < NUM_BUFFERED_VIDEO; i++) {
+ struct buffered_video_surface *p = vc->buffered_video + i;
+ if (p->mpi)
+ p->mpi->usage_count--;
+ *p = (struct buffered_video_surface){
+ .surface = VDP_INVALID_HANDLE,
+ };
}
}
@@ -280,8 +377,8 @@ static void resize(struct vo *vo)
vc->out_rect_vid.y1 = dst_rect.bottom;
vc->src_rect_vid.x0 = src_rect.left;
vc->src_rect_vid.x1 = src_rect.right;
- vc->src_rect_vid.y0 = src_rect.top;
- vc->src_rect_vid.y1 = src_rect.bottom;
+ vc->src_rect_vid.y0 = vc->flip ? src_rect.bottom : src_rect.top;
+ vc->src_rect_vid.y1 = vc->flip ? src_rect.top : src_rect.bottom;
vc->border_x = borders.left;
vc->border_y = borders.top;
#ifdef CONFIG_FREETYPE
@@ -290,6 +387,7 @@ static void resize(struct vo *vo)
#endif
vo_osd_changed(OSDTYPE_OSD);
+ bool had_frames = vc->num_shown_frames;
if (vc->output_surface_width < vo->dwidth
|| vc->output_surface_height < vo->dheight) {
if (vc->output_surface_width < vo->dwidth) {
@@ -315,10 +413,11 @@ static void resize(struct vo *vo)
mp_msg(MSGT_VO, MSGL_DBG2, "OUT CREATE: %u\n",
vc->output_surfaces[i]);
}
+ vc->num_shown_frames = 0;
}
- if (vc->paused && vc->visible_buf)
+ if (vc->paused && had_frames)
if (video_to_output_surface(vo) >= 0)
- flip_page(vo);
+ flip_page_timed(vo, 0, -1);
}
static void preemption_callback(VdpDevice device, void *context)