/*
* VDPAU video output driver
*
* Copyright (C) 2008 NVIDIA
*
* 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 and presentation are implemented here.
* All necessary frame information is collected through
* the "vdpau_render_state" structure after parsing all headers
* etc. in libavcodec for different codecs.
*/
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stdbool.h>
#include "config.h"
#include "mp_msg.h"
#include "options.h"
#include "talloc.h"
#include "video_out.h"
#include "x11_common.h"
#include "aspect.h"
#include "sub.h"
#include "subopt-helper.h"
#include "libmpcodecs/vfcap.h"
#include "libmpcodecs/mp_image.h"
#include "osdep/timer.h"
#include "libavcodec/vdpau.h"
#include "font_load.h"
#include "libavutil/common.h"
#include "libavutil/mathematics.h"
#include "ass_mp.h"
#define CHECK_ST_ERROR(message) \
do { \
if (vdp_st != VDP_STATUS_OK) { \
mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] %s: %s\n", \
message, vdp->get_error_string(vdp_st)); \
return -1; \
} \
} while (0)
#define CHECK_ST_WARNING(message) \
do { \
if (vdp_st != VDP_STATUS_OK) \
mp_msg(MSGT_VO, MSGL_WARN, "[ vdpau] %s: %s\n", \
message, vdp->get_error_string(vdp_st)); \
} while (0)
/* number of video and output surfaces */
#define NUM_OUTPUT_SURFACES 2
#define MAX_VIDEO_SURFACES 50
/* number of palette entries */
#define PALETTE_SIZE 256
/* Initial size of EOSD surface in pixels (x*x) */
#define EOSD_SURFACE_INITIAL_SIZE 256
/*
* Global variable declaration - VDPAU specific
*/
struct vdp_functions {
#define VDP_FUNCTION(vdp_type, _, mp_name) vdp_type *mp_name;
#include "vdpau_template.c"
#undef VDP_FUNCTION
};
struct vdpctx {
struct vdp_functions *vdp;
VdpDevice vdp_device;
bool is_preempted;
bool preemption_acked;
bool preemption_user_notified;
unsigned int last_preemption_retry_fail;
VdpDeviceCreateX11 *vdp_device_create;
VdpGetProcAddress *vdp_get_proc_address;
VdpPresentationQueueTarget flip_target;
VdpPresentationQueue flip_queue;
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];
int deint_queue_pos;
mp_image_t *deint_mpi[3];
int output_surface_width, output_surface_height;
VdpVideoMixer video_mixer;
int deint;
int deint_type;
int deint_counter;
int pullup;
float denoise;
float sharpen;
int chroma_deint;
int top_field_first;
VdpDecoder decoder;
int decoder_max_refs;
VdpRect src_rect_vid;
VdpRect out_rect_vid;
int border_x, border_y;
struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES];
int surface_num;
uint32_t vid_width, vid_height;
uint32_t image_format;
VdpChromaType vdp_chroma_type;
VdpYCbCrFormat vdp_pixel_format;
/* draw_osd */
unsigned char *index_data;
int index_data_size;
uint32_t palette[PALETTE_SIZE];
// EOSD
// Pool of surfaces
struct eosd_bitmap_surface {
VdpBitmapSurface surface;
int w;
int h;
uint32_t max_width;
uint32_t max_height;
} eosd_surface;
// List of surfaces to be rendered
struct eosd_target {
VdpRect source;
VdpRect dest;
VdpColor color;
} *eosd_targets;
int eosd_targets_size;
int *eosd_scratch;
int eosd_render_count;
// Video equalizer
VdpProcamp procamp;
bool visible_buf;
bool paused;
// These tell what's been initialized and uninit() should free/uninitialize
bool mode_switched;
};
static void flip_page(struct vo *vo);
static void video_to_output_surface(struct vo *vo)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
VdpTime dummy;
VdpStatus vdp_st;
if (vc->deint_queue_pos < 0)
return;
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,
// 2 last field of previous frame and so on
if (vc->deint) {
field = vc->top_field_first ^ (dp & 1) ?
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]};
const VdpVideoSurface *future_fields = (const VdpVideoSurface [])
|