summaryrefslogtreecommitdiff
path: root/recipes
diff options
context:
space:
mode:
authorBrijesh Singh <bksingh@ti.com>2009-09-15 14:17:02 -0500
committerKoen Kooi <k-kooi@ti.com>2009-09-17 10:02:26 +0200
commitcac885572c1429e0522935ffa0854bdf1ed15bcc (patch)
tree095b4d9f64eb7903c9c4aeba1be443482a7d87f5 /recipes
parent0624cfcd88665ee317e39d53be9febdba013a244 (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"
Diffstat (limited to 'recipes')
-rw-r--r--recipes/ti/gstreamer-ti/gstreamer-ti-add-omapfb.patch1336
-rw-r--r--recipes/ti/gstreamer-ti_svn.bb11
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"