diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-11-16 04:18:13 +0200 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-11-16 04:18:13 +0200 |
commit | 507f4fe6c7811558b1367e4b64855ae7f9bc8da8 (patch) | |
tree | 416b70358bf4b13871cda60fd8e8f64c5e9a2392 | |
parent | 8bbb79c03a594e452fb9109dd6fda781d390a798 (diff) | |
parent | b8861ce8e28080b151467827f65bdc3707a74511 (diff) | |
download | mpv-507f4fe6c7811558b1367e4b64855ae7f9bc8da8.tar.bz2 mpv-507f4fe6c7811558b1367e4b64855ae7f9bc8da8.tar.xz |
Merge branch 'vdpau'
-rw-r--r-- | DOCS/man/en/mplayer.1 | 37 | ||||
-rw-r--r-- | TOOLS/vdpau_functions.py | 3 | ||||
-rw-r--r-- | codec-cfg.c | 1 | ||||
-rw-r--r-- | command.c | 45 | ||||
-rw-r--r-- | etc/codecs.conf | 31 | ||||
-rw-r--r-- | fmt-conversion.c | 1 | ||||
-rw-r--r-- | input/input.c | 1 | ||||
-rw-r--r-- | libmenu/vf_menu.c | 2 | ||||
-rw-r--r-- | libmpcodecs/img_format.c | 1 | ||||
-rw-r--r-- | libmpcodecs/img_format.h | 1 | ||||
-rw-r--r-- | libmpcodecs/vf.h | 3 | ||||
-rw-r--r-- | libmpcodecs/vf_tfields.c | 6 | ||||
-rw-r--r-- | libmpcodecs/vf_vo.c | 10 | ||||
-rw-r--r-- | libmpcodecs/vf_yadif.c | 2 | ||||
-rw-r--r-- | libvo/vdpau_template.c | 3 | ||||
-rw-r--r-- | libvo/video_out.c | 9 | ||||
-rw-r--r-- | libvo/video_out.h | 9 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 492 | ||||
-rw-r--r-- | libvo/vo_xv.c | 11 | ||||
-rw-r--r-- | libvo/x11_common.c | 18 | ||||
-rw-r--r-- | libvo/x11_common.h | 1 | ||||
-rw-r--r-- | mencoder.c | 2 | ||||
-rw-r--r-- | mplayer.c | 30 |
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} }; @@ -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) |