diff options
author | Brijesh Singh <bksingh@ti.com> | 2009-09-15 14:17:02 -0500 |
---|---|---|
committer | Koen Kooi <k-kooi@ti.com> | 2009-09-17 10:02:26 +0200 |
commit | cac885572c1429e0522935ffa0854bdf1ed15bcc (patch) | |
tree | 095b4d9f64eb7903c9c4aeba1be443482a7d87f5 | |
parent | 0624cfcd88665ee317e39d53be9febdba013a244 (diff) |
gstreamer-ti: import omapfbsink in gst_ti and add support for hw accelerated framecopy based on dmai transport buffers. The new element is registered as "omapdmaifbsink"
-rw-r--r-- | recipes/ti/gstreamer-ti/gstreamer-ti-add-omapfb.patch | 1336 | ||||
-rw-r--r-- | recipes/ti/gstreamer-ti_svn.bb | 11 |
2 files changed, 1345 insertions, 2 deletions
diff --git a/recipes/ti/gstreamer-ti/gstreamer-ti-add-omapfb.patch b/recipes/ti/gstreamer-ti/gstreamer-ti-add-omapfb.patch new file mode 100644 index 0000000000..e7b1dab300 --- /dev/null +++ b/recipes/ti/gstreamer-ti/gstreamer-ti-add-omapfb.patch @@ -0,0 +1,1336 @@ +diff -uNr ticodecplugin/configure.ac ticodecplugin.new/configure.ac +--- ticodecplugin/configure.ac 2009-09-05 00:04:51.000000000 -0500 ++++ ticodecplugin.new/configure.ac 2009-09-15 13:14:44.000000000 -0500 +@@ -25,6 +25,7 @@ + AC_SUBST(ACLOCAL_AMFLAGS, "-I m4") + + AM_CONFIG_HEADER(config.h) ++AM_PROG_AS + + dnl check for tools + AC_PROG_CC +diff -uNr ticodecplugin/src/Makefile.am ticodecplugin.new/src/Makefile.am +--- ticodecplugin/src/Makefile.am 2009-09-05 00:04:51.000000000 -0500 ++++ ticodecplugin.new/src/Makefile.am 2009-09-15 13:14:44.000000000 -0500 +@@ -4,16 +4,16 @@ + plugin_LTLIBRARIES = libgstticodecplugin.la + + # sources used to compile this plug-in +-libgstticodecplugin_la_SOURCES = gstticodecplugin.c gsttiauddec.c gsttiauddec1.c gsttividdec.c gsttividdec2.c gsttiimgenc1.c gsttiimgenc.c gsttiimgdec1.c gsttiimgdec.c gsttidmaibuffertransport.c gstticircbuffer.c gsttidmaivideosink.c gstticodecs.c gstticodecs_platform.c gsttiquicktime_aac.c gsttiquicktime_h264.c gsttividenc.c gsttividenc1.c gstticommonutils.c ++libgstticodecplugin_la_SOURCES = gstticodecplugin.c gsttiauddec.c gsttiauddec1.c gsttividdec.c gsttividdec2.c gsttiimgenc1.c gsttiimgenc.c gsttiimgdec1.c gsttiimgdec.c gsttidmaibuffertransport.c gstticircbuffer.c gsttidmaivideosink.c gstticodecs.c gstticodecs_platform.c gsttiquicktime_aac.c gsttiquicktime_h264.c gsttividenc.c gsttividenc1.c gstticommonutils.c omapfb.c yuv.S + + # flags used to compile this plugin + # add other _CFLAGS and _LIBS as needed +-libgstticodecplugin_la_CFLAGS = $(GST_CFLAGS) $(shell cat $(XDC_CONFIG_BASENAME)/compiler.opt) +-libgstticodecplugin_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstvideo-0.10 -lgstaudio-0.10 -lm ++libgstticodecplugin_la_CFLAGS = $(GST_CFLAGS) $(shell cat $(XDC_CONFIG_BASENAME)/compiler.opt) -I$(LINUXKERNEL_INSTALL_DIR)/include ++libgstticodecplugin_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstvideo-0.10 -lgstaudio-0.10 -lm -lX11 + libgstticodecplugin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -Wl,$(XDC_CONFIG_BASENAME)/linker.cmd + + # headers we need but don't want installed +-noinst_HEADERS = gsttiauddec.h gsttiauddec1.h gsttividdec.h gsttividdec2.h gsttiimgenc1.h gsttiimgenc.h gsttiimgdec1.h gsttiimgdec.h gsttidmaibuffertransport.h gstticircbuffer.h gsttidmaivideosink.h gsttithreadprops.h gstticodecs.h gsttiquicktime_aac.h gsttiquicktime_h264.h gsttividenc.h gsttividenc1.h gstticommonutils.h ++noinst_HEADERS = gsttiauddec.h gsttiauddec1.h gsttividdec.h gsttividdec2.h gsttiimgenc1.h gsttiimgenc.h gsttiimgdec1.h gsttiimgdec.h gsttidmaibuffertransport.h gstticircbuffer.h gsttidmaivideosink.h gsttithreadprops.h gstticodecs.h gsttiquicktime_aac.h gsttiquicktime_h264.h gsttividenc.h gsttividenc1.h gstticommonutils.h omapfb.h + + # XDC Configuration + CONFIGURO = $(XDC_INSTALL_DIR)/xs xdc.tools.configuro +diff -uNr ticodecplugin/src/gstticodecplugin.c ticodecplugin.new/src/gstticodecplugin.c +--- ticodecplugin/src/gstticodecplugin.c 2009-09-05 00:04:51.000000000 -0500 ++++ ticodecplugin.new/src/gstticodecplugin.c 2009-09-15 13:14:44.000000000 -0500 +@@ -44,6 +44,7 @@ + #include "gsttidmaivideosink.h" + #include "gsttividenc.h" + #include "gsttividenc1.h" ++#include "omapfb.h" + + /* entry point to initialize the plug-in + * initialize the plug-in itself +@@ -137,6 +138,13 @@ + GST_TYPE_TIDMAIVIDEOSINK)) + return FALSE; + ++ env_value = getenv("GST_Omapfbdmaisink_DISABLE"); ++ ++ if ((!env_value || strcmp(env_value,"1")) && !gst_element_register( ++ TICodecPlugin, "omapdmaifbsink", GST_RANK_PRIMARY, ++ GST_OMAPFB_SINK_TYPE)) ++ return FALSE; ++ + return TRUE; + } + +diff -uNr ticodecplugin/src/omapfb.c ticodecplugin.new/src/omapfb.c +--- ticodecplugin/src/omapfb.c 1969-12-31 18:00:00.000000000 -0600 ++++ ticodecplugin.new/src/omapfb.c 2009-09-15 13:16:03.000000000 -0500 +@@ -0,0 +1,1005 @@ ++/* ++ * Copyright (C) 2008 Felipe Contreras <felipe.contreras@gmail.com> ++ * Copyright (C) 2009 Tim Yamin <plasm@roo.me.uk> ++ * Copyright (C) 2009 Brijesh Singh <brijesh.ksingh@gmail.com> ++ * ++ * X code largely copied from ximagesink by Julien Moutte and ++ * vo_omapfb.c by Gregoire Gentil. ++ * ++ * Use DMAI hw framecopy module to copy the dmai transport buffers. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation ++ * version 2.1 of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA ++ */ ++ ++#include <fcntl.h> ++#include <sys/ioctl.h> ++#include <sys/mman.h> ++#include <unistd.h> ++#include <string.h> ++#include <sys/types.h> ++#include <malloc.h> ++#include <stdlib.h> ++ ++#include "omapfb.h" ++#include <gst/interfaces/xoverlay.h> ++ ++static GstVideoSinkClass *parent_class = NULL; ++ ++extern void yuv420_to_yuv422(__uint8_t *yuv, __uint8_t *y, __uint8_t *u, __uint8_t *v, ++ int w, int h, int yw, int cw, int dw); ++ ++static void x11_get_window_abs_position(Display *display, Window window, ++ int *wx, int *wy, int *ww, int *wh) ++{ ++ Window root, parent; ++ Window *child; ++ unsigned int n_children; ++ XWindowAttributes attribs; ++ ++ /* Get window attributes */ ++ XGetWindowAttributes(display, window, &attribs); ++ ++ /* Get relative position of given window */ ++ *wx = attribs.x; ++ *wy = attribs.y; ++ if (ww) ++ *ww = attribs.width; ++ if (wh) ++ *wh = attribs.height; ++ ++ /* Query window tree information */ ++ XQueryTree(display, window, &root, &parent, &child, &n_children); ++ if (parent) ++ { ++ int x, y; ++ ++ /* If we have a parent we must go there and discover his position */ ++ x11_get_window_abs_position(display, parent, &x, &y, NULL, NULL); ++ *wx += x; ++ *wy += y; ++ } ++ ++ /* If we had children, free them */ ++ if(n_children) ++ XFree(child); ++} ++ ++static GstXWindow * ++gst_omapfbsink_xwindow_new (GstOmapFbSink * omapfbsink, gint width, gint height) ++{ ++ GstXWindow *xwindow = NULL; ++ XGCValues values; ++ ++ if(!omapfbsink->xcontext) ++ return NULL; ++ ++ xwindow = g_new0 (GstXWindow, 1); ++ xwindow->width = width; ++ xwindow->height = height; ++ xwindow->internal = TRUE; ++ ++ g_mutex_lock (omapfbsink->x_lock); ++ xwindow->win = XCreateSimpleWindow (omapfbsink->xcontext->disp, ++ omapfbsink->xcontext->root, ++ 0, 0, xwindow->width, xwindow->height, ++ 0, 0, omapfbsink->colorKey); ++ ++ /* We have to do that to prevent X from redrawing the background on ++ ConfigureNotify. This takes away flickering of video when resizing. */ ++ XSetWindowBackgroundPixmap (omapfbsink->xcontext->disp, xwindow->win, None); ++ ++ if (omapfbsink->handle_events) { ++ Atom wm_delete; ++ ++ XSelectInput (omapfbsink->xcontext->disp, xwindow->win, ExposureMask | ++ StructureNotifyMask | PointerMotionMask | KeyPressMask | ++ KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); ++ ++ /* Tell the window manager we'd like delete client messages instead of ++ * being killed */ ++ wm_delete = XInternAtom (omapfbsink->xcontext->disp, ++ "WM_DELETE_WINDOW", False); ++ (void) XSetWMProtocols (omapfbsink->xcontext->disp, xwindow->win, ++ &wm_delete, 1); ++ } ++ ++ xwindow->gc = XCreateGC (omapfbsink->xcontext->disp, xwindow->win, ++ 0, &values); ++ ++ XMapRaised (omapfbsink->xcontext->disp, xwindow->win); ++ XSync (omapfbsink->xcontext->disp, FALSE); ++ ++ g_mutex_unlock (omapfbsink->x_lock); ++ gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (omapfbsink), xwindow->win); ++ ++ return xwindow; ++} ++ ++static gboolean gst_omapfbsink_update_plane (GstOmapFbSink *omapfbsink) ++{ ++ int wx, wy, ww, wh; ++ if (!omapfbsink->xcontext) ++ { ++ if (ioctl (omapfbsink->overlay_fd, OMAPFB_SETUP_PLANE, &omapfbsink->plane_info)) ++ return FALSE; ++ return TRUE; ++ } ++ ++ if (omapfbsink->plane_info.enabled != 1) ++ return FALSE; ++ ++ x11_get_window_abs_position(omapfbsink->xcontext->disp, ++ omapfbsink->xwindow->win, &wx, &wy, &ww, &wh); ++ ++ if (wx != omapfbsink->xwindow->wx || wy != omapfbsink->xwindow->wy || ++ wh != omapfbsink->xwindow->height || ww != omapfbsink->xwindow->width) { ++ omapfbsink->plane_info.out_width = omapfbsink->xwindow->width = ww; ++ omapfbsink->plane_info.out_height = omapfbsink->xwindow->height = wh; ++ omapfbsink->plane_info.pos_x = omapfbsink->xwindow->wx = wx; ++ omapfbsink->plane_info.pos_y = omapfbsink->xwindow->wy = wy; ++ ++ GST_DEBUG_OBJECT(omapfbsink, "updating geometry to: (%d,%d) %dx%d", wx, wy, ww, wh); ++ ++ XSetForeground (omapfbsink->xcontext->disp, omapfbsink->xwindow->gc, omapfbsink->colorKey); ++ XFillRectangle (omapfbsink->xcontext->disp, omapfbsink->xwindow->win, omapfbsink->xwindow->gc, 0, 0, ww, wh); ++ ++ if (ioctl (omapfbsink->overlay_fd, OMAPFB_SETUP_PLANE, &omapfbsink->plane_info)) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static void ++gst_omapfbsink_expose (GstXOverlay * overlay) ++{ ++ gst_omapfbsink_update_plane(GST_OMAPFB_SINK (overlay)); ++} ++ ++static void ++gst_omapfbsink_xwindow_destroy (GstOmapFbSink * omapfbsink, ++ GstXWindow * xwindow) ++{ ++ g_return_if_fail (xwindow != NULL); ++ g_mutex_lock (omapfbsink->x_lock); ++ ++ /* If we did not create that window we just free the GC and let it live */ ++ if (xwindow->internal) ++ XDestroyWindow (omapfbsink->xcontext->disp, xwindow->win); ++ else ++ XSelectInput (omapfbsink->xcontext->disp, xwindow->win, 0); ++ ++ XFreeGC (omapfbsink->xcontext->disp, xwindow->gc); ++ XSync (omapfbsink->xcontext->disp, FALSE); ++ g_mutex_unlock (omapfbsink->x_lock); ++ g_free (xwindow); ++} ++ ++/* This function handles XEvents that might be in the queue. It generates ++ GstEvent that will be sent upstream in the pipeline to handle interactivity ++ and navigation.*/ ++static void ++gst_omapfbsink_handle_xevents (GstOmapFbSink * omapfbsink) ++{ ++ XEvent e; ++ g_mutex_lock (omapfbsink->flow_lock); ++ g_mutex_lock (omapfbsink->x_lock); ++ ++ while (XCheckWindowEvent (omapfbsink->xcontext->disp, ++ omapfbsink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) { ++ switch (e.type) { ++ case Expose: ++ case ConfigureNotify: ++ gst_omapfbsink_update_plane (omapfbsink); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ /* Handle Display events */ ++ while (XPending (omapfbsink->xcontext->disp)) { ++ XNextEvent (omapfbsink->xcontext->disp, &e); ++ ++ switch (e.type) { ++ case ClientMessage:{ ++ Atom wm_delete; ++ ++ wm_delete = XInternAtom (omapfbsink->xcontext->disp, ++ "WM_DELETE_WINDOW", False); ++ if (wm_delete == (Atom) e.xclient.data.l[0]) { ++ /* Handle window deletion by posting an error on the bus */ ++ GST_ELEMENT_ERROR (omapfbsink, RESOURCE, NOT_FOUND, ++ ("Output window was closed"), (NULL)); ++ ++ g_mutex_unlock (omapfbsink->x_lock); ++ gst_omapfbsink_xwindow_destroy (omapfbsink, omapfbsink->xwindow); ++ omapfbsink->xwindow = NULL; ++ g_mutex_lock (omapfbsink->x_lock); ++ } ++ break; ++ } ++ default: ++ break; ++ } ++ } ++ ++ g_mutex_unlock (omapfbsink->x_lock); ++ g_mutex_unlock (omapfbsink->flow_lock); ++} ++ ++static gpointer ++gst_omapfbsink_event_thread (GstOmapFbSink * omapfbsink) ++{ ++ GST_OBJECT_LOCK (omapfbsink); ++ while (omapfbsink->running) { ++ GST_OBJECT_UNLOCK (omapfbsink); ++ ++ if (omapfbsink->xwindow) ++ gst_omapfbsink_handle_xevents (omapfbsink); ++ g_usleep (100000); ++ ++ GST_OBJECT_LOCK (omapfbsink); ++ } ++ GST_OBJECT_UNLOCK (omapfbsink); ++ ++ return NULL; ++} ++ ++/* This function gets the X Display and global info about it. Everything is ++ stored in our object and will be cleaned when the object is disposed. */ ++static GstXContext * ++gst_omapfbsink_xcontext_get (GstOmapFbSink * omapfbsink) ++{ ++ GstXContext *xcontext = g_new0 (GstXContext, 1); ++ g_mutex_lock (omapfbsink->x_lock); ++ ++ xcontext->disp = XOpenDisplay (omapfbsink->display_name); ++ ++ if (!xcontext->disp) { ++ g_mutex_unlock (omapfbsink->x_lock); ++ g_free (xcontext); ++ GST_ELEMENT_WARNING (omapfbsink, RESOURCE, WRITE, ++ ("Could not initialise X output"), ++ ("Could not open display")); ++ return NULL; ++ } ++ ++ xcontext->screen = DefaultScreenOfDisplay (xcontext->disp); ++ xcontext->screen_num = DefaultScreen (xcontext->disp); ++ xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num); ++ xcontext->root = DefaultRootWindow (xcontext->disp); ++ ++ xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num); ++ xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num); ++ ++ g_mutex_unlock (omapfbsink->x_lock); ++ ++ /* Setup our event listening thread */ ++ GST_OBJECT_LOCK (omapfbsink); ++ omapfbsink->running = TRUE; ++ omapfbsink->event_thread = g_thread_create ( ++ (GThreadFunc) gst_omapfbsink_event_thread, omapfbsink, TRUE, NULL); ++ GST_OBJECT_UNLOCK (omapfbsink); ++ ++ return xcontext; ++} ++ ++static void ++gst_omapfbsink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id) ++{ ++ GstOmapFbSink *omapfbsink = GST_OMAPFB_SINK (overlay); ++ GstXWindow *xwindow = NULL; ++ XWindowAttributes attr; ++ ++ /* If we already use that window, return */ ++ if (omapfbsink->xwindow && (xwindow_id == omapfbsink->xwindow->win)) ++ return; ++ ++ /* If the element has not initialized the X11 context try to do so */ ++ if (!omapfbsink->xcontext && ++ !(omapfbsink->xcontext = gst_omapfbsink_xcontext_get (omapfbsink))) { ++ g_mutex_unlock (omapfbsink->flow_lock); ++ return; ++ } ++ ++ /* If a window is there already we destroy it */ ++ if (omapfbsink->xwindow) { ++ gst_omapfbsink_xwindow_destroy (omapfbsink, omapfbsink->xwindow); ++ omapfbsink->xwindow = NULL; ++ } ++ ++ /* If the xid is 0 we go back to an internal window */ ++ if (xwindow_id == 0) { ++ /* If no width/height caps nego did not happen window will be created ++ during caps nego then */ ++ if (GST_VIDEO_SINK_WIDTH (omapfbsink) && GST_VIDEO_SINK_HEIGHT (omapfbsink)) { ++ xwindow = gst_omapfbsink_xwindow_new (omapfbsink, ++ GST_VIDEO_SINK_WIDTH (omapfbsink), ++ GST_VIDEO_SINK_HEIGHT (omapfbsink)); ++ } ++ } else { ++ xwindow = g_new0 (GstXWindow, 1); ++ xwindow->wx = xwindow->wy = -1; ++ xwindow->win = xwindow_id; ++ ++ /* We get window geometry, set the event we want to receive, ++ and create a GC */ ++ g_mutex_lock (omapfbsink->x_lock); ++ XGetWindowAttributes (omapfbsink->xcontext->disp, xwindow->win, &attr); ++ xwindow->width = attr.width; ++ xwindow->height = attr.height; ++ xwindow->internal = FALSE; ++ if (omapfbsink->handle_events) { ++ XSelectInput (omapfbsink->xcontext->disp, xwindow->win, ExposureMask | ++ StructureNotifyMask | PointerMotionMask | KeyPressMask | ++ KeyReleaseMask); ++ } ++ ++ xwindow->gc = XCreateGC (omapfbsink->xcontext->disp, xwindow->win, 0, NULL); ++ g_mutex_unlock (omapfbsink->x_lock); ++ } ++ ++ if (xwindow) { ++ omapfbsink->xwindow = xwindow; ++ ++ g_mutex_lock (omapfbsink->x_lock); ++ gst_omapfbsink_update_plane(omapfbsink); ++ g_mutex_unlock (omapfbsink->x_lock); ++ } ++} ++ ++static void ++gst_omapfbsink_xwindow_clear (GstOmapFbSink * omapfbsink, ++ GstXWindow * xwindow) ++{ ++ g_return_if_fail (xwindow != NULL); ++ g_mutex_lock (omapfbsink->x_lock); ++ ++ XSetForeground (omapfbsink->xcontext->disp, xwindow->gc, ++ XBlackPixel (omapfbsink->xcontext->disp, ++ omapfbsink->xcontext->screen_num)); ++ ++ XFillRectangle (omapfbsink->xcontext->disp, xwindow->win, xwindow->gc, ++ 0, 0, xwindow->width, xwindow->height); ++ ++ XSync (omapfbsink->xcontext->disp, FALSE); ++ g_mutex_unlock (omapfbsink->x_lock); ++} ++ ++static void ++gst_omapfbsink_set_event_handling (GstXOverlay * overlay, ++ gboolean handle_events) ++{ ++ GstOmapFbSink *omapfbsink = GST_OMAPFB_SINK (overlay); ++ omapfbsink->handle_events = handle_events; ++ ++ g_mutex_lock (omapfbsink->flow_lock); ++ ++ if (G_UNLIKELY (!omapfbsink->xwindow)) { ++ g_mutex_unlock (omapfbsink->flow_lock); ++ return; ++ } ++ ++ g_mutex_lock (omapfbsink->x_lock); ++ ++ if (handle_events) { ++ if (omapfbsink->xwindow->internal) { ++ XSelectInput (omapfbsink->xcontext->disp, omapfbsink->xwindow->win, ++ ExposureMask | StructureNotifyMask | PointerMotionMask | ++ KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); ++ } else { ++ XSelectInput (omapfbsink->xcontext->disp, omapfbsink->xwindow->win, ++ ExposureMask | StructureNotifyMask | PointerMotionMask | ++ KeyPressMask | KeyReleaseMask); ++ } ++ } else { ++ XSelectInput (omapfbsink->xcontext->disp, omapfbsink->xwindow->win, 0); ++ } ++ ++ g_mutex_unlock (omapfbsink->x_lock); ++ g_mutex_unlock (omapfbsink->flow_lock); ++} ++ ++static void ++gst_omapfbsink_xoverlay_init (GstXOverlayClass * iface) ++{ ++ iface->set_xwindow_id = gst_omapfbsink_set_xwindow_id; ++ iface->expose = gst_omapfbsink_expose; ++ iface->handle_events = gst_omapfbsink_set_event_handling; ++} ++ ++static GstCaps * ++generate_sink_template (void) ++{ ++ GstCaps *caps; ++ GstStructure *struc; ++ ++ caps = gst_caps_new_empty (); ++ ++ struc = gst_structure_new ("video/x-raw-yuv", ++ "width", GST_TYPE_INT_RANGE, 16, 4096, ++ "height", GST_TYPE_INT_RANGE, 16, 4096, ++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 30, 1, ++ NULL); ++ ++ { ++ GValue list; ++ GValue val; ++ ++ list.g_type = val.g_type = 0; ++ ++ g_value_init (&list, GST_TYPE_LIST); ++ g_value_init (&val, GST_TYPE_FOURCC); ++ ++#if 0 ++ gst_value_set_fourcc (&val, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2')); ++ gst_value_list_append_value (&list, &val); ++#else ++ gst_value_set_fourcc (&val, GST_MAKE_FOURCC ('I', '4', '2', '0')); ++ gst_value_list_append_value (&list, &val); ++ ++ gst_value_set_fourcc (&val, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y')); ++ gst_value_list_append_value (&list, &val); ++#endif ++ ++ gst_structure_set_value (struc, "format", &list); ++ ++ g_value_unset (&val); ++ g_value_unset (&list); ++ } ++ ++ gst_caps_append_structure (caps, struc); ++ ++ return caps; ++} ++ ++static GstFlowReturn ++buffer_alloc (GstBaseSink *bsink, ++ guint64 offset, ++ guint size, ++ GstCaps *caps, ++ GstBuffer **buf) ++{ ++ GstOmapFbSink *self; ++ GstBuffer *buffer = NULL; ++ GstFlowReturn ret = GST_FLOW_OK; ++ self = GST_OMAPFB_SINK (bsink); ++ ++ if(self->row_skip) { ++ buffer = gst_buffer_new (); ++ GST_BUFFER_DATA (buffer) = self->buffer = self->framebuffer; ++ GST_BUFFER_SIZE (buffer) = self->buffer_size = size; ++ gst_buffer_set_caps (buffer, caps); ++ } else { ++ if(self->buffer && size == self->buffer_size) { ++ buffer = gst_buffer_new (); ++ GST_BUFFER_DATA (buffer) = self->buffer; ++ GST_BUFFER_SIZE (buffer) = size; ++ gst_buffer_set_caps (buffer, caps); ++ } else { ++ if(self->buffer) ++ free(self->buffer); ++ if(posix_memalign(&self->buffer, 16, (size_t) size) == 0) { ++ buffer = gst_buffer_new (); ++ GST_BUFFER_DATA (buffer) = self->buffer; ++ GST_BUFFER_SIZE (buffer) = self->buffer_size = size; ++ gst_buffer_set_caps (buffer, caps); ++ } else { ++ GST_ELEMENT_ERROR (self, RESOURCE, WRITE, ("Could not allocate aligned buf!"), ++ ("Could not alloc aligned buf!")); ++ } ++ } ++ } ++ ++ *buf = buffer; ++ return ret; ++} ++ ++static void ++x_memcpy (GstOmapFbSink *omapfbsink, __uint8_t *outBuf, __uint8_t *inBuf) ++{ ++ BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; ++ Buffer_Handle hInBuf = NULL, hOutBuf = NULL; ++ Framecopy_Attrs fcAttrs = Framecopy_Attrs_DEFAULT; ++ int size; ++ ++ if (omapfbsink->hFc == NULL) { ++ fcAttrs.accel = TRUE; ++ omapfbsink->hFc = Framecopy_create(&fcAttrs); ++ if (omapfbsink->hFc == NULL) { ++ GST_ELEMENT_ERROR(omapfbsink, RESOURCE, WRITE, ("failed to create dmai framecopy handle"), ("failed to create dmai framecopy handle")); ++ goto cleanup; ++ } ++ } ++ ++ gfxAttrs.bAttrs.reference = TRUE; ++ gfxAttrs.dim.width = GST_VIDEO_SINK_WIDTH (omapfbsink); ++ gfxAttrs.dim.height = GST_VIDEO_SINK_HEIGHT (omapfbsink); ++ gfxAttrs.colorSpace = ColorSpace_UYVY; ++ gfxAttrs.dim.lineLength = omapfbsink->fixinfo.line_length; ++ size = gfxAttrs.dim.height * gfxAttrs.dim.width * 2; ++ ++ hInBuf = Buffer_create(size, BufferGfx_getBufferAttrs(&gfxAttrs)); ++ if (hInBuf == NULL) { ++ GST_ELEMENT_ERROR(omapfbsink, RESOURCE, WRITE, ("Could not allocate refer dmai buffer"), ("Could not allocate refer dmai buffer")); ++ goto cleanup; ++ } ++ Buffer_setUserPtr(hInBuf, (Int8*) inBuf); ++ Buffer_setNumBytesUsed(hInBuf,Buffer_getSize(hInBuf)); ++ ++ hOutBuf = Buffer_create(size, BufferGfx_getBufferAttrs(&gfxAttrs)); ++ if (hOutBuf == NULL) { ++ GST_ELEMENT_ERROR(omapfbsink, RESOURCE, WRITE, ("Could not allocate refer dmai buffer"), ("Could not allocate refer dmai buffer")); ++ goto cleanup; ++ } ++ Buffer_setUserPtr(hOutBuf, (Int8*) outBuf); ++ Buffer_setNumBytesUsed(hOutBuf,Buffer_getSize(hOutBuf)); ++ ++ ++ if (Framecopy_config(omapfbsink->hFc, hInBuf, hOutBuf) < 0) { ++ GST_ELEMENT_ERROR(omapfbsink, RESOURCE, WRITE, ("failed to configure dmai framecopy handle"), ("failed to configure dmai framecopy handle")); ++ goto cleanup; ++ } ++ ++ if (Framecopy_execute(omapfbsink->hFc, hInBuf, hOutBuf) < 0) { ++ GST_ELEMENT_ERROR(omapfbsink, RESOURCE, WRITE, ("failed to execute dmai framecopy handle"), ("failed to configure dmai framecopy handle")); ++ goto cleanup; ++ } ++ cleanup: ++ ++ if (hInBuf) ++ Buffer_delete(hInBuf); ++ if (hOutBuf) ++ Buffer_delete(hOutBuf); ++} ++ ++static GstFlowReturn ++render (GstBaseSink * bsink, GstBuffer * buf) ++{ ++ int i, w, h; ++ GstOmapFbSink *omapfbsink = GST_OMAPFB_SINK(bsink); ++ __uint8_t *fb = omapfbsink->framebuffer, *data = GST_BUFFER_DATA(buf); ++ gboolean useXcopy = FALSE; ++ ++ if (GST_IS_TIDMAIBUFFERTRANSPORT(buf)) { ++ GST_LOG("found dmai transport buffer, enabling hw framecopy.\n"); ++ useXcopy = TRUE; ++ } ++ ++ if(omapfbsink->plane_info.enabled == 2) ++ { ++ omapfbsink->plane_info.enabled = 1; ++ ++ g_mutex_lock (omapfbsink->x_lock); ++ gst_omapfbsink_update_plane(omapfbsink); ++ g_mutex_unlock (omapfbsink->x_lock); ++ } ++ ++ /* If a buffer which wasn't supplied by us is given to us to render with, ++ we need to copy to our buffer first so that memory alignment constraints ++ are met. */ ++ if((data != omapfbsink->buffer && GST_BUFFER_SIZE(buf) <= omapfbsink->buffer_size) && !useXcopy) ++ { ++ memcpy(omapfbsink->buffer, data, GST_BUFFER_SIZE(buf)); ++ data = omapfbsink->buffer; ++ } ++ ++ /* buffer_alloc gave a direct buffer, so we have nothing to ++ do here... */ ++ if(omapfbsink->row_skip) ++ return GST_FLOW_OK; ++ ++ switch(omapfbsink->image_format) { ++ case GST_MAKE_FOURCC('I', '4', '2', '0'): ++ /* Convert to YUV422 and send to FB */ ++ ++ h = GST_VIDEO_SINK_HEIGHT (omapfbsink); ++ w = GST_VIDEO_SINK_WIDTH (omapfbsink); ++ ++ __uint8_t *y, *u, *v; ++ y = data; ++ u = y + w * h; ++ v = u + w / 2 * h / 2; ++ yuv420_to_yuv422(fb, y, u, v, w & ~15, h, w, w / 2, omapfbsink->fixinfo.line_length); ++ break; ++ ++ case GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'): ++ /* Send to FB, taking into account line_length */ ++ if (useXcopy) { ++ x_memcpy(omapfbsink, fb, data); ++ } ++ else { ++ ++ w = 2 * GST_VIDEO_SINK_WIDTH (omapfbsink); ++ for(i = 0; i < GST_VIDEO_SINK_HEIGHT (omapfbsink); i++) ++ { ++ memcpy(fb, data, w); ++ ++ fb += omapfbsink->fixinfo.line_length; ++ data += w; ++ } ++ } ++ break; ++ } ++ ++ return GST_FLOW_OK; ++} ++ ++static gboolean ++setcaps (GstBaseSink *bsink, ++ GstCaps *vscapslist) ++{ ++ GstOmapFbSink *self; ++ GstStructure *structure; ++ ++ gint width, height; ++ struct omapfb_color_key color_key; ++ ++ self = GST_OMAPFB_SINK (bsink); ++ ++ structure = gst_caps_get_structure (vscapslist, 0); ++ ++ gst_structure_get_int (structure, "width", &width); ++ gst_structure_get_int (structure, "height", &height); ++ ++ self->overlay_info.xres = MIN (self->varinfo.xres, width) & ~15; ++ self->overlay_info.yres = MIN (self->varinfo.yres, height) & ~15; ++ self->overlay_info.xres_virtual = self->overlay_info.xres; ++ self->overlay_info.yres_virtual = self->overlay_info.yres; ++ ++ self->overlay_info.xoffset = 0; ++ self->overlay_info.yoffset = 0; ++ ++ gst_structure_get_fourcc (structure, "format", &self->image_format); ++ switch(self->image_format) { ++ case GST_MAKE_FOURCC('I', '4', '2', '0'): ++ self->row_skip = FALSE; /* Colorspace conversion required */ ++ self->overlay_info.nonstd = OMAPFB_COLOR_YUY422; ++ break; ++ case GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'): ++ /* Can data be pushed straight to the FB or do we need to interleave? */ ++ if (self->fixinfo.line_length != 2 * width) ++ self->row_skip = FALSE; ++ else ++ self->row_skip = TRUE; ++ self->overlay_info.nonstd = OMAPFB_COLOR_YUV422; ++ break; ++ } ++ ++ if (ioctl (self->overlay_fd, FBIOPUT_VSCREENINFO, &self->overlay_info)) ++ return FALSE; ++ ++ GST_VIDEO_SINK_WIDTH (self) = width; ++ GST_VIDEO_SINK_HEIGHT (self) = height; ++ if (!self->xwindow) { ++ self->xwindow = gst_omapfbsink_xwindow_new (self, ++ GST_VIDEO_SINK_WIDTH (self), GST_VIDEO_SINK_HEIGHT (self)); ++ } ++ ++ color_key.channel_out = OMAPFB_CHANNEL_OUT_LCD; ++ color_key.background = 0x0; ++ color_key.trans_key = self->colorKey; ++ if (self->xwindow) ++ color_key.key_type = OMAPFB_COLOR_KEY_GFX_DST; ++ else ++ color_key.key_type = OMAPFB_COLOR_KEY_DISABLED; ++ ++ if (ioctl (self->overlay_fd, OMAPFB_SET_COLOR_KEY, &color_key)) ++ return FALSE; ++ ++ self->plane_info.pos_x = 0; ++ self->plane_info.pos_y = 0; ++ self->plane_info.out_width = self->overlay_info.xres; ++ self->plane_info.out_height = self->overlay_info.yres; ++ self->plane_info.enabled = 2; ++ ++ if (ioctl (self->overlay_fd, FBIOGET_FSCREENINFO, &self->fixinfo)) ++ return FALSE; ++ ++ self->enabled = TRUE; ++ return TRUE; ++} ++ ++static gboolean ++start (GstBaseSink *bsink) ++{ ++ GstOmapFbSink *self; ++ int fd; ++ ++ self = GST_OMAPFB_SINK (bsink); ++ ++ fd = open ("/dev/fb0", O_RDWR); ++ ++ if (fd == -1) ++ return FALSE; ++ ++ if (ioctl (fd, FBIOGET_VSCREENINFO, &self->varinfo)) ++ { ++ close (fd); ++ return FALSE; ++ } ++ ++ if (close (fd)) ++ return FALSE; ++ ++ self->overlay_fd = open ("/dev/fb1", O_RDWR); ++ ++ if (self->overlay_fd == -1) ++ return FALSE; ++ ++ if (ioctl (self->overlay_fd, FBIOGET_VSCREENINFO, &self->overlay_info)) ++ return FALSE; ++ ++ if (ioctl (self->overlay_fd, OMAPFB_QUERY_PLANE, &self->plane_info)) ++ return FALSE; ++ ++ if (ioctl (self->overlay_fd, OMAPFB_QUERY_MEM, &self->mem_info)) ++ return FALSE; ++ ++ self->framebuffer = mmap (NULL, self->mem_info.size, PROT_WRITE, MAP_SHARED, self->overlay_fd, 0); ++ if (self->framebuffer == MAP_FAILED) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++static gboolean ++stop (GstBaseSink *bsink) ++{ ++ GstOmapFbSink *self; ++ ++ self = GST_OMAPFB_SINK (bsink); ++ ++ if (self->enabled) ++ { ++ self->plane_info.enabled = 0; ++ ++ if (ioctl (self->overlay_fd, OMAPFB_SETUP_PLANE, &self->plane_info)) ++ return FALSE; ++ } ++ ++ if (munmap (self->framebuffer, self->mem_info.size)) ++ return FALSE; ++ ++ if (close (self->overlay_fd)) ++ return FALSE; ++ ++ if (self->hFc) ++ Framecopy_delete(self->hFc); ++ ++ return TRUE; ++} ++ ++/* This function cleans the X context. Closing the Display and unrefing the ++ caps for supported formats. */ ++static void ++gst_omapfbsink_xcontext_clear (GstOmapFbSink * omapfbsink) ++{ ++ GstXContext *xcontext; ++ GST_OBJECT_LOCK (omapfbsink); ++ if (omapfbsink->xcontext == NULL) { ++ GST_OBJECT_UNLOCK (omapfbsink); ++ return; ++ } ++ ++ xcontext = omapfbsink->xcontext; ++ omapfbsink->xcontext = NULL; ++ ++ GST_OBJECT_UNLOCK (omapfbsink); ++ g_mutex_lock (omapfbsink->x_lock); ++ ++ XCloseDisplay (xcontext->disp); ++ g_mutex_unlock (omapfbsink->x_lock); ++ g_free (xcontext); ++} ++ ++static void ++gst_omapfbsink_reset (GstOmapFbSink *omapfbsink) ++{ ++ GThread *thread; ++ ++ GST_OBJECT_LOCK (omapfbsink); ++ omapfbsink->running = FALSE; ++ /* grab thread and mark it as NULL */ ++ thread = omapfbsink->event_thread; ++ omapfbsink->event_thread = NULL; ++ GST_OBJECT_UNLOCK (omapfbsink); ++ ++ /* Wait for our event thread to finish before we clean up our stuff. */ ++ if (thread) ++ g_thread_join (thread); ++ ++ g_mutex_lock (omapfbsink->flow_lock); ++ if (omapfbsink->xwindow) { ++ gst_omapfbsink_xwindow_clear (omapfbsink, omapfbsink->xwindow); ++ gst_omapfbsink_xwindow_destroy (omapfbsink, omapfbsink->xwindow); ++ omapfbsink->xwindow = NULL; ++ } ++ g_mutex_unlock (omapfbsink->flow_lock); ++ gst_omapfbsink_xcontext_clear (omapfbsink); ++} ++ ++static GstStateChangeReturn ++gst_omapfbsink_change_state (GstElement * element, GstStateChange transition) ++{ ++ GstOmapFbSink *omapfbsink; ++ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; ++ GstXContext *xcontext = NULL; ++ ++ omapfbsink = GST_OMAPFB_SINK (element); ++ ++ switch (transition) { ++ case GST_STATE_CHANGE_NULL_TO_READY: ++ ++ /* Initializing the XContext */ ++ if (omapfbsink->xcontext == NULL) { ++ xcontext = gst_omapfbsink_xcontext_get (omapfbsink); ++ ++ GST_OBJECT_LOCK (omapfbsink); ++ omapfbsink->xcontext = xcontext; ++ GST_OBJECT_UNLOCK (omapfbsink); ++ } ++ break; ++ case GST_STATE_CHANGE_READY_TO_PAUSED: ++ g_mutex_lock (omapfbsink->flow_lock); ++ if (omapfbsink->xwindow) ++ gst_omapfbsink_xwindow_clear (omapfbsink, omapfbsink->xwindow); ++ g_mutex_unlock (omapfbsink->flow_lock); ++ break; ++ case GST_STATE_CHANGE_PAUSED_TO_PLAYING: ++ break; ++ default: ++ break; ++ } ++ ++ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); ++ ++ switch (transition) { ++ case GST_STATE_CHANGE_PLAYING_TO_PAUSED: ++ break; ++ case GST_STATE_CHANGE_PAUSED_TO_READY: ++ GST_VIDEO_SINK_WIDTH (omapfbsink) = 0; ++ GST_VIDEO_SINK_HEIGHT (omapfbsink) = 0; ++ break; ++ case GST_STATE_CHANGE_READY_TO_NULL: ++ gst_omapfbsink_reset (omapfbsink); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static void ++type_class_init (gpointer g_class, ++ gpointer class_data) ++{ ++ GstElementClass *element_class; ++ GstBaseSinkClass *base_sink_class; ++ ++ element_class = (GstElementClass *) g_class; ++ base_sink_class = (GstBaseSinkClass *) g_class; ++ ++ parent_class = g_type_class_peek_parent (g_class); ++ ++ base_sink_class->set_caps = GST_DEBUG_FUNCPTR (setcaps); ++ base_sink_class->buffer_alloc = GST_DEBUG_FUNCPTR (buffer_alloc); ++ base_sink_class->render = GST_DEBUG_FUNCPTR (render); ++ base_sink_class->start = GST_DEBUG_FUNCPTR (start); ++ base_sink_class->stop = GST_DEBUG_FUNCPTR (stop); ++ ++ element_class->change_state = gst_omapfbsink_change_state; ++} ++ ++static void ++type_base_init (gpointer g_class) ++{ ++ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); ++ ++ { ++ GstElementDetails details; ++ ++ details.longname = "Linux OMAP framebuffer sink"; ++ details.klass = "Sink/Video"; ++ details.description = "Renders video with omapfb"; ++ details.author = "Felipe Contreras"; ++ ++ gst_element_class_set_details (element_class, &details); ++ } ++ ++ { ++ GstPadTemplate *template; ++ ++ template = gst_pad_template_new ("sink", GST_PAD_SINK, ++ GST_PAD_ALWAYS, ++ generate_sink_template ()); ++ ++ gst_element_class_add_pad_template (element_class, template); ++ } ++} ++ ++static gboolean ++gst_omapfbsink_interface_supported (GstImplementsInterface * iface, GType type) ++{ ++ g_assert (type == GST_TYPE_X_OVERLAY); ++ return TRUE; ++} ++ ++static void ++gst_omapfbsink_interface_init (GstImplementsInterfaceClass * klass) ++{ ++ klass->supported = gst_omapfbsink_interface_supported; ++} ++ ++static void ++gst_omapfbsink_init (GstOmapFbSink * omapfbsink) ++{ ++ omapfbsink->display_name = NULL; ++ omapfbsink->xcontext = NULL; ++ omapfbsink->xwindow = NULL; ++ ++ omapfbsink->event_thread = NULL; ++ omapfbsink->running = FALSE; ++ ++ omapfbsink->x_lock = g_mutex_new (); ++ omapfbsink->flow_lock = g_mutex_new (); ++ ++ omapfbsink->handle_events = TRUE; ++ omapfbsink->colorKey = 0xff0; ++ ++ omapfbsink->plane_info.enabled = 0; ++ omapfbsink->row_skip = FALSE; ++ ++ omapfbsink->buffer = NULL; ++ omapfbsink->buffer_size = 0; ++ omapfbsink->hFc = NULL; ++} ++ ++GType ++gst_omapfbsink_get_type (void) ++{ ++ static GType type = 0; ++ ++ if (G_UNLIKELY (type == 0)) ++ { ++ GTypeInfo *type_info; ++ static const GInterfaceInfo iface_info = { ++ (GInterfaceInitFunc) gst_omapfbsink_interface_init, ++ NULL, ++ NULL, ++ }; ++ static const GInterfaceInfo overlay_info = { ++ (GInterfaceInitFunc) gst_omapfbsink_xoverlay_init, ++ NULL, ++ NULL, ++ }; ++ type_info = g_new0 (GTypeInfo, 1); ++ type_info->class_size = sizeof (GstOmapFbSinkClass); ++ type_info->base_init = type_base_init; ++ type_info->class_init = type_class_init; ++ type_info->instance_size = sizeof (GstOmapFbSink); ++ type_info->instance_init = (GInstanceInitFunc) gst_omapfbsink_init; ++ ++ type = g_type_register_static (GST_TYPE_BASE_SINK, "GstOmapFbSink", type_info, 0); ++ g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info); ++ g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &overlay_info); ++ ++ g_free (type_info); ++ } ++ ++ return type; ++} +diff -uNr ticodecplugin/src/omapfb.h ticodecplugin.new/src/omapfb.h +--- ticodecplugin/src/omapfb.h 1969-12-31 18:00:00.000000000 -0600 ++++ ticodecplugin.new/src/omapfb.h 2009-09-15 13:14:44.000000000 -0500 +@@ -0,0 +1,142 @@ ++/* ++ * Copyright (C) 2008 Felipe Contreras <felipe.contreras@gmail.com> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation ++ * version 2.1 of the License. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA ++ */ ++ ++#ifndef GST_OMAPFB_H ++#define GST_OMAPFB_H ++ ++#include <ti/sdo/dmai/BufferGfx.h> ++#include <ti/sdo/dmai/Framecopy.h> ++ ++#include "gsttidmaibuffertransport.h" ++#include <gst/gst.h> ++#include <gst/video/gstvideosink.h> ++#include <gst/video/video.h> ++ ++#include <X11/Xlib.h> ++#include <X11/Xutil.h> ++ ++#include <linux/fb.h> ++#include <linux/omapfb.h> ++ ++ ++G_BEGIN_DECLS ++ ++#define GST_OMAPFB_SINK_TYPE (gst_omapfbsink_get_type ()) ++#define GST_OMAPFB_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_OMAPFB_SINK_TYPE, GstOmapFbSink)) ++ ++typedef struct GstXContext GstXContext; ++typedef struct GstXWindow GstXWindow; ++typedef struct GstOmapFbSink GstOmapFbSink; ++typedef struct GstOmapFbSinkClass GstOmapFbSinkClass; ++ ++/** ++ * GstXWindow: ++ * @win: the Window ID of this X11 window ++ * @width: the width in pixels of Window @win ++ * @height: the height in pixels of Window @win ++ * @internal: used to remember if Window @win was created internally or passed ++ * through the #GstXOverlay interface ++ * @gc: the Graphical Context of Window @win ++ * ++ * Structure used to store informations about a Window. ++ */ ++struct GstXWindow { ++ Window win; ++ gint width, height; ++ gboolean internal; ++ GC gc; ++ ++ gint wx, wy; ++}; ++ ++/** ++ * GstXContext: ++ * @disp: the X11 Display of this context ++ * @screen: the default Screen of Display @disp ++ * @screen_num: the Screen number of @screen ++ * @visual: the default Visual of Screen @screen ++ * @root: the root Window of Display @disp ++ * @white: the value of a white pixel on Screen @screen ++ * @black: the value of a black pixel on Screen @screen ++ * @depth: the color depth of Display @disp ++ * @bpp: the number of bits per pixel on Display @disp ++ * @endianness: the endianness of image bytes on Display @disp ++ * @width: the width in pixels of Display @disp ++ * @height: the height in pixels of Display @disp ++ * ++ * Structure used to store various informations collected/calculated for a ++ * Display. ++ */ ++struct GstXContext { ++ Display *disp; ++ Screen *screen; ++ gint screen_num; ++ ++ Visual *visual; ++ Window root; ++ ++ gint depth; ++ gint bpp; ++ ++ gint width, height; ++}; ++ ++struct GstOmapFbSink ++{ ++ GstVideoSink videosink; ++ ++ struct fb_fix_screeninfo fixinfo; ++ struct fb_var_screeninfo varinfo; ++ struct fb_var_screeninfo overlay_info; ++ struct omapfb_mem_info mem_info; ++ struct omapfb_plane_info plane_info; ++ ++ int overlay_fd; ++ unsigned char *framebuffer; ++ gboolean enabled; ++ ++ GMutex *x_lock; ++ GMutex *flow_lock; ++ ++ GstXContext *xcontext; ++ GstXWindow *xwindow; ++ ++ gulong colorKey; ++ char *display_name; ++ GThread *event_thread; ++ ++ void *buffer; ++ guint buffer_size; ++ guint image_format; ++ ++ gboolean row_skip; ++ gboolean handle_events; ++ gboolean running; ++ Framecopy_Handle hFc; ++}; ++ ++struct GstOmapFbSinkClass ++{ ++ GstBaseSinkClass parent_class; ++}; ++ ++GType gst_omapfbsink_get_type (void); ++ ++G_END_DECLS ++ ++#endif /* GST_OMAPFB_H */ +diff -uNr ticodecplugin/src/yuv.S ticodecplugin.new/src/yuv.S +--- ticodecplugin/src/yuv.S 1969-12-31 18:00:00.000000000 -0600 ++++ ticodecplugin.new/src/yuv.S 2009-09-15 13:14:44.000000000 -0500 +@@ -0,0 +1,117 @@ ++/* ++ Copyright (C) 2008 Mans Rullgard ++ ++ Permission is hereby granted, free of charge, to any person ++ obtaining a copy of this software and associated documentation ++ files (the "Software"), to deal in the Software without ++ restriction, including without limitation the rights to use, copy, ++ modify, merge, publish, distribute, sublicense, and/or sell copies ++ of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice shall be ++ included in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ DEALINGS IN THE SOFTWARE. ++*/ ++ ++ .fpu neon ++ .text ++ ++@ yuv420_to_yuv422(uint8_t *yuv, uint8_t *y, uint8_t *u, uint8_t *v, ++@ int w, int h, int yw, int cw, int dw) ++ ++#define yuv r0 ++#define y r1 ++#define u r2 ++#define v r3 ++#define w r4 ++#define h r5 ++#define yw r6 ++#define cw r7 ++#define dw r8 ++ ++#define tyuv r9 ++#define ty r10 ++#define tu r11 ++#define tv r12 ++#define i lr ++ ++ .global yuv420_to_yuv422 ++ .func yuv420_to_yuv422 ++yuv420_to_yuv422: ++ push {r4-r11,lr} ++ add r4, sp, #36 ++ ldm r4, {r4-r8} ++1: ++ mov tu, u ++ mov tv, v ++ vld1.64 {d2}, [u,:64], cw @ u0 ++ vld1.64 {d3}, [v,:64], cw @ v0 ++ mov tyuv, yuv ++ mov ty, y ++ vzip.8 d2, d3 @ u0v0 ++ mov i, #16 ++2: ++ pld [y, #64] ++ vld1.64 {d0, d1}, [y,:128], yw @ y0 ++ pld [u, #64] ++ subs i, i, #4 ++ vld1.64 {d6}, [u,:64], cw @ u2 ++ pld [y, #64] ++ vld1.64 {d4, d5}, [y,:128], yw @ y1 ++ pld [v, #64] ++ vld1.64 {d7}, [v,:64], cw @ v2 ++ pld [y, #64] ++ vld1.64 {d16,d17}, [y,:128], yw @ y2 ++ vzip.8 d6, d7 @ u2v2 ++ pld [u, #64] ++ vld1.64 {d22}, [u,:64], cw @ u4 ++ pld [v, #64] ++ vld1.64 {d23}, [v,:64], cw @ v4 ++ pld [y, #64] ++ vld1.64 {d20,d21}, [y,:128], yw @ y3 ++ vmov q9, q3 @ u2v2 ++ vzip.8 d22, d23 @ u4v4 ++ vrhadd.u8 q3, q1, q3 @ u1v1 ++ vzip.8 q0, q1 @ y0u0y0v0 ++ vmov q12, q11 @ u4v4 ++ vzip.8 q2, q3 @ y1u1y1v1 ++ vrhadd.u8 q11, q9, q11 @ u3v3 ++ vst1.64 {d0-d3}, [yuv,:128], dw @ y0u0y0v0 ++ vzip.8 q8, q9 @ y2u2y2v2 ++ vst1.64 {d4-d7}, [yuv,:128], dw @ y1u1y1v1 ++ vzip.8 q10, q11 @ y3u3y3v3 ++ vst1.64 {d16-d19}, [yuv,:128], dw @ y2u2y2v2 ++ vmov q1, q12 ++ vst1.64 {d20-d23}, [yuv,:128], dw @ y3u3y3v3 ++ bgt 2b ++ subs w, w, #16 ++ add yuv, tyuv, #32 ++ add y, ty, #16 ++ add u, tu, #8 ++ add v, tv, #8 ++ bgt 1b ++ ++ ldr w, [sp, #36] ++ subs h, h, #16 ++ add yuv, yuv, dw, lsl #4 ++ sub yuv, yuv, w, lsl #1 ++ add y, y, yw, lsl #4 ++ sub y, y, w ++ add u, u, cw, lsl #3 ++ sub u, u, w, asr #1 ++ add v, v, cw, lsl #3 ++ sub v, v, w, asr #1 ++ bgt 1b ++ ++ pop {r4-r11,pc} ++ .endfunc ++ diff --git a/recipes/ti/gstreamer-ti_svn.bb b/recipes/ti/gstreamer-ti_svn.bb index 8fcc528019..e1782ba477 100644 --- a/recipes/ti/gstreamer-ti_svn.bb +++ b/recipes/ti/gstreamer-ti_svn.bb @@ -11,10 +11,11 @@ SRCREV = "335" SRC_URI = "svn://gforge.ti.com/svn/gstreamer_ti/trunk;module=gstreamer_ti;proto=https;user=anonymous;pswd='' \ file://gstreamer-ti-tracker-824.patch;patch=1 \ file://gstreamer-ti-tracker-462.patch;patch=1 \ + file://gstreamer-ti-add-omapfb.patch;patch=1 \ " # Again, no '.' in PWD allowed :( -PR = "r33" +PR = "r35" PV = "svnr${SRCREV}" S = "${WORKDIR}/gstreamer_ti/ti_build/ticodecplugin" @@ -66,7 +67,13 @@ PACKAGES += "gstreamer-ti-demo-script" FILES_gstreamer-ti-demo-script = "${installdir}/gst/*" RDEPENDS_gstreamer-ti-demo-script = "gstreamer-ti" -RDEPENDS_${PN} = "ti-dmai-apps" +RDEPENDS_${PN} = " \ +gst-plugins-base-meta \ +gst-plugins-good-meta \ +gst-plugins-bad-meta \ +gst-plugins-ugly-meta \ +ti-dmai-apps" + FILES_${PN} += "${libdir}/gstreamer-0.10/*.so" FILES_${PN}-dev += "${libdir}/gstreamer-0.10/*.a ${libdir}/gstreamer-0.10/*.la" FILES_${PN}-dbg += "${libdir}/gstreamer-0.10/.debug" |