diff --git a/ChangeLog b/ChangeLog index 1f57192d1b..ba043a7e5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2005-11-06 Julien MOUTTE + + * ext/directfb/Makefile.am: Add the example application. + * ext/directfb/dfb-example.c: (get_me_out), (main): + Here is an example application that runs videotestsrc for 20 + seconds. It's included in the documentation. + * ext/directfb/dfbvideosink.c: (gst_dfbvideosink_enum_layers), + (gst_dfbvideosink_setup), (gst_dfbvideosink_can_blit_from_format), + (gst_dfbvideosink_getcaps), (gst_dfbvideosink_buffer_alloc): + More fixes, calculate new size of the buffer when renegotiating. + This completely breaks ffmpegcolorspace but i need to discuss + that with Wim on monday. Add documentation. + 2005-11-05 Julien MOUTTE * ext/directfb/dfbvideosink.c: (gst_dfbvideosink_enum_layers), diff --git a/ext/directfb/Makefile.am b/ext/directfb/Makefile.am index eb90c28be8..7a6a65c612 100644 --- a/ext/directfb/Makefile.am +++ b/ext/directfb/Makefile.am @@ -12,3 +12,7 @@ libgstdfbvideosink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ libgstdfbvideosink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = dfbvideosink.h + +noinst_PROGRAMS = dfb-example +dfb_example_CFLAGS = $(GST_CFLAGS) $(DIRECTFB_CFLAGS) +dfb_example_LDADD = $(GST_LIBS) $(DIRECTFB_LIBS) diff --git a/ext/directfb/dfb-example.c b/ext/directfb/dfb-example.c new file mode 100644 index 0000000000..3f455c928d --- /dev/null +++ b/ext/directfb/dfb-example.c @@ -0,0 +1,78 @@ + +#include +#include + +static IDirectFB *dfb = NULL; +static IDirectFBSurface *primary = NULL; +static GMainLoop *loop; + +#define DFBCHECK(x...) \ + { \ + DFBResult err = x; \ + \ + if (err != DFB_OK) \ + { \ + fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ + DirectFBErrorFatal( #x, err ); \ + } \ + } + +static gboolean +get_me_out (gpointer data) +{ + g_main_loop_quit (loop); + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + DFBSurfaceDescription dsc; + GstElement *pipeline, *src, *sink; + + /* Init both GStreamer and DirectFB */ + DFBCHECK (DirectFBInit (&argc, &argv)); + gst_init (&argc, &argv); + + /* Creates DirectFB main context and set it to fullscreen layout */ + DFBCHECK (DirectFBCreate (&dfb)); + DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN)); + + /* We want a double buffered primary surface */ + dsc.flags = DSDESC_CAPS; + dsc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING; + + DFBCHECK (dfb->CreateSurface (dfb, &dsc, &primary)); + + /* Creating our pipeline : videotestsrc ! dfbvideosink */ + pipeline = gst_pipeline_new (NULL); + g_assert (pipeline); + src = gst_element_factory_make ("videotestsrc", NULL); + g_assert (src); + sink = gst_element_factory_make ("dfbvideosink", NULL); + g_assert (sink); + /* That's the interesting part, giving the primary surface to dfbvideosink */ + g_object_set (sink, "surface", primary, NULL); + + /* Adding elements to the pipeline */ + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + g_assert (gst_element_link (src, sink)); + + /* Let's play ! */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* we need to run a GLib main loop to get out of here */ + loop = g_main_loop_new (NULL, FALSE); + /* Get us out after 20 seconds */ + g_timeout_add (20000, get_me_out, NULL); + g_main_loop_run (loop); + + /* Release elements and stop playback */ + gst_element_set_state (pipeline, GST_STATE_NULL); + + /* Release DirectFB context and surface */ + primary->Release (primary); + dfb->Release (dfb); + + return 0; +} diff --git a/ext/directfb/dfbvideosink.c b/ext/directfb/dfbvideosink.c index 47b2cd2fd6..84dd040700 100644 --- a/ext/directfb/dfbvideosink.c +++ b/ext/directfb/dfbvideosink.c @@ -17,6 +17,66 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-dfbvideosink + * + * + * + * DfbVideoSink renders video frames using the + * DirectFB library. + * Rendering can happen in two different modes : + * + * + * + * Standalone: this mode will take complete control of the monitor forcing + * DirectFB to fullscreen layout. + * This is convenient to test using the gst-launch command line tool or + * other simple applications. It is possible to interrupt playback while + * being in this mode by pressing the Escape key. + * + * + * This mode handles navigation events for every input device supported by + * the DirectFB library, it will + * look for available video modes in the fb.modes file and try to switch + * the framebuffer video mode to the most suitable one. Depending on + * hardware acceleration capabilities the element will handle scaling or not. + * If no acceleration is available it will do clipping or centering of the + * video frames respecting the original aspect ratio. + * + * + * + * + * Embedded: this mode will render video frames in a + * surface provided by the + * application developer. This is a more advanced usage of the element and + * it is required to integrate video playback in existing + * DirectFB applications. + * + * + * When using this mode the element just renders to the + * surface provided by the + * application, that means it won't handle navigation events and won't resize + * the surface to fit video + * frames geometry. Application has to implement the necessary code to grab + * informations about the negotiated geometry and resize there + * surface accordingly. + * + * + * + * For both modes the element implements a buffer pool allocation system to + * optimize memory allocation time and handle reverse negotiation. Indeed if + * you insert an element like videoscale in the pipeline the video sink will + * negotiate with it to try get a scaled video for either the fullscreen layout + * or the application provided external + * surface. + * + * Example application + * + * + * + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -1392,11 +1452,15 @@ gst_dfbvideosink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, gst_structure_set (structure, "height", G_TYPE_INT, result.h, NULL); if (gst_pad_accept_caps (peer, desired_caps)) { - GST_DEBUG ("peed pad accepts our desired caps %" GST_PTR_FORMAT, - desired_caps); + gint bpp; + + bpp = size / height / width; rev_nego = TRUE; width = result.w; height = result.h; + size = bpp * width * height; + GST_DEBUG ("peed pad accepts our desired caps %" GST_PTR_FORMAT + " buffer size is now %d bytes", desired_caps, size); } else { GST_DEBUG ("peer pad does not accept our desired caps %" GST_PTR_FORMAT, desired_caps);