summaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/directfb/Makefile.am8
-rw-r--r--ext/directfb/dfbvideosink.c133
2 files changed, 119 insertions, 22 deletions
diff --git a/ext/directfb/Makefile.am b/ext/directfb/Makefile.am
index 47f98984..eb90c28b 100644
--- a/ext/directfb/Makefile.am
+++ b/ext/directfb/Makefile.am
@@ -4,11 +4,11 @@ plugin_LTLIBRARIES = libgstdfbvideosink.la
libgstdfbvideosink_la_SOURCES = dfbvideosink.c
libgstdfbvideosink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
- $(DIRECTFB_CFLAGS)
+ $(DIRECTFB_CFLAGS) $(LIBOIL_CFLAGS)
libgstdfbvideosink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
- -lgstvideo-$(GST_MAJORMINOR) \
- -lgstinterfaces-$(GST_MAJORMINOR) \
- $(DIRECTFB_LIBS)
+ -lgstvideo-$(GST_MAJORMINOR) \
+ -lgstinterfaces-$(GST_MAJORMINOR) \
+ $(DIRECTFB_LIBS) $(LIBOIL_LIBS)
libgstdfbvideosink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = dfbvideosink.h
diff --git a/ext/directfb/dfbvideosink.c b/ext/directfb/dfbvideosink.c
index 8e69ca02..27902136 100644
--- a/ext/directfb/dfbvideosink.c
+++ b/ext/directfb/dfbvideosink.c
@@ -27,6 +27,9 @@
/* Object header */
#include "dfbvideosink.h"
+#include <string.h>
+#include <liboil/liboil.h>
+
/* Debugging category */
GST_DEBUG_CATEGORY (dfbvideosink_debug);
#define GST_CAT_DEFAULT dfbvideosink_debug
@@ -1138,6 +1141,8 @@ static GstFlowReturn
gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
{
GstDfbVideoSink *dfbvideosink;
+ DFBResult res;
+ DFBRectangle dst, src, result;
GstFlowReturn ret = GST_FLOW_OK;
dfbvideosink = GST_DFBVIDEOSINK (bsink);
@@ -1151,43 +1156,129 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
if (GST_IS_DFBSURFACE (buf)) {
GstDfbSurface *surface = GST_DFBSURFACE (buf);
- if (dfbvideosink->ext_surface) { /* Blit to an external surface */
- /* FIXME : Check return values */
- dfbvideosink->ext_surface->Blit (dfbvideosink->ext_surface,
- surface->surface, NULL, 0, 0);
+ /* Blit to the fullscreen primary */
+ GST_DEBUG ("show frame with a buffer we allocated");
+
+ src.w = surface->width;
+ src.h = surface->height;
+
+ dfbvideosink->primary->GetSize (dfbvideosink->primary, &dst.w, &dst.h);
+
+ /* Unlocking surface before blit */
+ surface->surface->Unlock (surface->surface);
+
+ gst_dfbvideosink_center_rect (src, dst, &result, dfbvideosink->hw_scaling);
+
+ if (dfbvideosink->hw_scaling) {
+ dfbvideosink->primary->StretchBlit (dfbvideosink->primary,
+ surface->surface, NULL, &result);
+ } else {
+ dfbvideosink->primary->Blit (dfbvideosink->primary, surface->surface,
+ NULL, result.x, result.y);
+ }
+
+ if (dfbvideosink->backbuffer) {
+ dfbvideosink->primary->Flip (dfbvideosink->primary, NULL, 0);
+ }
+ } else {
+ if (dfbvideosink->ext_surface) {
+ IDirectFBSurface *dest = NULL;
+ gpointer data;
+ gint dest_pitch, src_pitch, line;
+
+ /* External surface, no buffer_alloc optimization */
+ GST_DEBUG ("show frame for an external surface (memcpy)");
+
+ src.w = dfbvideosink->video_width;
+ src.h = dfbvideosink->video_height;
+
+ dfbvideosink->ext_surface->GetSize (dfbvideosink->ext_surface, &dst.w,
+ &dst.h);
+
+ gst_dfbvideosink_center_rect (src, dst, &result, FALSE);
+
+ res = dfbvideosink->ext_surface->GetSubSurface (dfbvideosink->ext_surface,
+ &result, &dest);
+ if (res != DFB_OK) {
+ GST_WARNING ("failed when getting a sub surface from the external one");
+ ret = GST_FLOW_UNEXPECTED;
+ goto beach;
+ }
+
+ res = dest->Lock (dest, DSLF_WRITE, &data, &dest_pitch);
+ if (res != DFB_OK) {
+ GST_WARNING ("failed locking the external subsurface for writing");
+ ret = GST_FLOW_ERROR;
+ goto beach;
+ }
+
+ /* Source video rowbytes */
+ src_pitch = GST_BUFFER_SIZE (buf) / result.h;
+
+ /* Write each line respecting subsurface pitch */
+ for (line = 0; line < result.h; line++) {
+ memcpy (data, GST_BUFFER_DATA (buf) + (line * src_pitch), src_pitch);
+ data += dest_pitch;
+ }
+
+ dest->Unlock (dest);
+
+ dest->Release (dest);
if (dfbvideosink->backbuffer) {
dfbvideosink->ext_surface->Flip (dfbvideosink->ext_surface, NULL, 0);
}
- } else { /* Blit to the fullscreen primary */
- DFBRectangle dst, src, result;
+ } else {
+ IDirectFBSurface *dest = NULL;
+ DFBSurfaceDescription s_dsc;
+ gpointer data;
+ gint pitch;
- src.w = surface->width;
- src.h = surface->height;
+ /* Our peer is bad, it's not using pad_buffer_alloc */
+ GST_DEBUG ("show frame for a buffer we did not allocate (memcpy)");
- dfbvideosink->primary->GetSize (dfbvideosink->primary, &dst.w, &dst.h);
+ src.w = dfbvideosink->video_width;
+ src.h = dfbvideosink->video_height;
- /* Unlocking surface before blit */
- surface->surface->Unlock (surface->surface);
+ dfbvideosink->primary->GetSize (dfbvideosink->primary, &dst.w, &dst.h);
gst_dfbvideosink_center_rect (src, dst, &result,
dfbvideosink->hw_scaling);
+ s_dsc.flags = DSDESC_PIXELFORMAT | DSDESC_WIDTH |
+ DSDESC_HEIGHT | DSDESC_CAPS;
+
+ s_dsc.pixelformat = dfbvideosink->pixel_format;
+ s_dsc.width = dfbvideosink->video_width;
+ s_dsc.height = dfbvideosink->video_height;
+ s_dsc.caps = DSCAPS_VIDEOONLY;
+
+ res = dfbvideosink->dfb->CreateSurface (dfbvideosink->dfb, &s_dsc, &dest);
+ if (res != DFB_OK) {
+ GST_WARNING ("failed creating a surface to memcpy buffer data");
+ goto beach;
+ }
+
+ dest->Lock (dest, DSLF_WRITE, &data, &pitch);
+
+ memcpy (data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+
+ dest->Unlock (dest);
+
if (dfbvideosink->hw_scaling) {
- dfbvideosink->primary->StretchBlit (dfbvideosink->primary,
- surface->surface, NULL, &result);
+ dfbvideosink->primary->StretchBlit (dfbvideosink->primary, dest, NULL,
+ &result);
} else {
- dfbvideosink->primary->Blit (dfbvideosink->primary, surface->surface,
- NULL, result.x, result.y);
+ dfbvideosink->primary->Blit (dfbvideosink->primary, dest, NULL,
+ result.x, result.y);
}
+ dest->Release (dest);
+
if (dfbvideosink->backbuffer) {
dfbvideosink->primary->Flip (dfbvideosink->primary, NULL, 0);
}
}
- } else {
- GST_WARNING
- ("we have to do a memcpy to our internal surface. implement me");
}
beach:
@@ -1228,6 +1319,12 @@ gst_dfbvideosink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
GST_DEBUG ("a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT
" and offset %llu", size, caps, offset);
+ /* If we use an external surface we can't allocate surfaces ourselves */
+ if (dfbvideosink->ext_surface) {
+ *buf = NULL;
+ goto beach;
+ }
+
desired_caps = gst_caps_copy (caps);
structure = gst_caps_get_structure (desired_caps, 0);