/*
* VDPAU video output driver
*
* Copyright (C) 2008 NVIDIA (Rajib Mahapatra <rmahapatra@nvidia.com>)
* Copyright (C) 2009 Uoti Urpala
*
* This file is part of MPlayer.
*
* MPlayer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* MPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* Actual decoding is done in video/decode/vdpau.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include <assert.h>
#include <libavutil/common.h>
#include "config.h"
#include "video/vdpau.h"
#include "video/hwdec.h"
#include "common/msg.h"
#include "options/options.h"
#include "talloc.h"
#include "vo.h"
#include "x11_common.h"
#include "video/csputils.h"
#include "sub/osd.h"
#include "options/m_option.h"
#include "video/vfcap.h"
#include "video/mp_image.h"
#include "osdep/timer.h"
#include "bitmap_packer.h"
// Returns x + a, but wrapped around to the range [0, m)
// a must be within [-m, m], x within [0, m)
#define WRAP_ADD(x, a, m) ((a) < 0 \
? ((x)+(a)+(m) < (m) ? (x)+(a)+(m) : (x)+(a)) \
: ((x)+(a) < (m) ? (x)+(a) : (x)+(a)-(m)))
/* number of video and output surfaces */
#define MAX_OUTPUT_SURFACES 15
#define NUM_BUFFERED_VIDEO 5
/* Pixelformat used for output surfaces */
#define OUTPUT_RGBA_FORMAT VDP_RGBA_FORMAT_B8G8R8A8
/*
* Global variable declaration - VDPAU specific
*/
struct vdpctx {
struct mp_vdpau_ctx *mpvdp;
struct vdp_functions *vdp;
VdpDevice vdp_device;
uint64_t preemption_counter;
struct m_color colorkey;
VdpPresentationQueueTarget flip_target;
VdpPresentationQueue flip_queue;
VdpOutputSurface output_surfaces[MAX_OUTPUT_SURFACES];
VdpOutputSurface screenshot_surface;
int num_output_surfaces;
VdpOutputSurface rgb_surfaces[NUM_BUFFERED_VIDEO];
VdpOutputSurface black_pixel;
struct buffered_video_surface {
// Either surface or rgb_surface is used (never both)
VdpVideoSurface surface;
VdpOutputSurface rgb_surface;
double pts;
mp_image_t *mpi;
} buffered_video[NUM_BUFFERED_VIDEO];
int deint_queue_pos;
// State for redrawing the screen after seek-reset
int prev_deint_queue_pos;
int output_surface_width, output_surface_height;
int force_yuv;
VdpVideoMixer video_mixer;
int user_deint;
int deint;
int deint_type;
int pullup;
float denoise;
float sharpen;
int hqscaling;
int chroma_deint;
int flip_offset_window;
int flip_offset_fs;
int top_field_first;
bool flip;
VdpRect src_rect_vid;
VdpRect out_rect_vid;
struct mp_osd_res osd_rect;
int surface_num; // indexes output_surfaces
int query_surface_num;
VdpTime recent_vsync_time;
float user_fps;
int composite_detect;
unsigned int vsync_interval;
uint64_t last_queue_time;
uint64_t queue_time[MAX_OUTPUT_SURFACES];
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;
VdpYCbCrFormat vdp_pixel_format;
bool rgb_mode;
// OSD
struct osd_bitmap_surface {
VdpRGBAFormat format;
VdpBitmapSurface surface;
uint32_t max_width;
uint32_t max_height;
struct bitmap_packer *packer;
// List of surfaces to be rendered
struct osd_target {
VdpRect source;
VdpRect dest;
VdpColor color;
} *targets;
int targets_size;
int render_count;
int bitmap_id;
int bitmap_pos_id;
} osd_surfaces[MAX_OSD_PARTS];
// Video equalizer
struct mp_csp_equalizer video_eq;
};
static bool status_ok(struct vo *vo);
static int render_video_to_output_surface(struct vo *vo,
VdpOutputSurface output_surface,
VdpRect *output_rect,
VdpRect *video_rect)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
VdpTime dummy;
VdpStatus vdp_st;
struct buffered_video_surface *bv = vc->buffered_video;
int dp = vc->deint_queue_pos;
// Redraw frame from before seek reset?
if (dp < 0)
dp = vc->prev_deint_queue_pos;
if (dp < 0) {
// At least clear the screen if there is nothing to render
int flags = VDP_OUTPUT_SURFACE_RENDER_ROTATE_0;
vdp_st = vdp->output_surface_render_output_surface(output_surface,
NULL, vc->black_pixel,
NULL, NULL, NULL,
flags);
return -1;
}
vdp_st = vdp->presentation_queue_block_until_surface_idle(vc->flip_queue,
output_surface,
&dummy);
CHECK_VDP_WARNING(vo, "Error when calling "
"vdp_presentation_queue_block_until_surface_idle");
if (vc->rgb_mode) {
int flags = VDP_OUTPUT_SURFACE_RENDER_ROTATE_0;
vdp_st = vdp->output_surface_render_output_surface(output_surface,
NULL, vc->black_pixel,
NULL, NULL, NULL,
flags);
|