gnash-commit
[Top][All Lists]
Advanced

[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)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]