[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r10609: XV support, part 2.
From: |
Bastiaan Jacques |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r10609: XV support, part 2. |
Date: |
Mon, 23 Feb 2009 05:13:31 +0100 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 10609
committer: Bastiaan Jacques <address@hidden>
branch nick: trunk
timestamp: Mon 2009-02-23 05:13:31 +0100
message:
XV support, part 2.
macros/x11.m4: Look for the Xv library and header file.
gui/am-frag/gtk.am: Build Xv if it's availabe on the system.
libbase/rc.{cpp,h}: Add "XVideo" boolean setting for gnashrc.
gui/gtk.cpp: If Xvideo is available and enabled in gnashrc, try to use
it and fall back on normal rendering if that fails.
gui/gtk_glue_agg_xv.{cpp,h}: Xv glue implementation that originates from
the proof-of-concept patch by Craig Kelley <address@hidden>.
gui/gui.h: Remove unused method.
libmedia/ffmpeg/VideoConverterFfmpeg.cpp: Add guard parenthesis around
struct initializer.
libmedia/gst/VideoConverterGst.cpp: Ensure that the decoder exists
before we attempt to clean it up.
added:
gui/gtk_glue_agg_xv.cpp
gui/gtk_glue_agg_xv.h
modified:
gui/am-frag/gtk.am
gui/gtk.cpp
gui/gui.h
libbase/rc.cpp
libbase/rc.h
libmedia/ffmpeg/VideoConverterFfmpeg.cpp
libmedia/gst/VideoConverterGst.cpp
macros/x11.m4
=== modified file 'gui/am-frag/gtk.am'
--- a/gui/am-frag/gtk.am 2008-02-17 02:04:26 +0000
+++ b/gui/am-frag/gtk.am 2009-02-23 04:13:31 +0000
@@ -42,6 +42,10 @@
gtk.cpp gtksup.h gtk_glue.h
gtk_gnash_LDADD = $(top_builddir)/backend/libgnashagg.la \
$(GNASH_LIBS) $(GTK_LIBS) $(AGG_LIBS) $(CAIRO_LIBS)
+if HAVE_XV
+gtk_gnash_SOURCES += gtk_glue_agg_xv.cpp gtk_glue_agg_xv.h
+gtk_gnash_LDADD += $(X11_LIBS)
+endif # HAVE_XV
endif # BUILD_AGG_RENDERER
if BUILD_CAIRO_RENDERER
gtk_gnash_CPPFLAGS += $(CAIRO_CFLAGS)
=== modified file 'gui/gtk.cpp'
--- a/gui/gtk.cpp 2009-02-12 15:15:22 +0000
+++ b/gui/gtk.cpp 2009-02-23 04:13:31 +0000
@@ -68,6 +68,9 @@
#ifdef RENDERER_AGG
#include "gtk_glue_agg.h"
+#ifdef HAVE_XV
+#include "gtk_glue_agg_xv.h"
+#endif // HAVE_XV
#endif
#ifdef GUI_HILDON
@@ -173,10 +176,28 @@
_glue.reset(new GtkCairoGlue);
#elif defined(RENDERER_OPENGL)
_glue.reset(new GtkGlExtGlue);
-#elif defined(RENDERER_AGG)
+#elif defined(RENDERER_AGG) && !defined(HAVE_XV)
_glue.reset(new GtkAggGlue);
-#endif
- _glue->init (argc, argv);
+#elif defined(RENDERER_AGG) && defined(HAVE_XV)
+ RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+
+ if (rcfile.useXv()) {
+ _glue.reset(new GtkAggXvGlue);
+ if (!_glue->init (argc, argv)) {
+ _glue.reset(new GtkAggGlue);
+ _glue->init(argc, argv);
+ }
+ } else {
+ _glue.reset(new GtkAggGlue);
+ _glue->init(argc, argv);
+ }
+#endif
+
+#if ! (defined(HAVE_XV) && defined(RENDERER_AGG))
+ if (!_glue->init (argc, argv)) {
+ return false;
+ }
+#endif
addPixmapDirectory (PKGDATADIR);
=== added file 'gui/gtk_glue_agg_xv.cpp'
--- a/gui/gtk_glue_agg_xv.cpp 1970-01-01 00:00:00 +0000
+++ b/gui/gtk_glue_agg_xv.cpp 2009-02-23 04:13:31 +0000
@@ -0,0 +1,636 @@
+//
+// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+/// \page gtk_shm_support GTK shared memory extension support
+///
+/// Xv glue for AGG.
+//
+/// Xv does hardware scaling for us.
+/// Thus, we should let the renderer render at a scale of 1 and we'll let
+/// Xv scale the rendered image to window size. Of course this destroys
+/// aspect ratio potentially set by the SWF.
+
+
+
+#include "gnash.h"
+#include "log.h"
+#include "render_handler.h"
+#include "render_handler_agg.h"
+#include "gtk_glue_agg_xv.h"
+#include "VideoConverter.h"
+#include "VM.h"
+
+#include <cerrno>
+
+#include <gdk/gdkx.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+namespace gnash
+{
+
+GtkAggXvGlue::GtkAggXvGlue()
+ : _agg_renderer(0),
+ _stride(0),
+ _xv_image(0),
+ _xv_image_is_shared(false),
+ _xv_port(std::numeric_limits<XvPortID>::max()),
+ _xv_max_width(0),
+ _xv_max_height(0),
+ _window_width(0),
+ _window_height(0),
+ _movie_width(0),
+ _movie_height(0),
+ _mediaHandler(media::MediaHandler::get()),
+ _shm_info(0)
+{
+ memset(&_xv_format, 0, sizeof(XvImageFormatValues));
+}
+
+GtkAggXvGlue::~GtkAggXvGlue()
+{
+ destroy_x_image();
+}
+
+bool
+GtkAggXvGlue::init(int /*argc*/, char **/*argv*/[])
+{
+ int dummy;
+ unsigned int p_version, p_release, p_request_base, p_event_base,
+ p_error_base;
+
+ if (!XQueryExtension(gdk_display, "XVideo", &dummy, &dummy, &dummy)) {
+ log_debug(_("WARNING: No XVideo extension available."));
+ return false;
+ }
+ if (XvQueryExtension(gdk_display, &p_version, &p_release, &p_request_base,
+ &p_event_base, &p_error_base) != Success) {
+ log_debug(_("WARNING: XVideo extension is available, but is not
currently ready."));
+ return false;
+ }
+
+ log_debug(_("GTK-AGG: XVideo available (version: %d, release: %d, "
+ "request base: %d, event base: %d, error base: %d)"),
+ p_version, p_release, p_request_base, p_event_base,
+ p_error_base);
+
+ return findXvPort(gdk_display);
+}
+
+void
+GtkAggXvGlue::prepDrawingArea(GtkWidget *drawing_area)
+{
+ _drawing_area = drawing_area;
+
+ gtk_widget_set_double_buffered(_drawing_area, FALSE);
+}
+
+render_handler*
+GtkAggXvGlue::createRenderHandler()
+{
+ _agg_renderer =
create_render_handler_agg(findPixelFormat(_xv_format).c_str());
+ return _agg_renderer;
+}
+
+void
+GtkAggXvGlue::setupRendering()
+{
+ static bool first = true;
+ if (first && VM::isInitialized()) {
+ first = false;
+
+ movie_definition* def = VM::get().getRoot().get_movie_definition();
+ assert(def);
+
+ _movie_width = def->get_width_pixels();
+ _movie_height = def->get_height_pixels();
+
+ if (!create_xv_shmimage(_movie_width, _movie_height)) {
+ if (!create_xv_image(_movie_width, _movie_height)) {
+ log_error(_("GTK-AGG: Could not create the Xv image."));
+ first = true;
+ return;
+ }
+ }
+
+ if (_xv_format.type == XvRGB) {
+ // init renderer to write directly to xv_image
+ static_cast<render_handler_agg_base *>(_agg_renderer)->init_buffer
+ ((unsigned char*) _xv_image->data, _xv_image->data_size,
+ _movie_width, _movie_height, _xv_image->pitches[0]);
+
+ } else {
+
+ int _bpp = 24;
+ int depth_bytes = _bpp / 8;
+
+ // 4 byte alignment. Gst expects this and ffmpeg doesn't object.
+ _stride = ( (_movie_width*depth_bytes) + 4 - 1 ) & ~( 4 - 1 );
+
+ int bufsize = _stride * _movie_height;
+
+ _offscreenbuf.reset(new unsigned char[bufsize]);
+
+ render_handler_agg_base * renderer =
+ static_cast<render_handler_agg_base *>(_agg_renderer);
+ renderer->init_buffer(_offscreenbuf.get(), bufsize, _movie_width,
+ _movie_height, _stride);
+
+ }
+ }
+}
+
+
+void
+GtkAggXvGlue::beforeRendering()
+{
+ setupRendering();
+
+ // We force the scale to its original state in case the GUI changed it (in
+ // the event of a resize), because we want Xv to do the scaling for us.
+ _agg_renderer->set_scale(1.0, 1.0);
+}
+
+void
+GtkAggXvGlue::render()
+{
+ render(0, 0, _movie_width, _movie_height);
+}
+
+void
+GtkAggXvGlue::render(int minx, int miny, int maxx, int maxy)
+{
+ if (!_drawing_area || !_xv_image) {
+ return;
+ }
+
+ if (_xv_format.type == XvYUV) {
+
+ boost::uint32_t imgtype = 0;
+ media::ImgBuf img(imgtype, _offscreenbuf.get(),
+ _stride*_movie_height,
+ _movie_width, _movie_height);
+ img.dealloc = media::ImgBuf::noop;
+ img.stride[0] = _stride;
+
+ std::auto_ptr<media::ImgBuf> buf = _video_converter->convert(img);
+ if (!buf.get()) {
+ log_error(_("RGB->YUV conversion failed."));
+ return;
+ }
+ if ((size_t)_xv_image->data_size != buf->size) {
+ log_error(_("Converter returned invalid YUV data size (exp: %d,
got %d)"),
+ _xv_image->data_size, buf->size);
+ return;
+ }
+
+
+ memcpy(_xv_image->data, buf->data, buf->size);
+ }
+
+ if (_xv_image_is_shared) {
+ XLockDisplay(gdk_display);
+
+ XvShmPutImage(
+ gdk_display,
+ _xv_port,
+ GDK_WINDOW_XWINDOW(_drawing_area->window),
+ GDK_GC_XGC(_drawing_area->style->fg_gc[GTK_STATE_NORMAL]), // ???
+ _xv_image,
+ //minx, miny, w, h,
+ 0, 0, _movie_width, _movie_height, /* source */
+ //minx2, miny2, w2, h2,
+ 0, 0, _window_width, _window_height, /* destination */
+ False);
+
+ XSync(gdk_display, False);
+
+ XUnlockDisplay (gdk_display);
+
+ } else {
+ XvPutImage(
+ gdk_display,
+ _xv_port,
+ GDK_WINDOW_XWINDOW(_drawing_area->window),
+ GDK_GC_XGC(_drawing_area->style->fg_gc[GTK_STATE_NORMAL]), // ???
+ _xv_image,
+ //minx, miny, w, h,
+ 0, 0, _movie_width, _movie_height, /* source */
+ //minx2, miny2, w2, h2,
+ 0, 0, _window_width, _window_height /* destination */);
+ }
+
+}
+
+void
+GtkAggXvGlue::configure(GtkWidget *const /*widget*/, GdkEventConfigure *const
event)
+{
+
+ _window_width = event->width;
+ _window_height = event->height;
+}
+
+
+void
+get_max_xv_image(Display *display, XvPortID xv_port,
+ unsigned int *width, unsigned int *height)
+{
+ XvEncodingInfo * encodings;
+ unsigned int num_encodings, idx;
+
+ XvQueryEncodings(display, xv_port, &num_encodings, &encodings);
+ if ( encodings ) {
+ for ( idx = 0; idx < num_encodings; ++idx ) {
+ if (std::equal(encodings[idx].name, encodings[idx].name+8,
"XV_IMAGE")) {
+ *width = encodings[idx].width;
+ *height = encodings[idx].height;
+ break;
+ }
+ }
+ }
+ log_debug("GTK-AGG: Maximum XVideo dimensions: %ux%u\n", *width, *height );
+ XvFreeEncodingInfo( encodings );
+}
+
+bool
+GtkAggXvGlue::findXvPort(Display* display)
+{
+ unsigned int num_adaptors;
+ XvAdaptorInfo* adaptor_info;
+
+ if ((XvQueryAdaptors(display, DefaultRootWindow(display), &num_adaptors,
+ &adaptor_info) != Success)) {
+ log_debug("GTK-AGG: WARNING: No XVideo adapters. Falling back to
non-Xv.");
+
+ return false;
+ }
+
+ log_debug("GTK-AGG: NOTICE: Found %d XVideo adapter(s) on GPU.",
num_adaptors);
+
+ for (unsigned int i = 0; i < num_adaptors; ++i) {
+
+ const XvAdaptorInfo& adaptor = adaptor_info[i];
+
+ if (!((adaptor.type & XvInputMask) &&
+ (adaptor.type & XvImageMask))) {
+ continue;
+ }
+
+ for (XvPortID port = adaptor.base_id;
+ port < adaptor.base_id + adaptor.num_ports;
+ ++port) {
+
+ int num_formats;
+ XvImageFormatValues* formats = XvListImageFormats(display, port,
&num_formats);
+
+ for (int j=0; j < num_formats; j++) {
+ const XvImageFormatValues& format = formats[j];
+
+ if (!isFormatBetter(_xv_format, format)) {
+ continue;
+ }
+
+ std::string agg_pixelformat = findPixelFormat(format);
+ if (agg_pixelformat.empty()) {
+ continue;
+ }
+
+ if (!ensurePortGrabbed(display, port)) {
+ continue;
+ }
+
+ _xv_format = format;
+ }
+
+ XFree(formats);
+ }
+ }
+
+ XvFreeAdaptorInfo(adaptor_info);
+
+ if (_xv_port != std::numeric_limits<XvPortID>::max()) {
+ const char fourcc[] = {(_xv_format.id & 0xFF),
+ (_xv_format.id >> 8) & 0xFF,
+ (_xv_format.id >> 16) & 0xFF,
+ (_xv_format.id >> 24) & 0xFF, 0};
+ log_debug(_("GTK-AGG: Selected format %s for Xv rendering."), fourcc);
+ get_max_xv_image(display, _xv_port, &_xv_max_width, &_xv_max_height);
+ }
+
+ return _xv_format.id != 0;
+}
+
+std::string
+GtkAggXvGlue::findPixelFormat(const XvImageFormatValues& format)
+{
+ std::string rv;
+
+ if ((format.type == XvRGB) && (format.format == XvPacked)) {
+
+ unsigned int red_shift, red_prec;
+ unsigned int green_shift, green_prec;
+ unsigned int blue_shift, blue_prec;
+
+ decode_mask(format.red_mask, &red_shift, &red_prec);
+ decode_mask(format.green_mask, &green_shift, &green_prec);
+ decode_mask(format.blue_mask, &blue_shift, &blue_prec);
+
+ const char *pixelformat = agg_detect_pixel_format(
+ red_shift, red_prec,
+ green_shift, green_prec,
+ blue_shift, blue_prec,
+ format.bits_per_pixel);
+
+ if (!pixelformat) {
+ log_debug("GTK-AGG: Unknown RGB format "
+ "'%d:%d:%d:%x:%x:%x' reported by Xv."
+ " Please report this to the gnash-dev "
+ "mailing list.", format.id,
+ format.bits_per_pixel, format.depth,
+ format.red_mask, format.green_mask,
+ format.blue_mask);
+ return rv;
+ }
+
+ rv = pixelformat;
+
+ } else {
+ std::auto_ptr<media::VideoConverter> converter =
+ _mediaHandler->createVideoConverter(0x32424752 /* RGB */,
format.id);
+
+ if (!converter.get()) {
+ return rv;
+ }
+
+ _video_converter = converter;
+
+ rv = "RGB24";
+ }
+
+ return rv;
+}
+
+bool
+GtkAggXvGlue::ensurePortGrabbed(Display *display, XvPortID port)
+{
+ if (port == _xv_port) {
+ return true;
+ }
+
+ if (!grabXvPort(display, port)) {
+ return false;
+ }
+
+ if (_xv_port != std::numeric_limits<XvPortID>::max()) {
+ XvUngrabPort(display, _xv_port, CurrentTime);
+ }
+
+ _xv_port = port;
+
+ return true;;
+}
+
+bool
+GtkAggXvGlue::isFormatBetter(const XvImageFormatValues& oldformat,
+ const XvImageFormatValues& newformat)
+{
+ if ( (newformat.type == XvRGB) ) {
+ if (oldformat.type != XvRGB) {
+ return true;
+ }
+
+ return (newformat.depth > oldformat.depth);
+ }
+
+ return newformat.bits_per_pixel > oldformat.bits_per_pixel;
+}
+
+void
+GtkAggXvGlue::decode_mask(unsigned long mask, unsigned int *shift, unsigned
int *size)
+{
+ *shift = 0;
+ *size = 0;
+
+ if (mask==0) return; // invalid mask
+
+ while (!(mask & 1)) {
+ (*shift)++;
+ mask = mask >> 1;
+ }
+
+ while (mask & 1) {
+ (*size)++;
+ mask = mask >> 1;
+ }
+}
+
+
+bool
+GtkAggXvGlue::grabXvPort(Display *display, XvPortID port)
+{
+ int status;
+
+ if ((status = XvGrabPort(display, port, CurrentTime)) == Success){
+ log_debug("GTK-AGG: XVideo successfully grabbed port %ld.",
+ (ptrdiff_t)port);
+ return true;
+ } else {
+ const char* reason;
+ switch (status) {
+ case XvInvalidTime:
+ reason = "XvInvalidTime";
+ break;
+ case XvAlreadyGrabbed:
+ reason = "XvAlreadyGrabbed";
+ break;
+ case XvBadExtension:
+ reason = "XvBadExtension";
+ break;
+ case XvBadAlloc:
+ reason = "XvBadAlloc";
+ break;
+ default:
+ reason = "Unknown";
+ }
+ log_debug("GTK-AGG: WARNING: Unable to XvGrabPort(%ld). Error: %s",
+ (unsigned long)port, reason);
+ }
+ return false;
+}
+
+bool
+GtkAggXvGlue::create_xv_image(unsigned int width, unsigned int height)
+{
+ destroy_x_image();
+
+ _xv_image = XvCreateImage (gdk_display, _xv_port,
+ _xv_format.id,
+ NULL, width, height);
+ if (!_xv_image) {
+ printf("GTK-AGG: XvCreateImage failed!");
+ return false;
+ }
+ if ((_xv_image->width < (int)width) || (_xv_image->height < (int)height)) {
+ log_debug("GTK-AGG: xv_image => XVideo requested %dx%d, got %dx%d.
Aborting.\n",
+ width, height, _xv_image->width, _xv_image->height);
+ destroy_x_image();
+ return false;
+ }
+ _xv_image->data = (char*)malloc(_xv_image->data_size);
+ if (!_xv_image->data) {
+ printf("GTK-AGG: Could not allocate %i bytes for Xv buffer: %s\n",
+ _xv_image->data_size, strerror(errno));
+ return false;
+ }
+ memset(_xv_image->data, 0, _xv_image->data_size);
+ _xv_image_is_shared = false;
+
+ log_debug(_("GTK-AGG: Created non-shared XvImage address@hidden, data=%#x,
%d bytes, %d planes."),
+ width, height, (ptrdiff_t)_xv_image, (ptrdiff_t)_xv_image->data,
+ _xv_image->data_size, _xv_image->num_planes);
+ return true;
+}
+
+bool
+GtkAggXvGlue::create_xv_shmimage(unsigned int width, unsigned int height)
+{
+ // First, we make sure that we can actually use XShm. Gdk seems to do a
+ // better job at detecting this than we traditionally have, so we'll just
+ // try to create small shared GdkImage.
+
+ assert(_drawing_area && _drawing_area->window);
+
+ GdkVisual* wvisual = gdk_drawable_get_visual(_drawing_area->window);
+
+ GdkImage* tmpimage = gdk_image_new (GDK_IMAGE_SHARED, wvisual, 1, 1);
+
+ if (tmpimage) {
+ gdk_image_destroy(tmpimage);
+ } else {
+ log_debug(_("GTK-AGG: XShm not supported; will use non-shared
memory."));
+ return false;
+ }
+
+ // destroy any already existing structures
+ destroy_x_image();
+
+ // prepare segment info (populated by XvShmCreateImage)
+ _shm_info = (XShmSegmentInfo*) malloc(sizeof(XShmSegmentInfo));
+ assert(_shm_info != NULL);
+
+ // create shared memory XImage
+ if ((width > _xv_max_width) || (height > _xv_max_height)) {
+ log_debug("GTK-AGG: xv_shmimage => %dx%d too big for XVideo", width,
height);
+ return false;
+ }
+ _xv_image = XvShmCreateImage(gdk_display, _xv_port,
+ _xv_format.id,
+ NULL, width, height, _shm_info);
+ if (!_xv_image) {
+ printf("GTK-AGG: XvShmCreateImage failed!");
+ return false;
+ }
+ if ((_xv_image->width < (int)width) || (_xv_image->height < (int)height)) {
+ log_debug("GTK-AGG: xv_shmimage => XVideo requested %dx%d, got %dx%d.
Aborting.\n",
+ width, height, _xv_image->width, _xv_image->height);
+ destroy_x_image();
+ return false;
+ }
+ _xv_image_is_shared = true;
+
+ // create shared memory segment
+ _shm_info->shmid = shmget(IPC_PRIVATE,
+ _xv_image->data_size,
+ IPC_CREAT|0777);
+ if (_shm_info->shmid == -1) {
+ printf("GTK-AGG: xv_shmimage => Failed requesting Xv shared memory
segment "
+ "(%s). Perhaps the "
+ "required memory size is bigger than the limit set by the
kernel.",
+ strerror(errno));
+ destroy_x_image();
+ return false;
+ }
+
+ // attach the shared memory segment to our process
+ _shm_info->shmaddr = _xv_image->data = (char*) shmat(_shm_info->shmid,
NULL, 0);
+
+ if (_shm_info->shmaddr == (char*)-1) {
+ printf("GTK-AGG: xv_shmimage => Failed attaching to Xv shared memory
segment: %s",
+ strerror(errno));
+ destroy_x_image();
+ return false;
+ }
+
+ // clear memory
+ memset(_xv_image->data, 0, _xv_image->data_size);
+
+ log_debug("GTK-AGG: Created shared XvImage address@hidden, data=%#x, %d
bytes.",
+ width, height, (ptrdiff_t)_xv_image, (ptrdiff_t)_xv_image->data,
+ _xv_image->data_size);
+
+ // Give the server full access to our memory segment. We just follow
+ // the documentation which recommends this, but we could also give him
+ // just read-only access since we don't need XShmGetImage...
+ _shm_info->readOnly = False;
+
+ // Finally, tell the server to attach to our shared memory segment
+ if (!XShmAttach(gdk_display, _shm_info)) {
+ printf("GTK-AGG: xv_shmimage => Server failed attaching to the shared "
+ "memory segment");
+ destroy_x_image();
+ return false;
+ }
+
+ XSync(gdk_display, False);
+
+ // mark segment for automatic destruction after last process detaches
+ shmctl(_shm_info->shmid, IPC_RMID, 0);
+
+ return true;
+}
+
+void
+GtkAggXvGlue::destroy_x_image()
+{
+ if (_xv_image) {
+ log_debug("GTK-AGG: destroy => Using XFree (XVideo) to dispose of "
+ "shared memory (%#x,%#x).", (ptrdiff_t)_xv_image,
(ptrdiff_t)_xv_image->data);
+ if (_xv_image->data != NULL) {
+ if (_xv_image_is_shared) {
+ shmdt(_xv_image->data);
+ } else {
+ XFree(_xv_image->data);
+ }
+ XFree(_xv_image);
+ }
+ _xv_image = NULL;
+ _xv_image_is_shared = false;
+ }
+
+ if (_shm_info) {
+ // TODO: call shmdt?
+ free(_shm_info);
+ _shm_info=NULL;
+ }
+}
+
+
+} // namespace gnash
+
=== added file 'gui/gtk_glue_agg_xv.h'
--- a/gui/gtk_glue_agg_xv.h 1970-01-01 00:00:00 +0000
+++ b/gui/gtk_glue_agg_xv.h 2009-02-23 04:13:31 +0000
@@ -0,0 +1,101 @@
+//
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "gtk_glue.h"
+#include "MediaHandler.h"
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <boost/scoped_array.hpp>
+
+#include <X11/Xlib.h>
+
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+
+
+namespace gnash
+{
+
+class GtkAggXvGlue : public GtkGlue
+{
+ public:
+ GtkAggXvGlue();
+ ~GtkAggXvGlue();
+
+ bool init(int argc, char **argv[]);
+ void prepDrawingArea(GtkWidget *drawing_area);
+ render_handler* createRenderHandler();
+ void beforeRendering();
+ void render();
+ void render(int minx, int miny, int maxx, int maxy);
+ void configure(GtkWidget *const widget, GdkEventConfigure *const event);
+
+ private:
+ bool findXvPort(Display* display);
+ bool grabXvPort(Display *display, XvPortID port);
+ bool create_xv_image(unsigned int width, unsigned int height);
+ bool create_xv_shmimage(unsigned int width, unsigned int height);
+ void destroy_x_image();
+ void setupRendering();
+ void decode_mask(unsigned long mask, unsigned int *shift, unsigned int
*size);
+ bool isFormatBetter(const XvImageFormatValues& oldformat,
+ const XvImageFormatValues& newformat);
+ bool ensurePortGrabbed(Display *display, XvPortID port);
+ std::string findPixelFormat(const XvImageFormatValues& format);
+
+ /// This will be used in case of RGB->YUV conversion.
+ boost::scoped_array<boost::uint8_t> _offscreenbuf;
+ render_handler *_agg_renderer;
+ size_t _stride;
+
+ /// If the hardware accepts RGB, then Agg will render directly into this.
+ XvImage* _xv_image;
+ bool _xv_image_is_shared;
+ XvPortID _xv_port;
+ unsigned int _xv_max_width;
+ unsigned int _xv_max_height;
+ int _window_width;
+ int _window_height;
+ int _movie_width;
+ int _movie_height;
+
+ media::MediaHandler* _mediaHandler;
+ std::auto_ptr<media::VideoConverter> _video_converter;
+
+ XvImageFormatValues _xv_format;
+
+ XShmSegmentInfo *_shm_info;
+};
+
+} // namespace gnash
+
+
+
+
+
+
+
+
+
+
=== modified file 'gui/gui.h'
--- a/gui/gui.h 2009-02-11 11:49:44 +0000
+++ b/gui/gui.h 2009-02-23 04:13:31 +0000
@@ -377,8 +377,6 @@
///
virtual bool yesno(const std::string& question);
- movie_root* getStage() const { return _stage; }
-
protected:
/// Default constructor. Initialises members to safe defaults.
=== modified file 'libbase/rc.cpp'
--- a/libbase/rc.cpp 2009-02-16 16:11:57 +0000
+++ b/libbase/rc.cpp 2009-02-23 04:13:31 +0000
@@ -104,7 +104,8 @@
_quality(-1),
_saveStreamingMedia(false),
_saveLoadedMedia(false),
- _popups(true)
+ _popups(true),
+ _useXv(false)
{
expandPath(_solsandbox);
@@ -482,6 +483,8 @@
||
extractSetting(_pluginSound, "pluginsound", variable, value)
||
+ extractSetting(_useXv, "xvideo", variable, value)
+ ||
extractSetting(_verboseASCodingErrors,
"ASCodingErrorsVerbosity", variable, value)
||
@@ -678,6 +681,7 @@
cmd << "ignoreFSCommand " << _ignoreFSCommand << endl <<
cmd << "saveStreamingMedia " << _saveStreamingMedia << endl <<
cmd << "saveLoadedMedia " << _saveLoadedMedia << endl <<
+ cmd << "XVideo " << _useXv << endl <<
// Strings.
@@ -744,6 +748,12 @@
}
void
+RcInitFile::useXv(bool value)
+{
+ _useXv = value;
+}
+
+void
RcInitFile::useLocalHost(bool value)
{
_localhostOnly = value;
=== modified file 'libbase/rc.h'
--- a/libbase/rc.h 2009-02-09 12:30:31 +0000
+++ b/libbase/rc.h 2009-02-23 04:13:31 +0000
@@ -134,6 +134,9 @@
bool useLocalDomain() const { return _localdomainOnly; }
void useLocalDomain(bool value);
+
+ bool useXv() const { return _useXv; }
+ void useXv(bool value);
/// Whether to restrict access to the local host
bool useLocalHost() const { return _localhostOnly; }
@@ -506,6 +509,8 @@
bool _popups;
+ bool _useXv;
+
};
// End of gnash namespace
=== modified file 'libmedia/ffmpeg/VideoConverterFfmpeg.cpp'
--- a/libmedia/ffmpeg/VideoConverterFfmpeg.cpp 2009-02-23 01:07:03 +0000
+++ b/libmedia/ffmpeg/VideoConverterFfmpeg.cpp 2009-02-23 04:13:31 +0000
@@ -128,7 +128,7 @@
#endif
- AVPicture srcpicture = {{src.data, 0, 0, 0}, src.stride[0], 0, 0, 0};
+ AVPicture srcpicture = {{src.data, 0, 0, 0}, {src.stride[0], 0, 0, 0}};
int bufsize = avpicture_get_size(dst_pixFmt, width, height);
@@ -140,7 +140,8 @@
AVPicture dstpicture;
avpicture_fill(&dstpicture, dstbuffer, dst_pixFmt, width, height);
-
+
+
#ifndef HAVE_SWSCALE_H
img_convert(&dstpicture, dst_pixFmt, &srcpicture, src_pixFmt, width,
height);
=== modified file 'libmedia/gst/VideoConverterGst.cpp'
--- a/libmedia/gst/VideoConverterGst.cpp 2009-02-21 14:19:48 +0000
+++ b/libmedia/gst/VideoConverterGst.cpp 2009-02-23 04:13:31 +0000
@@ -29,6 +29,8 @@
VideoConverterGst::VideoConverterGst(ImgBuf::Type4CC srcFormat,
ImgBuf::Type4CC dstFormat)
: VideoConverter(srcFormat, dstFormat)
{
+ _decoder.bin = 0;
+
gst_init (NULL, NULL);
GstElementFactory* colorspacefactory = gst_element_factory_find
("ffmpegcolorspace");
@@ -113,8 +115,10 @@
VideoConverterGst::~VideoConverterGst()
{
- swfdec_gst_decoder_push_eos(&_decoder);
- swfdec_gst_decoder_finish(&_decoder);
+ if (_decoder.bin) {
+ swfdec_gst_decoder_push_eos(&_decoder);
+ swfdec_gst_decoder_finish(&_decoder);
+ }
}
std::auto_ptr<ImgBuf>
=== modified file 'macros/x11.m4'
--- a/macros/x11.m4 2008-09-22 10:20:32 +0000
+++ b/macros/x11.m4 2009-02-23 04:13:31 +0000
@@ -43,6 +43,14 @@
if test x"${ac_cv_path_x11_incl}" = x ; then
AC_CHECK_HEADERS(X11/X.h, [ac_cv_path_x11_incl=""])
fi
+
+ dnl We want to know whether the headers for XShm exist.
+ if test x"${ac_cv_path_x11_incl}" != x ; then
+ includedirfound=`echo "${ac_cv_path_x11_incl}" | cut -b 3-`
+ if test -f "$includedirfound/X11/extensions/Xv.h"; then
+ xv_incl=yes
+ fi
+ fi
AC_MSG_CHECKING([for X11 headers])
if test x"${ac_cv_path_x11_incl}" != x ; then
@@ -88,7 +96,11 @@
ac_cv_path_x11_lib="${ac_cv_path_x11_lib} -lSM"
fi
if test -f $i/libICE.a -o -f $i/libICE.${shlibext}; then
- ac_cv_path_x11_lib="${ac_cv_path_x11_lib} -lICE"
+ ac_cv_path_x11_lib="${ac_cv_path_x11_lib} -lICE"
+ fi
+ if test -f $i/libXv.a -o -f $i/libXv.${shlibext}; then
+ ac_cv_path_x11_lib="${ac_cv_path_x11_lib} -lXv"
+ xv_lib=yes
fi
break
fi
@@ -126,6 +138,11 @@
if test "x$x11" = xyes; then
AC_DEFINE(HAVE_X11, [1], [X11 headers and libraries])
fi
+
+ if test x"$xv_incl" != x -a x"$xv_lib" != x; then
+ AC_DEFINE(HAVE_XV, [1], [X Video extension header and library])
+ fi
+ AM_CONDITIONAL(HAVE_XV, [ test x"$xv_incl" != x -a x"$xv_lib" != x ])
AC_SUBST(X11_CFLAGS)
AC_SUBST(X11_LIBS)
- [Gnash-commit] /srv/bzr/gnash/trunk r10609: XV support, part 2.,
Bastiaan Jacques <=