mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 17:18:15 +00:00
Some more refactoring, handle exotic DirectFB row stride.
Original commit message from CVS: 2005-12-18 Julien MOUTTE <julien@moutte.net> * docs/plugins/gst-plugins-bad-plugins-decl.txt: * ext/directfb/dfbvideosink.c: (gst_dfbvideosink_surface_create), (gst_dfbvideosink_event_thread), (gst_dfbvideosink_enum_devices), (gst_dfbvideosink_setup), (gst_dfbvideosink_cleanup), (gst_dfbvideosink_can_blit_from_format), (gst_dfbvideosink_getcaps), (gst_dfbvideosink_setcaps), (gst_dfbvideosink_show_frame), (gst_dfbvideosink_buffer_alloc), (gst_dfbsurface_finalize), (gst_dfbvideosink_navigation_send_event), (gst_dfbvideosink_update_colorbalance), (gst_dfbvideosink_set_property), (gst_dfbvideosink_init): Some more refactoring, handle exotic DirectFB row stride.
This commit is contained in:
parent
998d0fc976
commit
0ec8bf9972
3 changed files with 135 additions and 60 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2005-12-18 Julien MOUTTE <julien@moutte.net>
|
||||
|
||||
* docs/plugins/gst-plugins-bad-plugins-decl.txt:
|
||||
* ext/directfb/dfbvideosink.c: (gst_dfbvideosink_surface_create),
|
||||
(gst_dfbvideosink_event_thread), (gst_dfbvideosink_enum_devices),
|
||||
(gst_dfbvideosink_setup), (gst_dfbvideosink_cleanup),
|
||||
(gst_dfbvideosink_can_blit_from_format),
|
||||
(gst_dfbvideosink_getcaps), (gst_dfbvideosink_setcaps),
|
||||
(gst_dfbvideosink_show_frame), (gst_dfbvideosink_buffer_alloc),
|
||||
(gst_dfbsurface_finalize),
|
||||
(gst_dfbvideosink_navigation_send_event),
|
||||
(gst_dfbvideosink_update_colorbalance),
|
||||
(gst_dfbvideosink_set_property), (gst_dfbvideosink_init): Some
|
||||
more refactoring, handle exotic DirectFB row stride.
|
||||
|
||||
2005-12-18 Julien MOUTTE <julien@moutte.net>
|
||||
|
||||
* docs/plugins/gst-plugins-bad-plugins-decl.txt:
|
||||
|
|
|
@ -48,6 +48,7 @@ struct _GstDfbSurface {
|
|||
|
||||
gint width;
|
||||
gint height;
|
||||
gint pitch;
|
||||
|
||||
gboolean locked;
|
||||
|
||||
|
|
|
@ -140,6 +140,8 @@ static DFBSurfacePixelFormat gst_dfbvideosink_get_format_from_caps (GstCaps *
|
|||
caps);
|
||||
static void gst_dfbvideosink_update_colorbalance (GstDfbVideoSink *
|
||||
dfbvideosink);
|
||||
static void gst_dfbvideosink_surface_destroy (GstDfbVideoSink * dfbvideosink,
|
||||
GstDfbSurface * surface);
|
||||
|
||||
static GstVideoSinkClass *parent_class = NULL;
|
||||
|
||||
|
@ -203,11 +205,15 @@ gst_dfbvideosink_surface_create (GstDfbVideoSink * dfbvideosink, GstCaps * caps,
|
|||
DFBSurfaceDescription s_dsc;
|
||||
gpointer data;
|
||||
gint pitch;
|
||||
gboolean succeeded = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_DFBVIDEOSINK (dfbvideosink), NULL);
|
||||
|
||||
surface = (GstDfbSurface *) gst_mini_object_new (GST_TYPE_DFBSURFACE);
|
||||
|
||||
/* Keep a ref to our sink */
|
||||
surface->dfbvideosink = gst_object_ref (dfbvideosink);
|
||||
/* Surface is not locked yet */
|
||||
surface->locked = FALSE;
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
@ -216,55 +222,91 @@ gst_dfbvideosink_surface_create (GstDfbVideoSink * dfbvideosink, GstCaps * caps,
|
|||
!gst_structure_get_int (structure, "height", &surface->height)) {
|
||||
GST_WARNING_OBJECT (dfbvideosink, "failed getting geometry from caps %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Pixel format from caps */
|
||||
surface->pixel_format = gst_dfbvideosink_get_format_from_caps (caps);
|
||||
|
||||
if (dfbvideosink->dfb) {
|
||||
/* Creating an internal surface which will be used as GstBuffer, we used
|
||||
the detected pixel format and video dimensions */
|
||||
|
||||
s_dsc.flags =
|
||||
DSDESC_PIXELFORMAT | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS;
|
||||
|
||||
s_dsc.pixelformat = surface->pixel_format;
|
||||
s_dsc.width = surface->width;
|
||||
s_dsc.height = surface->height;
|
||||
s_dsc.caps = DSCAPS_VIDEOONLY;
|
||||
|
||||
ret = dfbvideosink->dfb->CreateSurface (dfbvideosink->dfb, &s_dsc,
|
||||
&surface->surface);
|
||||
if (ret != DFB_OK) {
|
||||
GST_WARNING_OBJECT (dfbvideosink, "failed creating a DirectFB surface");
|
||||
gst_object_unref (surface);
|
||||
surface = NULL;
|
||||
goto beach;
|
||||
}
|
||||
|
||||
/* Clearing surface */
|
||||
surface->surface->Clear (surface->surface, 0x00, 0x00, 0x00, 0xFF);
|
||||
|
||||
/* Locking the surface to acquire the memory pointer */
|
||||
surface->surface->Lock (surface->surface, DSLF_WRITE, &data, &pitch);
|
||||
surface->locked = TRUE;
|
||||
GST_BUFFER_DATA (surface) = data;
|
||||
GST_BUFFER_SIZE (surface) = pitch * surface->height;
|
||||
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "creating a %dx%d surface with %s pixel "
|
||||
"format, line pitch %d", surface->width, surface->height,
|
||||
gst_dfbvideosink_get_format_name (surface->pixel_format), pitch);
|
||||
} else {
|
||||
GST_BUFFER (surface)->malloc_data = g_malloc (size);
|
||||
GST_BUFFER_DATA (surface) = GST_BUFFER (surface)->malloc_data;
|
||||
GST_BUFFER_SIZE (surface) = size;
|
||||
surface->surface = NULL;
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "allocating a buffer of %d bytes", size);
|
||||
if (surface->pixel_format == DSPF_UNKNOWN) {
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Keep a ref to our sink */
|
||||
surface->dfbvideosink = gst_object_ref (dfbvideosink);
|
||||
if (!dfbvideosink->dfb) {
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "no DirectFB context to create a surface");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Creating an internal surface which will be used as GstBuffer, we used
|
||||
the detected pixel format and video dimensions */
|
||||
|
||||
s_dsc.flags =
|
||||
DSDESC_PIXELFORMAT | DSDESC_WIDTH | DSDESC_HEIGHT /*| DSDESC_CAPS */ ;
|
||||
|
||||
s_dsc.pixelformat = surface->pixel_format;
|
||||
s_dsc.width = surface->width;
|
||||
s_dsc.height = surface->height;
|
||||
/*s_dsc.caps = DSCAPS_VIDEOONLY; */
|
||||
|
||||
ret = dfbvideosink->dfb->CreateSurface (dfbvideosink->dfb, &s_dsc,
|
||||
&surface->surface);
|
||||
if (ret != DFB_OK) {
|
||||
GST_WARNING_OBJECT (dfbvideosink, "failed creating a DirectFB surface");
|
||||
surface->surface = NULL;
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Clearing surface */
|
||||
surface->surface->Clear (surface->surface, 0x00, 0x00, 0x00, 0xFF);
|
||||
|
||||
/* Locking the surface to acquire the memory pointer */
|
||||
surface->surface->Lock (surface->surface, DSLF_WRITE, &data, &pitch);
|
||||
surface->locked = TRUE;
|
||||
GST_BUFFER_DATA (surface) = data;
|
||||
GST_BUFFER_SIZE (surface) = pitch * surface->height;
|
||||
|
||||
/* Be carefull here. If size is different from the surface size
|
||||
(pitch * height), we can't use that surface through buffer alloc system
|
||||
or we are going to run into serious stride issues */
|
||||
if (GST_BUFFER_SIZE (surface) != size) {
|
||||
GST_WARNING_OBJECT (dfbvideosink, "DirectFB surface size (%dx%d=%d) "
|
||||
"differs from GStreamer requested size %d", pitch, surface->height,
|
||||
GST_BUFFER_SIZE (surface), size);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "creating a %dx%d surface (%p) with %s "
|
||||
"pixel format, line pitch %d", surface->width, surface->height, surface,
|
||||
gst_dfbvideosink_get_format_name (surface->pixel_format), pitch);
|
||||
|
||||
succeeded = TRUE;
|
||||
|
||||
goto beach;
|
||||
|
||||
fallback:
|
||||
|
||||
/* We allocate a standard buffer ourselves to store it in our buffer pool,
|
||||
this is an optimisation for memory allocation */
|
||||
GST_BUFFER (surface)->malloc_data = g_malloc (size);
|
||||
GST_BUFFER_DATA (surface) = GST_BUFFER (surface)->malloc_data;
|
||||
GST_BUFFER_SIZE (surface) = size;
|
||||
if (surface->surface) {
|
||||
if (surface->locked) {
|
||||
surface->surface->Unlock (surface->surface);
|
||||
surface->locked = FALSE;
|
||||
}
|
||||
surface->surface->Release (surface->surface);
|
||||
surface->surface = NULL;
|
||||
}
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "allocating a buffer (%p) of %d bytes",
|
||||
surface, size);
|
||||
|
||||
succeeded = TRUE;
|
||||
|
||||
beach:
|
||||
if (!succeeded) {
|
||||
gst_dfbvideosink_surface_destroy (dfbvideosink, surface);
|
||||
surface = NULL;
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
@ -560,7 +602,7 @@ gst_dfbvideosink_setup (GstDfbVideoSink * dfbvideosink)
|
|||
goto beach;
|
||||
}
|
||||
|
||||
/* Get Hardwared capabilities */
|
||||
/* Get Hardware capabilities */
|
||||
ret = dfbvideosink->dfb->GetDeviceDescription (dfbvideosink->dfb,
|
||||
&hw_caps);
|
||||
|
||||
|
@ -1461,6 +1503,7 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
DFBResult res;
|
||||
GstVideoRectangle dst, src, result;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gboolean mem_cpy = TRUE;
|
||||
|
||||
dfbvideosink = GST_DFBVIDEOSINK (bsink);
|
||||
|
||||
|
@ -1469,9 +1512,27 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
goto beach;
|
||||
}
|
||||
|
||||
/* If we are rendering from a buffer we did not allocate or to an external
|
||||
* surface, we will memcpy data */
|
||||
if (!GST_IS_DFBSURFACE (buf) || dfbvideosink->ext_surface) {
|
||||
/* Is that a buffer we allocated ourselves ? */
|
||||
if (GST_IS_DFBSURFACE (buf)) {
|
||||
GstDfbSurface *tmp_surface = GST_DFBSURFACE (buf);
|
||||
|
||||
/* Does it have a surface ? */
|
||||
if (tmp_surface->surface) {
|
||||
mem_cpy = FALSE;
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "we have a buffer (%p) we allocated "
|
||||
"ourselves and it has a surface, no memcpy then", buf);
|
||||
} else {
|
||||
/* No surface, that's a malloc */
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "we have a buffer (%p) we allocated "
|
||||
"ourselves but it does not hold a surface", buf);
|
||||
}
|
||||
} else {
|
||||
/* Not our baby */
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "we have a buffer (%p) we did not allocate",
|
||||
buf);
|
||||
}
|
||||
|
||||
if (mem_cpy) {
|
||||
IDirectFBSurface *dest = NULL, *surface = NULL;
|
||||
gpointer data;
|
||||
gint dest_pitch, src_pitch, line;
|
||||
|
@ -1492,6 +1553,7 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
"(vsync %d)", dfbvideosink->vsync);
|
||||
}
|
||||
|
||||
/* Get the video frame geometry from the buffer caps */
|
||||
structure = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0);
|
||||
if (structure) {
|
||||
gst_structure_get_int (structure, "width", &src.w);
|
||||
|
@ -1547,7 +1609,7 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
res = surface->Flip (surface, NULL, DSFLIP_NONE);
|
||||
}
|
||||
}
|
||||
} else if (dfbvideosink->primary) {
|
||||
} else {
|
||||
/* Else we will [Stretch]Blit to our primary */
|
||||
GstDfbSurface *surface = GST_DFBSURFACE (buf);
|
||||
|
||||
|
@ -1560,8 +1622,10 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
dfbvideosink->primary->GetSize (dfbvideosink->primary, &dst.w, &dst.h);
|
||||
|
||||
/* Unlocking surface before blit */
|
||||
surface->surface->Unlock (surface->surface);
|
||||
surface->locked = FALSE;
|
||||
if (surface->locked) {
|
||||
surface->surface->Unlock (surface->surface);
|
||||
surface->locked = FALSE;
|
||||
}
|
||||
|
||||
gst_video_sink_center_rect (src, dst, &result, dfbvideosink->hw_scaling);
|
||||
|
||||
|
@ -1591,11 +1655,6 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
dfbvideosink->primary->Flip (dfbvideosink->primary, NULL, DSFLIP_NONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GST_WARNING_OBJECT (dfbvideosink, "no primary, no external surface "
|
||||
"what's going on ?");
|
||||
ret = GST_FLOW_UNEXPECTED;
|
||||
goto beach;
|
||||
}
|
||||
|
||||
beach:
|
||||
|
@ -1740,6 +1799,7 @@ alloc:
|
|||
}
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (dfbvideosink->pool_lock);
|
||||
|
||||
/* We haven't found anything, creating a new one */
|
||||
if (!surface) {
|
||||
|
@ -1758,12 +1818,11 @@ alloc:
|
|||
gst_buffer_set_caps (GST_BUFFER (surface), caps);
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (dfbvideosink->pool_lock);
|
||||
|
||||
gst_caps_unref (desired_caps);
|
||||
|
||||
*buf = GST_BUFFER (surface);
|
||||
|
||||
gst_caps_unref (desired_caps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1786,13 +1845,13 @@ gst_dfbsurface_finalize (GstDfbSurface * surface)
|
|||
if ((surface->width != dfbvideosink->video_width) ||
|
||||
(surface->height != dfbvideosink->video_height) ||
|
||||
(surface->pixel_format != dfbvideosink->pixel_format)) {
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "destroy image as its size changed %dx%d "
|
||||
"vs current %dx%d", surface->width, surface->height,
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "destroy surface %p as its size changed "
|
||||
"%dx%d vs current %dx%d", surface, surface->width, surface->height,
|
||||
dfbvideosink->video_width, dfbvideosink->video_height);
|
||||
gst_dfbvideosink_surface_destroy (dfbvideosink, surface);
|
||||
} else {
|
||||
/* In that case we can reuse the image and add it to our image pool. */
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "recycling image in pool");
|
||||
GST_DEBUG_OBJECT (dfbvideosink, "recycling surface %p in pool", surface);
|
||||
/* need to increment the refcount again to recycle */
|
||||
gst_buffer_ref (GST_BUFFER (surface));
|
||||
g_mutex_lock (dfbvideosink->pool_lock);
|
||||
|
|
Loading…
Reference in a new issue