GNOME Bugzilla – Bug 503743
dfbvideosink: does not handle external surface correctly
Last modified: 2018-01-25 12:46:02 UTC
Hi, I'm using gstreamer and DirectFB to create a media player on a ARM11 board. now I found if i create a surface in my application and pass this surface to dfbvideosink, it's very slow on my board.and if i let dfbvideosink to create the surface itself, it's faster. then i checked the source code in dfbvideosink.c, and found those: 1. in gst_dfbvideosink_setup() it will not get dirctFB initialized if it's a external surface. just copy some configuation from the ext surface, 2, in gst_dfbvideosink_surface_create() , it will not create any surface is DirectFB is not initialized, 3, in gst_dfbvideosink_show_frame(), it will check the buffer has surface or not to decide use Blit or mem_cpy. since using the external surface do not cause a directfb initialized and then no surface created in buffer. mem_cpy is chosen. this cause the video playback slower. I think dfbvideosink should check the external surface support blit or not, if yes,it should use blit to accelarate. could you check and fix this? Best Regards Joyious
Hi, I just do a simple change,hope this info can help you. here are the diff results: 100,101d99 < #define HHM_TEST 780,858d773 < #ifdef HHM_TEST < < if (!dfbvideosink->dfb) { < DFBGraphicsDeviceDescription hw_caps; < < GST_DEBUG_OBJECT (dfbvideosink, "initializing DirectFB"); < < ret = DirectFBInit (0, NULL); < < if (ret != DFB_OK) { < GST_WARNING_OBJECT (dfbvideosink, "DirectFB initialization failed"); < goto beach; < } < < ret = DirectFBCreate (&(dfbvideosink->dfb)); < < if (ret != DFB_OK) { < GST_WARNING_OBJECT (dfbvideosink, "failed creating the DirectFB " < "main object"); < goto beach; < } < < /* Get Hardware capabilities */ < ret = dfbvideosink->dfb->GetDeviceDescription (dfbvideosink->dfb, < &hw_caps); < < if (ret != DFB_OK) { < GST_WARNING_OBJECT (dfbvideosink, "failed grabbing the hardware " < "capabilities"); < goto beach; < } < < GST_DEBUG_OBJECT (dfbvideosink, "video card %s from vendor %s detected " < "with %d bytes of video memory", hw_caps.name, hw_caps.vendor, < hw_caps.video_memory); < < if (hw_caps.acceleration_mask & DFXL_BLIT) { < GST_DEBUG_OBJECT (dfbvideosink, "Blit is accelerated"); < } < if (hw_caps.acceleration_mask & DFXL_STRETCHBLIT) { < GST_DEBUG_OBJECT (dfbvideosink, "StretchBlit is accelerated"); < dfbvideosink->hw_scaling = TRUE; < } else { < GST_DEBUG_OBJECT (dfbvideosink, "StretchBlit is not accelerated"); < dfbvideosink->hw_scaling = FALSE; < } < < dfbvideosink->layer_id = -1; < < /* Inspect all the Display layers */ < dfbvideosink->dfb->EnumDisplayLayers (dfbvideosink->dfb, < gst_dfbvideosink_enum_layers, dfbvideosink); < /* Inspect all Video modes */ < dfbvideosink->dfb->EnumVideoModes (dfbvideosink->dfb, < gst_dfbvideosink_enum_vmodes, dfbvideosink); < < < if (!dfbvideosink->layer) { < GList *channels_list = NULL; < DFBDisplayLayerDescription dl_desc; < < /* Get the best Display Layer */ < ret = dfbvideosink->dfb->GetDisplayLayer (dfbvideosink->dfb, < dfbvideosink->layer_id, &dfbvideosink->layer); < if (ret != DFB_OK) { < GST_WARNING_OBJECT (dfbvideosink, "failed getting display layer"); < goto beach; < } < < ret = dfbvideosink->layer->SetCooperativeLevel (dfbvideosink->layer, < DFSCL_NORMAL); < < if (ret != DFB_OK) { < GST_WARNING_OBJECT (dfbvideosink, "failed setting display layer to " < "fullscreen mode"); < goto beach; < } < < dfbvideosink->layer->GetDescription (dfbvideosink->layer, &dl_desc); 860,943d774 < /* Check that this layer is able to do colorbalance settings */ < if (dl_desc.caps & DLCAPS_BRIGHTNESS) { < channels_list = g_list_append (channels_list, "BRIGHTNESS"); < } < if (dl_desc.caps & DLCAPS_CONTRAST) { < channels_list = g_list_append (channels_list, "CONTRAST"); < } < if (dl_desc.caps & DLCAPS_HUE) { < channels_list = g_list_append (channels_list, "HUE"); < } < if (dl_desc.caps & DLCAPS_SATURATION) { < channels_list = g_list_append (channels_list, "SATURATION"); < } < < if (channels_list) { < GList *walk = channels_list; < < /* Generate Color balance channel list */ < while (walk) { < GstColorBalanceChannel *channel = NULL; < < GST_DEBUG_OBJECT (dfbvideosink, "adding %s as a colorbalance channel", < walk->data); < < channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL); < channel->label = g_strdup (walk->data); < channel->min_value = 0x0000; < channel->max_value = 0xFFFF; < < dfbvideosink->cb_channels = g_list_append (dfbvideosink->cb_channels, < channel); < < walk = g_list_next (walk); < } < < /* If the colorbalance settings have not been touched we get current < values as defaults and update our internal variables */ < if (!dfbvideosink->cb_changed) { < DFBColorAdjustment cb_adjust; < < ret = dfbvideosink->layer->GetColorAdjustment (dfbvideosink->layer, < &cb_adjust); < < if (ret != DFB_OK) { < GST_WARNING_OBJECT (dfbvideosink, "failed when getting color " < "adjustment from layer"); < } < < if (cb_adjust.flags & DCAF_BRIGHTNESS) { < dfbvideosink->brightness = cb_adjust.brightness; < } else { < dfbvideosink->brightness = 0x8000; < } < if (cb_adjust.flags & DCAF_CONTRAST) { < dfbvideosink->contrast = cb_adjust.contrast; < } else { < dfbvideosink->contrast = 0x8000; < } < if (cb_adjust.flags & DCAF_HUE) { < dfbvideosink->hue = cb_adjust.hue; < } else { < dfbvideosink->hue = 0x8000; < } < if (cb_adjust.flags & DCAF_SATURATION) { < dfbvideosink->saturation = cb_adjust.saturation; < } else { < dfbvideosink->saturation = 0x8000; < } < GST_DEBUG_OBJECT (dfbvideosink, "brightness %d, contrast %d, " < "hue %d, saturation %d", dfbvideosink->brightness, < dfbvideosink->contrast, dfbvideosink->hue, < dfbvideosink->saturation); < } < < g_list_free (channels_list); < < gst_dfbvideosink_update_colorbalance (dfbvideosink); < } < < dfbvideosink->layer->SetBackgroundColor (dfbvideosink->layer, < 0x00, 0x00, 0x00, 0xFF); < } < } < #endif 1809,1813d1639 < #ifdef HHM_TEST < if (dfbvideosink ->ext_surface) < { < GST_DEBUG_OBJECT (dfbvideosink, "blitting to a External surface (vsync %d)", < dfbvideosink->vsync); 1815,1858d1640 < src.w = GST_VIDEO_SINK_WIDTH (dfbvideosink); < src.h = GST_VIDEO_SINK_HEIGHT (dfbvideosink); < < dfbvideosink->ext_surface->GetSize (dfbvideosink->ext_surface, &dst.w, &dst.h); < < /* Unlocking surface before blit */ < if (surface->locked) { < surface->surface->Unlock (surface->surface); < surface->locked = FALSE; < } < < gst_video_sink_center_rect (src, dst, &result, dfbvideosink->hw_scaling); < < /* If we are not using Flip we wait for VSYNC before blit */ < if (!dfbvideosink->backbuffer && dfbvideosink->vsync) { < dfbvideosink->layer->WaitForSync (dfbvideosink->layer); < } < < dfbvideosink->ext_surface->Clear(dfbvideosink->ext_surface, 0x00,0x00,0x00,0x00); < < if (dfbvideosink->hw_scaling) { < dfbvideosink->ext_surface->StretchBlit (dfbvideosink->ext_surface, < surface->surface, NULL, (DFBRectangle *) & result); < } else { < DFBRectangle clip; < < clip.x = clip.y = 0; < clip.w = result.w; < clip.h = result.h; < dfbvideosink->ext_surface->Blit (dfbvideosink->ext_surface, surface->surface, < &clip, result.x, result.y); < } < < if (dfbvideosink->backbuffer) { < if (dfbvideosink->vsync) { < dfbvideosink->ext_surface->Flip (dfbvideosink->ext_surface, NULL, < DSFLIP_ONSYNC); < } else { < dfbvideosink->ext_surface->Flip (dfbvideosink->ext_surface, NULL, DSFLIP_NONE); < } < } < goto beach; < } < #endif
Problem seems to be, that you can't create another surface with only the surface known. you need to know the IDirectFB context somehow but this would probably cause threading problems. I'll try to find a good solution though...
directfb has been ported to 1.x. Huimin, Sebastian, Does this bug still apply in 1.x ?
Closing this bug report as no further information has been provided. Please feel free to reopen this bug report if you can provide the information that was asked for in a previous comment. Thanks!