summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Thommeret <hftom@free.fr>2009-06-11 01:06:33 +0100
committerChristophe Thommeret <hftom@free.fr>2009-06-11 01:06:33 +0100
commit152bbca94ab1e298c68a7b810222a5ae6f5a8808 (patch)
treedf0514072d62dcd3179818e38b2c4f06667a3492
parent16dff702fb2b4d807c465b0a30afeb862b49e9a1 (diff)
downloadxine-lib-152bbca94ab1e298c68a7b810222a5ae6f5a8808.tar.gz
xine-lib-152bbca94ab1e298c68a7b810222a5ae6f5a8808.tar.bz2
video_window_overlay + vdpau_dispose fixes.
-rw-r--r--include/xine.h.in8
-rw-r--r--src/video_out/video_out_vdpau.c83
-rw-r--r--src/xine-engine/osd.c26
-rw-r--r--src/xine-engine/osd.h11
-rw-r--r--src/xine-engine/video_out.c14
-rw-r--r--src/xine-engine/video_out.h7
-rw-r--r--src/xine-engine/xine_interface.c4
7 files changed, 138 insertions, 15 deletions
diff --git a/include/xine.h.in b/include/xine.h.in
index a2a658611..854474de3 100644
--- a/include/xine.h.in
+++ b/include/xine.h.in
@@ -2139,6 +2139,7 @@ void xine_event_send (xine_stream_t *stream, const xine_event_t *event) XINE_PRO
#define XINE_OSD_CAP_UNSCALED 0x0002 /* unscaled overlays supp. by vo drv */
#define XINE_OSD_CAP_CUSTOM_EXTENT 0x0004 /* hardware scaled to match video output window */
#define XINE_OSD_CAP_ARGB_LAYER 0x0008 /* supports separate true color layer */
+#define XINE_OSD_CAP_VIDEO_WINDOW 0x0010 /* can scale video to an area within osd extent */
typedef struct xine_osd_s xine_osd_t;
@@ -2226,6 +2227,13 @@ void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer,
void xine_osd_set_extent(xine_osd_t *self, int extent_width, int extent_height) XINE_PROTECTED;
/*
+ * define area within osd extent to output
+ * video to while osd is on screen
+ * see also XINE_OSD_CAP_VIDEO_WINDOW
+ */
+void xine_osd_set_video_window(xine_osd_t *self, int window_x, int window_y, int window_width, int window_height) XINE_PROTECTED;
+
+/*
* close osd rendering engine
* loaded fonts are unloaded
* osd objects are closed
diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c
index 7f4956e97..c7d3daa02 100644
--- a/src/video_out/video_out_vdpau.c
+++ b/src/video_out/video_out_vdpau.c
@@ -81,6 +81,8 @@ VdpDevice vdp_device;
VdpPresentationQueue vdp_queue;
VdpPresentationQueueTarget vdp_queue_target;
+VdpDeviceDestroy *vdp_device_destroy;
+
VdpGetProcAddress *vdp_get_proc_address;
VdpGetApiVersion *vdp_get_api_version;
@@ -266,6 +268,11 @@ typedef struct {
int argb_ovl_data_count;
argb_ovl_data_t argb_ovl_data[XINE_VORAW_MAX_OVL];
+ int32_t video_window_x;
+ int32_t video_window_y;
+ int32_t video_window_width;
+ int32_t video_window_height;
+
VdpVideoSurface soft_surface;
uint32_t soft_surface_width;
uint32_t soft_surface_height;
@@ -350,6 +357,10 @@ static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_
int ovl_data_count = 0;
int total_extent_width = 0, total_extent_height = 0;
+ this->video_window_x = 0;
+ this->video_window_y = 0;
+ this->video_window_width = 0;
+ this->video_window_height = 0;
/* lock layers while processing and determine extent */
for (i = 0; i < this->argb_ovl_count; i++) {
@@ -373,6 +384,14 @@ static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_
ovl_data[ovl_data_count].h = this->argb_ovl[i]->height;
ovl[ovl_data_count++] = this->argb_ovl[i];
}
+ if (this->argb_ovl[i]->video_window_width > 0
+ && this->argb_ovl[i]->video_window_height > 0) {
+ /* last one wins */
+ this->video_window_x = this->argb_ovl[i]->video_window_x;
+ this->video_window_y = this->argb_ovl[i]->video_window_y;
+ this->video_window_width = this->argb_ovl[i]->video_window_width;
+ this->video_window_height = this->argb_ovl[i]->video_window_height;
+ }
}
}
@@ -428,7 +447,6 @@ static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_
VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&zeros, &pitch, &dest);
if (st != VDP_STATUS_OK)
printf("vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st));
- this->has_argb_overlay = 1;
}
}
free(zeros);
@@ -1406,13 +1424,23 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
layer_count = 0;
}
- VdpRect argb_rect = {0, 0, this->argb_overlay_width, this->argb_overlay_height };
+ VdpRect argb_dest;
+ VdpRect argb_rect = { 0, 0, this->argb_overlay_width, this->argb_overlay_height };
if( this->has_argb_overlay ) {
layer_count++;
- layer[layer_count-1].destination_rect = &vid_dest;
+ memcpy(&argb_dest, &vid_dest, sizeof (vid_dest));
+ layer[layer_count-1].destination_rect = &argb_dest;
layer[layer_count-1].source_rect = &argb_rect;
layer[layer_count-1].source_surface = this->argb_overlay;
layer[layer_count-1].struct_version = VDP_LAYER_VERSION;
+ /* recalculate video destination window to match osd's specified video window */
+ if (this->video_window_width > 0 && this->video_window_height > 0) {
+ VdpRect win_rect = { this->video_window_x, this->video_window_y, this->video_window_x + this->video_window_width, this->video_window_y + this->video_window_height };
+ vid_dest.x0 = ((win_rect.x0 - argb_rect.x0) * (argb_dest.x1 - argb_dest.x0) + argb_dest.x0 * (argb_rect.x1 - argb_rect.x0)) / (argb_rect.x1 - argb_rect.x0);
+ vid_dest.y0 = ((win_rect.y0 - argb_rect.y0) * (argb_dest.y1 - argb_dest.y0) + argb_dest.y0 * (argb_rect.y1 - argb_rect.y0)) / (argb_rect.y1 - argb_rect.y0);
+ vid_dest.x1 = ((win_rect.x1 - argb_rect.x0) * (argb_dest.x1 - argb_dest.x0) + argb_dest.x0 * (argb_rect.x1 - argb_rect.x0)) / (argb_rect.x1 - argb_rect.x0);
+ vid_dest.y1 = ((win_rect.y1 - argb_rect.y0) * (argb_dest.y1 - argb_dest.y0) + argb_dest.y0 * (argb_rect.y1 - argb_rect.y0)) / (argb_rect.y1 - argb_rect.y0);
+ }
}
/* try to get frame duration from previous img->pts when frame->duration is 0 */
@@ -1457,7 +1485,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
#ifdef LOCKDISPLAY
XLockDisplay(this->display);
#endif
- }
+ }
if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) {
/* recreate output surface to match window size */
@@ -1726,18 +1754,29 @@ static void vdpau_dispose (vo_driver_t *this_gen)
if ( this->video_mixer!=VDP_INVALID_HANDLE )
vdp_video_mixer_destroy( this->video_mixer );
- if ( this->overlay_unscaled!=VDP_INVALID_HANDLE )
- vdp_output_surface_destroy( this->overlay_unscaled );
- if ( this->overlay_output!=VDP_INVALID_HANDLE )
- vdp_output_surface_destroy( this->overlay_output );
- if ( this->output_surface[0]!=VDP_INVALID_HANDLE )
- vdp_output_surface_destroy( this->output_surface[0] );
- if ( this->output_surface[1]!=VDP_INVALID_HANDLE )
- vdp_output_surface_destroy( this->output_surface[1] );
if ( this->soft_surface != VDP_INVALID_HANDLE )
vdp_video_surface_destroy( this->soft_surface );
- vdp_queue_destroy( vdp_queue );
- vdp_queue_target_destroy( vdp_queue_target );
+
+ if ( vdp_output_surface_destroy ) {
+ if (this->argb_overlay != VDP_INVALID_HANDLE)
+ vdp_output_surface_destroy(this->argb_overlay);
+ if ( this->overlay_unscaled!=VDP_INVALID_HANDLE )
+ vdp_output_surface_destroy( this->overlay_unscaled );
+ if ( this->overlay_output!=VDP_INVALID_HANDLE )
+ vdp_output_surface_destroy( this->overlay_output );
+ if ( this->output_surface[0]!=VDP_INVALID_HANDLE )
+ vdp_output_surface_destroy( this->output_surface[0] );
+ if ( this->output_surface[1]!=VDP_INVALID_HANDLE )
+ vdp_output_surface_destroy( this->output_surface[1] );
+ }
+
+ if ( vdp_queue != VDP_INVALID_HANDLE )
+ vdp_queue_destroy( vdp_queue );
+ if ( vdp_queue_target != VDP_INVALID_HANDLE )
+ vdp_queue_target_destroy( vdp_queue_target );
+
+ if ( (vdp_device != VDP_INVALID_HANDLE) && vdp_device_destroy )
+ vdp_device_destroy( vdp_device );
for ( i=0; i<NUM_FRAMES_BACK; i++ )
if ( this->back_frame[i] )
@@ -1927,6 +1966,17 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
this->vo_driver.dispose = vdpau_dispose;
this->vo_driver.redraw_needed = vdpau_redraw_needed;
+ this->video_mixer = VDP_INVALID_HANDLE;
+ this->output_surface[0] = VDP_INVALID_HANDLE;
+ this->output_surface[1] = VDP_INVALID_HANDLE;
+ this->soft_surface = VDP_INVALID_HANDLE;
+ vdp_queue = VDP_INVALID_HANDLE;
+ vdp_queue_target = VDP_INVALID_HANDLE;
+ vdp_device = VDP_INVALID_HANDLE;
+
+ vdp_output_surface_destroy = NULL,
+ vdp_device_destroy = NULL;
+
for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) {
this->overlays[i].ovl_w = this->overlays[i].ovl_h = 0;
this->overlays[i].bitmap_width = this->overlays[i].bitmap_height = 0;
@@ -1994,6 +2044,9 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
vdpau_dispose( &this->vo_driver );
return NULL;
}
+ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DEVICE_DESTROY , (void*)&vdp_device_destroy );
+ if ( vdpau_init_error( st, "Can't get DEVICE_DESTROY proc address !!", &this->vo_driver, 1 ) )
+ return NULL;
st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void*)&orig_vdp_video_surface_create ); vdp_video_surface_create = guarded_vdp_video_surface_create;
if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) )
return NULL;
@@ -2189,7 +2242,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
if(frame_num < 22)
config->update_num(config,"engine.buffers.video_num_frames",22);
- this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY;
+ this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY | VO_CAP_VIDEO_WINDOW_OVERLAY;
ok = 0;
uint32_t mw, mh, ml, mr;
st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_MAIN, &ok, &ml, &mr, &mw, &mh );
diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c
index 7f4e6aefb..73470be1f 100644
--- a/src/xine-engine/osd.c
+++ b/src/xine-engine/osd.c
@@ -143,6 +143,10 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width
osd->next = this->osds;
this->osds = osd;
+ osd->video_window_x = 0;
+ osd->video_window_y = 0;
+ osd->video_window_width = 0;
+ osd->video_window_height = 0;
osd->extent_width = 0;
osd->extent_height = 0;
osd->width = width;
@@ -186,6 +190,19 @@ static void osd_set_extent (osd_object_t *osd, int extent_width, int extent_heig
osd->extent_height = extent_height;
}
+/*
+ * osd video window defines an area withing osd extent where the
+ * video shall be scaled to while an osd is displayed on screen.
+ * both width and height must be > 0 to take effect.
+ */
+static void osd_set_video_window (osd_object_t *osd, int window_x, int window_y, int window_width, int window_height) {
+
+ osd->video_window_x = window_x;
+ osd->video_window_y = window_y;
+ osd->video_window_width = window_width;
+ osd->video_window_height = window_height;
+}
+
/*
@@ -254,6 +271,11 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) {
this->event.object.overlay->width = osd->x2 - osd->x1;
this->event.object.overlay->height = osd->y2 - osd->y1;
+ this->event.object.overlay->video_window_x = osd->video_window_x;
+ this->event.object.overlay->video_window_y = osd->video_window_y;
+ this->event.object.overlay->video_window_width = osd->video_window_width;
+ this->event.object.overlay->video_window_height = osd->video_window_height;
+
this->event.object.overlay->extent_width = osd->extent_width;
this->event.object.overlay->extent_height = osd->extent_height;
@@ -1627,6 +1649,9 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) {
if (vo_capabilities & VO_CAP_ARGB_LAYER_OVERLAY)
capabilities |= XINE_OSD_CAP_ARGB_LAYER;
+ if (vo_capabilities & VO_CAP_VIDEO_WINDOW_OVERLAY)
+ capabilities |= XINE_OSD_CAP_VIDEO_WINDOW;
+
return capabilities;
}
@@ -1691,6 +1716,7 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) {
this->show_unscaled = osd_show_unscaled;
this->get_capabilities = osd_get_capabilities;
this->set_extent = osd_set_extent;
+ this->set_video_window = osd_set_video_window;
return this;
}
diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h
index 36e6fc0ae..be5e2218c 100644
--- a/src/xine-engine/osd.h
+++ b/src/xine-engine/osd.h
@@ -50,6 +50,10 @@ struct osd_object_s {
int area_touched; /* work area was used for painting */
int display_x,display_y; /* where to display it in screen */
+ /* video output area within osd extent */
+ int video_window_x, video_window_y;
+ int video_window_width, video_window_height;
+
/* extent of reference coordinate system */
int extent_width, extent_height;
@@ -243,6 +247,13 @@ struct osd_renderer_s {
void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer,
int dirty_x, int dirty_y, int dirty_width, int dirty_height);
+ /*
+ * osd video window defines an area withing osd extent where the
+ * video shall be scaled to while an osd is displayed on screen.
+ * both width and height must be > 0 to take effect.
+ */
+ void (*set_video_window) (osd_object_t *osd,
+ int window_x, int window_y, int window_width, int window_height);
/* private stuff */
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 171190bc5..152f0878a 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -437,6 +437,20 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
int frames_to_skip;
int duration;
+ /*if (1) {
+ static int64_t pts = 0;
+ fprintf(stderr, "img->pts: %lld, pts: %lld, img->duration: %d", img->pts, pts, img->duration);
+ if (img->pts) {
+ if (pts != img->pts)
+ fprintf(stderr, " ERROR: %12ld", img->pts - pts);
+ pts = img->pts + img->duration;
+ }
+ else {
+ pts += img->duration;
+ }
+ fprintf(stderr, "\n");
+ }*/
+
/* handle anonymous streams like NULL for easy checking */
if (stream == XINE_ANON_STREAM) stream = NULL;
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index bbf0dcc35..480c1c8f2 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.h
@@ -299,6 +299,7 @@ struct xine_video_port_s {
#define VO_CAP_VDPAU_VC1 0x00000200 /* driver can use VDPAU for mpeg1/2 */
#define VO_CAP_CUSTOM_EXTENT_OVERLAY 0x01000000 /* driver can blend custom extent overlay to output extent */
#define VO_CAP_ARGB_LAYER_OVERLAY 0x02000000 /* driver supports true color overlay */
+#define VO_CAP_VIDEO_WINDOW_OVERLAY 0x04000000 /* driver can scale video to an area within overlay */
/*
@@ -429,6 +430,12 @@ struct vo_overlay_s {
int width; /* width of subpicture area */
int height; /* height of subpicture area */
+ /* area within osd extent to scale video to */
+ int video_window_x;
+ int video_window_y;
+ int video_window_width;
+ int video_window_height;
+
/* extent of reference coordinate system */
int extent_width;
int extent_height;
diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c
index 20101b436..8301414cd 100644
--- a/src/xine-engine/xine_interface.c
+++ b/src/xine-engine/xine_interface.c
@@ -868,6 +868,10 @@ void xine_osd_set_extent(xine_osd_t *this, int extent_width, int extent_height)
this->osd.renderer->set_extent(&this->osd, extent_width, extent_height);
}
+void xine_osd_set_video_window(xine_osd_t *this, int window_x, int window_y, int window_width, int window_height) {
+ this->osd.renderer->set_video_window(&this->osd, window_x, window_y, window_width, window_height);
+}
+
const char *const *xine_post_list_inputs(xine_post_t *this_gen) {
post_plugin_t *this = (post_plugin_t *)this_gen;