From 92d89235ad1e8a413422947b92b957a5453950ea Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 27 Dec 2008 17:20:17 +0000 Subject: Initial support for ARGB overlay. --- include/xine.h.in | 7 +++++ src/video_out/video_out_vdpau.c | 65 +++++++++++++++++++++++++++++++++++----- src/xine-engine/osd.c | 15 ++++++++++ src/xine-engine/osd.h | 13 ++++++++ src/xine-engine/video_out.h | 2 ++ src/xine-engine/xine_interface.c | 5 ++++ 6 files changed, 100 insertions(+), 7 deletions(-) diff --git a/include/xine.h.in b/include/xine.h.in index ced7a8757..79db9024e 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -2200,6 +2200,13 @@ void xine_osd_get_palette (xine_osd_t *self, uint32_t *color, void xine_osd_set_palette (xine_osd_t *self, const uint32_t *const color, const uint8_t *const trans ) XINE_PROTECTED; + +/* + * set an argb buffer to be blended into video + * this is currently only supported with vdpau + */ +void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer) XINE_PROTECTED; + /* * close osd rendering engine * loaded fonts are unloaded diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index ed68b5c5f..190e671b3 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -154,6 +154,11 @@ typedef struct { uint32_t overlay_unscaled_height; int has_unscaled; + VdpOutputSurface argb_overlay; + uint32_t argb_overlay_width; + uint32_t argb_overlay_height; + int has_argb_overlay; + VdpVideoSurface soft_surface; uint32_t soft_surface_width; uint32_t soft_surface_height; @@ -212,7 +217,35 @@ static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *over } } +static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + if(overlay->argb_buffer == NULL) + return 0; + + if ( (this->argb_overlay_width != overlay->width ) || (this->argb_overlay_height != overlay->height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) { + if (this->argb_overlay != VDP_INVALID_HANDLE) { + vdp_output_surface_destroy( this->argb_overlay ); + } + VdpStatus st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, &this->argb_overlay ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + } + this->argb_overlay_width = overlay->width; + this->argb_overlay_height = overlay->height; + } + + uint32_t pitch = this->argb_overlay_width*4; + VdpRect dest = { 0, 0, this->argb_overlay_width, this->argb_overlay_height }; + VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(overlay->argb_buffer), &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) ); + } else + this->has_argb_overlay = 1; + return 1; +} static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) { @@ -316,6 +349,9 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v if ( vdpau_process_ovl( this, overlay ) ) ++this->ovl_changed; } + + if(overlay->argb_buffer) + vdpau_process_argb_ovl( this, overlay ); } @@ -667,9 +703,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 2; - void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS, VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; + int num_layers = 3; + float noise_reduction_level = 1.0; + void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers, &noise_reduction_level }; vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; @@ -700,7 +737,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); uint32_t layer_count; - VdpLayer layer[2]; + VdpLayer layer[3]; VdpRect layersrc, unscaledsrc; if ( this->has_overlay ) { //printf("vdpau_display_frame: overlay should be visible !\n"); @@ -715,6 +752,15 @@ 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 }; + if( this->has_argb_overlay ) { + layer_count++; + layer[layer_count-1].destination_rect = &vid_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; + } + if ( frame->vo_frame.duration>2500 && !frame->vo_frame.progressive_frame && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; @@ -1069,6 +1115,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->ovl_changed = 0; this->has_overlay = 0; + this->argb_overlay = VDP_INVALID_HANDLE; + this->argb_overlay_width = this->argb_overlay_height = 0; + this->has_argb_overlay = 0; + /* overlay converter */ this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); this->ovl_yuv2rgb = this->yuv2rgb_factory->create_converter( this->yuv2rgb_factory ); @@ -1241,9 +1291,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 2; - void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS, VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; + int num_layers = 3; + float noise_reduction_level = 1.0; + void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers, &noise_reduction_level }; st = vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 05acd4779..0bc1574ca 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -152,6 +152,8 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width osd->x2 = 0; osd->y2 = 0; + osd->argb_buffer = NULL; + memcpy(osd->color, textpalettes_color[0], sizeof(textpalettes_color[0])); memcpy(osd->trans, textpalettes_trans[0], sizeof(textpalettes_trans[0])); @@ -228,6 +230,9 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { this->event.object.handle = osd->handle; memset( this->event.object.overlay, 0, sizeof(*this->event.object.overlay) ); + + this->event.object.overlay->argb_buffer = osd->argb_buffer; + this->event.object.overlay->unscaled = unscaled; this->event.object.overlay->x = osd->display_x + osd->x1; this->event.object.overlay->y = osd->display_y + osd->y1; @@ -1537,6 +1542,15 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap, } } +static void osd_set_argb_buffer(osd_object_t *osd, uint32_t *argb_buffer) +{ + osd->argb_buffer = argb_buffer; + osd->x2 = osd->width; + osd->x1 = 0; + osd->y2 = osd->height; + osd->y1 = 0; +} + static uint32_t osd_get_capabilities (osd_object_t *osd) { osd_renderer_t *this = osd->renderer; @@ -1612,6 +1626,7 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { this->get_text_size = osd_get_text_size; this->close = osd_renderer_close; this->draw_bitmap = osd_draw_bitmap; + this->set_argb_buffer = osd_set_argb_buffer; this->show_unscaled = osd_show_unscaled; this->get_capabilities = osd_get_capabilities; diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index 70193a2ea..ed3118a05 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -65,6 +65,13 @@ struct osd_object_s { osd_font_t *font; osd_ft2context_t *ft2; + + + /* this holds an optional ARGB overlay, which + * is only be used by supported video_out modules. + * right now this is only vdpau */ + uint32_t *argb_buffer; + }; /* this one is public */ @@ -211,6 +218,12 @@ struct osd_renderer_s { */ uint32_t (*get_capabilities) (osd_object_t *osd); + /* + * set a buffer to an argb buffer + */ + void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer); + + /* private stuff */ pthread_mutex_t osd_mutex; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 17ddd660b..7fa34ac8b 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -419,6 +419,8 @@ struct vo_overlay_s { int hili_rgb_clut; /* true if clut was converted to rgb */ int unscaled; /* true if it should be blended unscaled */ + + uint32_t *argb_buffer; }; diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index d1d5a18d9..1f6175a06 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -855,6 +855,11 @@ void xine_osd_draw_bitmap(xine_osd_t *this, uint8_t *bitmap, this->osd.renderer->draw_bitmap(&this->osd, bitmap, x1, y1, width, height, palette_map); } +void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer) { + this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer); +} + + const char *const *xine_post_list_inputs(xine_post_t *this_gen) { post_plugin_t *this = (post_plugin_t *)this_gen; return this->input_ids; -- cgit v1.2.3