gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r10604: XV support, part one: colors


From: Bastiaan Jacques
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10604: XV support, part one: colorspace conversion.
Date: Sat, 21 Feb 2009 15:19:48 +0100
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10604
committer: Bastiaan Jacques <address@hidden>
branch nick: trunk
timestamp: Sat 2009-02-21 15:19:48 +0100
message:
  XV support, part one: colorspace conversion.
  
  * libmedia/VideoConverter.h: Base class for video converter 
    implementations.
  * libmedia/MediaHandler.{h}: Media handler support for creating
    video converter objects.
  * libmedia/ffmpeg/MediaHandlerFfmpeg.{cpp,h}: Support creating 
    the ffmpeg video converter.
  * libmedia/gst/MediaHandlerGst.{cpp,h}: Idem dito.
  * libmedia/gst/swfdec_codec_gst.{c,h}: Add a function specifically
    for creating a colorspace conversion "pipeline".
  * libmedia/ffmpeg/VideoConverterFfmpeg{cpp,h}: Implementation of the
    ffmpeg video converter.
  * libmedia/gst/VideoConverterGst.{cpp,h}: Gstreamer video converter
    implementation.
  * libmedia/Makefile.am: Enable building of newly added files.
added:
  libmedia/VideoConverter.h
  libmedia/ffmpeg/VideoConverterFfmpeg.cpp
  libmedia/ffmpeg/VideoConverterFfmpeg.h
  libmedia/gst/VideoConverterGst.cpp
  libmedia/gst/VideoConverterGst.h
modified:
  libmedia/Makefile.am
  libmedia/MediaHandler.h
  libmedia/ffmpeg/MediaHandlerFfmpeg.cpp
  libmedia/ffmpeg/MediaHandlerFfmpeg.h
  libmedia/gst/MediaHandlerGst.cpp
  libmedia/gst/MediaHandlerGst.h
  libmedia/gst/swfdec_codec_gst.c
  libmedia/gst/swfdec_codec_gst.h
=== modified file 'libmedia/Makefile.am'
--- a/libmedia/Makefile.am      2009-01-22 20:10:39 +0000
+++ b/libmedia/Makefile.am      2009-02-21 14:19:48 +0000
@@ -81,6 +81,7 @@
 noinst_HEADERS = \
        AudioDecoder.h \
        VideoDecoder.h \
+       VideoConverter.h \
        MediaParser.h \
        MediaHandler.h \
        FLVParser.h \
@@ -97,6 +98,7 @@
                gst/VideoDecoderGst.cpp \
                gst/AudioDecoderGst.cpp \
                gst/MediaParserGst.cpp \
+               gst/VideoConverterGst.cpp \
                gst/GstUtil.cpp \
                gst/swfdec_codec_gst.c \
                $(NULL)
@@ -106,6 +108,7 @@
                gst/AudioDecoderGst.h \
                gst/VideoDecoderGst.h \
                gst/MediaParserGst.h \
+               gst/VideoConverterGst.cpp \
                gst/GstUtil.h \
                gst/swfdec_codec_gst.h \
                gst/gnash_gst_version.h \
@@ -129,6 +132,7 @@
                ffmpeg/AudioDecoderFfmpeg.cpp \
                ffmpeg/VideoDecoderFfmpeg.cpp \
                ffmpeg/AudioResamplerFfmpeg.cpp \
+               ffmpeg/VideoConverterFfmpeg.cpp \
                $(NULL)
 
    noinst_HEADERS += \
@@ -138,6 +142,7 @@
                ffmpeg/VideoDecoderFfmpeg.h \
                ffmpeg/AudioResamplerFfmpeg.h \
                ffmpeg/ffmpegHeaders.h \
+               ffmpeg/VideoConverterFfmpeg.h \
                $(NULL)
 
    libgnashmedia_la_LIBADD += \

=== modified file 'libmedia/MediaHandler.h'
--- a/libmedia/MediaHandler.h   2009-01-22 20:10:39 +0000
+++ b/libmedia/MediaHandler.h   2009-02-21 14:19:48 +0000
@@ -26,6 +26,7 @@
 
 #include "MediaParser.h" // for videoCodecType and audioCodecType enums
 #include "dsodefs.h" // DSOEXPORT
+#include "VideoConverter.h"
 
 #include <memory>
 
@@ -106,6 +107,15 @@
     ///             gnash::MediaException if a fatal error occurs.
        virtual std::auto_ptr<AudioDecoder> createAudioDecoder(const AudioInfo& 
info)=0;
 
+    /// Create an VideoConverter for converting between color spaces.
+    //
+    /// @param srcFormat The source image color space
+    /// @param dstFormat The destination image color space
+    ///
+    /// @return A valid VideoConverter or a NULL auto_ptr if a fatal error 
occurs.
+    virtual std::auto_ptr<VideoConverter>
+        createVideoConverter(ImgBuf::Type4CC srcFormat, ImgBuf::Type4CC 
dstFormat)=0;
+
     /// Return the number of bytes padding needed for input buffers
     //
     /// Bitstream readers are optimized to read several bytes at a time,

=== added file 'libmedia/VideoConverter.h'
--- a/libmedia/VideoConverter.h 1970-01-01 00:00:00 +0000
+++ b/libmedia/VideoConverter.h 2009-02-21 14:19:48 +0000
@@ -0,0 +1,113 @@
+//   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
+
+
+#ifndef GNASH_VIDEOCONVERTER_H
+#define GNASH_VIDEOCONVERTER_H
+
+#include <boost/noncopyable.hpp>
+#include <boost/cstdint.hpp>
+#include <memory>
+
+namespace gnash {
+namespace media {
+
+
+
+/// Image buffer wrapper
+//
+/// Unfortunately, the GnashImage buffer class currently insists on owning
+/// its buffer. Hacking around this results in things like gnashGstBuffer,
+/// which is less than desirable. Furthermore, it only supports a handful of
+/// pixel and image formats. Something more elaborate is needed to support the
+/// various YUV formats and different bit depths for RGB. But in the mean time:
+/// here's a simple image class for use in VideoConverter, at least until we
+/// merge the image classes.
+
+struct ImgBuf : public boost::noncopyable
+{
+    typedef boost::uint32_t Type4CC;
+    typedef void (*FreeFunc)(void*);
+
+    ImgBuf(Type4CC t, boost::uint8_t* dataptr, size_t datasize, size_t w,
+           size_t h)
+    : type(t),
+      data(dataptr),
+      size(datasize),
+      width(w),
+      height(h),
+      dealloc(array_delete)
+    {}
+    
+    ~ImgBuf()
+    {
+        dealloc(data);
+    }
+    
+    static void array_delete(void* voidptr)
+    {
+        boost::uint8_t* ptr = static_cast<boost::uint8_t*>(voidptr);
+        delete [] ptr;
+    }
+    
+    static void noop(void* /*voidptr*/)
+    {
+    }
+
+    Type4CC type;
+    boost::uint8_t* data;
+
+    size_t size; // in bytes
+    size_t width; // in pixels
+    size_t height; // in pixels
+    
+    size_t stride[4];
+    
+    FreeFunc dealloc;
+};
+
+
+/// Abstract base class for video image space conversion.
+
+class VideoConverter : public boost::noncopyable {
+
+public:
+    VideoConverter(ImgBuf::Type4CC srcFormat, ImgBuf::Type4CC dstFormat)
+     : _src_fmt(srcFormat),
+       _dst_fmt(dstFormat) 
+    {
+    }
+    
+    virtual ~VideoConverter()
+    {
+    }
+  
+    /// Convert a (video) image from one colorspace to another.
+    //
+    /// @param src the image to convert
+    /// @return the converted image or a NULL auto_ptr if an error occurred.
+    virtual std::auto_ptr<ImgBuf> convert(const ImgBuf& src) = 0;
+  
+protected:
+    ImgBuf::Type4CC  _src_fmt;
+    ImgBuf::Type4CC  _dst_fmt;
+};
+
+       
+} // gnash.media namespace 
+} // gnash namespace
+
+#endif // __VIDEOCONVERTER_H__

=== modified file 'libmedia/ffmpeg/MediaHandlerFfmpeg.cpp'
--- a/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp    2009-01-22 20:10:39 +0000
+++ b/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp    2009-02-21 14:19:48 +0000
@@ -24,6 +24,7 @@
 #include "AudioDecoderFfmpeg.h"
 #include "GnashException.h"
 #include "FLVParser.h"
+#include "VideoConverterFfmpeg.h"
 
 #include "IOChannel.h" // for visibility of destructor
 #include "MediaParser.h" // for visibility of destructor
@@ -64,6 +65,26 @@
        return ret;
 }
 
+std::auto_ptr<VideoConverter>
+MediaHandlerFfmpeg::createVideoConverter(ImgBuf::Type4CC srcFormat,
+                                         ImgBuf::Type4CC dstFormat)
+{
+    std::auto_ptr<VideoConverter> converter;
+
+    try
+    {
+        converter.reset(new VideoConverterFfmpeg(srcFormat, dstFormat));
+    }
+    catch (GnashException& ex)
+    {
+        log_error("Could not create Ffmpeg based video converter parser for "
+                "input format: %s", ex.what());
+    }
+    
+    return converter;
+}
+
+
 std::auto_ptr<AudioDecoder>
 MediaHandlerFfmpeg::createAudioDecoder(const AudioInfo& info)
 {

=== modified file 'libmedia/ffmpeg/MediaHandlerFfmpeg.h'
--- a/libmedia/ffmpeg/MediaHandlerFfmpeg.h      2008-10-27 11:20:47 +0000
+++ b/libmedia/ffmpeg/MediaHandlerFfmpeg.h      2009-02-21 14:19:48 +0000
@@ -51,6 +51,9 @@
        virtual std::auto_ptr<MediaParser> 
createMediaParser(std::auto_ptr<IOChannel> stream);
 
        virtual std::auto_ptr<VideoDecoder> createVideoDecoder(const VideoInfo& 
info);
+       
+       virtual std::auto_ptr<VideoConverter>
+               createVideoConverter(ImgBuf::Type4CC srcFormat, ImgBuf::Type4CC 
dstFormat);
 
        virtual std::auto_ptr<AudioDecoder> createAudioDecoder(const AudioInfo& 
info);
 

=== added file 'libmedia/ffmpeg/VideoConverterFfmpeg.cpp'
--- a/libmedia/ffmpeg/VideoConverterFfmpeg.cpp  1970-01-01 00:00:00 +0000
+++ b/libmedia/ffmpeg/VideoConverterFfmpeg.cpp  2009-02-21 14:19:48 +0000
@@ -0,0 +1,193 @@
+// 
+//     Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+//     Copyright (C) 1999-2008 the VideoLAN team
+// 
+// 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
+
+#include "VideoConverterFfmpeg.h"
+#include "GnashException.h"
+
+namespace gnash {
+namespace media {
+namespace ffmpeg {
+
+#ifdef HAVE_SWSCALE_H
+/// A wrapper round an SwsContext that ensures it's
+/// freed on destruction.
+class SwsContextWrapper
+{
+public:
+
+    SwsContextWrapper(SwsContext* context)
+        :
+        _context(context)
+    {}
+
+    ~SwsContextWrapper()
+    {
+         sws_freeContext(_context);
+    }
+    
+    SwsContext* getContext() const { return _context; }
+
+private:
+    SwsContext* _context;
+
+};
+#endif
+
+// The lookup table in this function is adapted from chroma.c from the VLC
+// codebase; its license permits distribution under GPLv3 and later.
+PixelFormat
+fourcc_to_ffmpeg(ImgBuf::Type4CC code)
+{
+
+#define GNASH_FOURCC( a, b, c, d ) \
+              ( ((uint32_t)a) | ( ((uint32_t)b) << 8 ) \
+              | ( ((uint32_t)c) << 16 ) | ( ((uint32_t)d) << 24 ) )   
+
+    static const struct
+    {
+        ImgBuf::Type4CC  fourcc;
+        PixelFormat ffmpegcode;
+    } pixfmt_table[] =
+    {
+        // Planar YUV formats
+        {GNASH_FOURCC('I','4','4','4'), PIX_FMT_YUV444P},
+        {GNASH_FOURCC('J','4','4','4'), PIX_FMT_YUVJ444P},
+
+#if LIBAVUTIL_VERSION_INT >= ((49<<16)+(5<<8)+0)
+        {GNASH_FOURCC('I','4','4','0'), PIX_FMT_YUV440P},
+        {GNASH_FOURCC('J','4','4','0'), PIX_FMT_YUVJ440P},
+#endif
+
+        {GNASH_FOURCC('I','4','2','2'), PIX_FMT_YUV422P},
+        {GNASH_FOURCC('J','4','2','2'), PIX_FMT_YUVJ422P},
+
+        {GNASH_FOURCC('I','4','2','0'), PIX_FMT_YUV420P},
+        {GNASH_FOURCC('Y','V','1','2'), PIX_FMT_YUV420P},
+        {GNASH_FOURCC('I','Y','U','V'), PIX_FMT_YUV420P},
+        {GNASH_FOURCC('J','4','2','0'), PIX_FMT_YUVJ420P},
+        {GNASH_FOURCC('I','4','1','1'), PIX_FMT_YUV411P},
+        {GNASH_FOURCC('I','4','1','0'), PIX_FMT_YUV410P},
+        {GNASH_FOURCC('Y','V','U','9'), PIX_FMT_YUV410P},
+
+        {GNASH_FOURCC('N','V','1','2'), PIX_FMT_NV12},
+        {GNASH_FOURCC('N','V','2','1'), PIX_FMT_NV21},
+
+        {GNASH_FOURCC('Y','U','Y','2'), PIX_FMT_YUYV422},
+        {GNASH_FOURCC('Y','U','Y','V'), PIX_FMT_YUYV422},
+        {GNASH_FOURCC('U','Y','V','Y'), PIX_FMT_UYVY422},
+        {GNASH_FOURCC('Y','4','1','1'), PIX_FMT_UYYVYY411},
+
+        { 0, PIX_FMT_NONE}
+    };
+#undef GNASH_FOURCC
+
+    for (int i = 0; pixfmt_table[i].fourcc != 0; i++ ) {
+    
+        if (pixfmt_table[i].fourcc == code) {
+            return pixfmt_table[i].ffmpegcode;
+        }
+    }
+   
+    return PIX_FMT_NONE;
+}
+
+VideoConverterFfmpeg::VideoConverterFfmpeg(ImgBuf::Type4CC srcFormat, 
ImgBuf::Type4CC dstFormat)
+    : VideoConverter(srcFormat, dstFormat)
+{
+     if(fourcc_to_ffmpeg(_dst_fmt) == PIX_FMT_NONE) {
+         throw MediaException(_("VideoConverterFfmpeg cannot convert to the "
+                              "requested format"));
+     }
+}
+
+VideoConverterFfmpeg::~VideoConverterFfmpeg()
+{
+  
+}
+
+
+std::auto_ptr<ImgBuf>
+VideoConverterFfmpeg::convert(const ImgBuf& src)
+{
+    std::auto_ptr<ImgBuf> ret;    
+    
+    const int width = src.width;
+    const int height = src.height;
+
+    PixelFormat dst_pixFmt = fourcc_to_ffmpeg(_dst_fmt);
+    assert(dst_pixFmt != PIX_FMT_NONE);
+    PixelFormat src_pixFmt = PIX_FMT_RGB24;
+    
+#ifdef HAVE_SWSCALE_H
+
+    if (!_swsContext.get()) {
+
+        _swsContext.reset(new SwsContextWrapper(sws_getContext(width, height,
+            src_pixFmt, width, height, dst_pixFmt, SWS_BILINEAR, NULL, NULL,
+            NULL)));
+
+        if (!_swsContext->getContext()) {
+
+            // This means we will try to assign the 
+            // context again next time.
+            _swsContext.reset();
+            
+            return ret;
+        }
+    }
+#endif
+
+
+    AVPicture srcpicture = {{src.data, 0, 0, 0}, src.stride[0], 0, 0, 0};
+    
+    
+    int bufsize = avpicture_get_size(dst_pixFmt, width, height);
+    if (bufsize == -1) {
+        return ret;
+    }
+
+    boost::uint8_t* dstbuffer = new boost::uint8_t[bufsize];
+
+    AVPicture dstpicture;
+    avpicture_fill(&dstpicture, dstbuffer, dst_pixFmt, width, height);
+
+#ifndef HAVE_SWSCALE_H
+    img_convert(&dstpicture, dst_pixFmt, &srcpicture, src_pixFmt, width,
+                height);
+#else
+
+    int rv = sws_scale(_swsContext->getContext(), srcpicture.data,
+                       srcpicture.linesize, 0, height, dstpicture.data,
+                       dstpicture.linesize);
+
+    if (rv == -1) {
+        return ret;
+    }
+#endif    
+    ret.reset(new ImgBuf(_dst_fmt, dstbuffer, bufsize, src.width,
+                         src.height));
+    std::copy(dstpicture.linesize, dstpicture.linesize+4, ret->stride); 
+ 
+    return ret;
+}
+
+
+
+} // gnash.media.ffmpeg namespace 
+} // gnash.media namespace 
+} // gnash namespace

=== added file 'libmedia/ffmpeg/VideoConverterFfmpeg.h'
--- a/libmedia/ffmpeg/VideoConverterFfmpeg.h    1970-01-01 00:00:00 +0000
+++ b/libmedia/ffmpeg/VideoConverterFfmpeg.h    2009-02-21 14:19:48 +0000
@@ -0,0 +1,62 @@
+//
+//     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
+
+
+#ifndef GNASH_VIDEOCONVERTERFFMPEG_H
+#define GNASH_VIDEOCONVERTERFFMPEG_H
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "ffmpegHeaders.h"
+#include "VideoConverter.h"
+
+#include "log.h"
+
+#if HAVE_SWSCALE_H
+#include <libswscale/swscale.h>
+#endif
+
+
+namespace gnash {
+namespace media {
+namespace ffmpeg {
+
+class SwsContextWrapper;
+
+class VideoConverterFfmpeg : public VideoConverter {
+
+public:
+    VideoConverterFfmpeg(ImgBuf::Type4CC srcFormat, ImgBuf::Type4CC dstFormat);
+    
+    ~VideoConverterFfmpeg();
+
+    std::auto_ptr<ImgBuf> convert(const ImgBuf& src);
+  
+private:
+
+#if HAVE_SWSCALE_H
+    std::auto_ptr<SwsContextWrapper> _swsContext;
+#endif
+};
+
+}
+}
+}
+
+#endif // GNASH_VIDEOCONVERTERFFMPEG_H

=== modified file 'libmedia/gst/MediaHandlerGst.cpp'
--- a/libmedia/gst/MediaHandlerGst.cpp  2009-01-22 20:10:39 +0000
+++ b/libmedia/gst/MediaHandlerGst.cpp  2009-02-21 14:19:48 +0000
@@ -22,6 +22,7 @@
 #include "VideoDecoderGst.h"
 #include "AudioDecoderGst.h"
 #include "MediaParserGst.h"
+#include "VideoConverterGst.h"
 #include "FLVParser.h"
 
 #ifdef DECODING_SPEEX
@@ -132,6 +133,24 @@
        return ret;
 }
 
+std::auto_ptr<VideoConverter>
+MediaHandlerGst::createVideoConverter(ImgBuf::Type4CC srcFormat, 
ImgBuf::Type4CC dstFormat)
+{
+    std::auto_ptr<VideoConverter> converter;
+
+    try
+    {
+        converter.reset(new VideoConverterGst(srcFormat, dstFormat));
+    }
+    catch (GnashException& ex)
+    {
+        log_error("Could not create Gstreamer based video converter parser for 
"
+                "input format: %s", ex.what());
+    }
+    
+    return converter;
+}
+
 } // gnash.media.gst namespace
 } // gnash.media namespace 
 } // gnash namespace

=== modified file 'libmedia/gst/MediaHandlerGst.h'
--- a/libmedia/gst/MediaHandlerGst.h    2008-10-27 11:20:47 +0000
+++ b/libmedia/gst/MediaHandlerGst.h    2009-02-21 14:19:48 +0000
@@ -53,6 +53,9 @@
        virtual std::auto_ptr<VideoDecoder> createVideoDecoder(const VideoInfo& 
info);
 
        virtual std::auto_ptr<AudioDecoder> createAudioDecoder(const AudioInfo& 
info);
+       
+       virtual std::auto_ptr<VideoConverter> 
createVideoConverter(ImgBuf::Type4CC srcFormat,
+                                                              ImgBuf::Type4CC 
dstFormat);
 };
 
 

=== added file 'libmedia/gst/VideoConverterGst.cpp'
--- a/libmedia/gst/VideoConverterGst.cpp        1970-01-01 00:00:00 +0000
+++ b/libmedia/gst/VideoConverterGst.cpp        2009-02-21 14:19:48 +0000
@@ -0,0 +1,162 @@
+//   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
+
+#include "VideoConverterGst.h"
+#include "MediaParser.h"
+#include "log.h"
+#include <cassert>
+
+
+namespace gnash {
+namespace media {
+namespace gst {
+
+/// Base class for video image space conversion.
+
+VideoConverterGst::VideoConverterGst(ImgBuf::Type4CC srcFormat, 
ImgBuf::Type4CC dstFormat)
+    : VideoConverter(srcFormat, dstFormat)
+{
+    gst_init (NULL, NULL);
+    
+    GstElementFactory* colorspacefactory = gst_element_factory_find 
("ffmpegcolorspace");
+    if (!colorspacefactory) {
+        throw MediaException(_("VideoConverterGst: ffmpegcolorspace element 
missing"));
+    }   
+
+    GstCaps* caps = gst_caps_new_simple("video/x-raw-yuv",
+                                        "format", GST_TYPE_FOURCC, _dst_fmt,
+                                        NULL); 
+
+    // Verify that ffmpegcolorspace can actually convert to the requested fmt.
+    bool found = false;
+    for (const GList* walk = gst_element_factory_get_static_pad_templates 
(colorspacefactory);
+         walk; walk = walk->next) {
+        GstStaticPadTemplate* templ = (GstStaticPadTemplate*) walk->data;
+
+        if (templ->direction != GST_PAD_SRC) {
+            continue;
+        }
+
+        GstCaps* template_caps = gst_static_caps_get (&templ->static_caps);
+        GstCaps* intersect = gst_caps_intersect (caps, template_caps);   
+        gst_caps_unref (template_caps);
+    
+        found = !gst_caps_is_empty (intersect);    
+        gst_caps_unref (intersect);
+
+        if (found) {
+            break;
+        }
+    }
+
+    gst_caps_unref(caps);
+    gst_object_unref(colorspacefactory);
+
+    if (!found) {
+         throw MediaException(_("VideoConverterGst: can't output requested 
format"));
+    }
+}
+
+bool
+VideoConverterGst::init(const ImgBuf& src)
+{
+    // FIXME: mask values are probably wrong.
+    GstCaps* srccaps = gst_caps_new_simple("video/x-raw-rgb",
+            "bpp", G_TYPE_INT, 24,
+            "depth", G_TYPE_INT, 24,
+            "width", G_TYPE_INT, src.width,
+            "height", G_TYPE_INT, src.height,
+            "red_mask", G_TYPE_INT, 16711680,
+            "green_mask", G_TYPE_INT, 65280,
+            "blue_mask", G_TYPE_INT, 255,
+            "endianness",G_TYPE_INT,  4321,
+            "framerate", GST_TYPE_FRACTION, 0, 1,
+            NULL);
+
+    GstCaps* sinkcaps = gst_caps_new_simple("video/x-raw-yuv",
+            "format", GST_TYPE_FOURCC, _dst_fmt,
+            "width", G_TYPE_INT, src.width,
+            "height", G_TYPE_INT, src.height,
+            "framerate", GST_TYPE_FRACTION, 0, 1,
+            NULL);
+
+    if (!sinkcaps || !srccaps) {
+        log_error(_("VideoConverterGst: internal error "
+                    "(caps creation failed)"));    
+        return false;  
+    }
+
+    bool rv = swfdec_gst_colorspace_init (&_decoder, srccaps, sinkcaps);
+    if (!rv) {
+        log_error(_("VideoConverterGst: initialisation failed."));
+        return false;
+    }
+
+    gst_caps_unref (srccaps);
+    gst_caps_unref (sinkcaps);
+    
+    return true;
+}
+
+VideoConverterGst::~VideoConverterGst()
+{
+    swfdec_gst_decoder_push_eos(&_decoder);
+    swfdec_gst_decoder_finish(&_decoder);
+}
+
+std::auto_ptr<ImgBuf>
+VideoConverterGst::convert(const ImgBuf& src)
+{
+    std::auto_ptr<ImgBuf> ret;
+    
+    if (!init(src)) {
+        return ret;  
+    }
+
+    GstBuffer* buffer = gst_buffer_new();
+
+    GST_BUFFER_DATA(buffer) = const_cast<boost::uint8_t*>(src.data);
+    GST_BUFFER_SIZE(buffer) = src.size;
+    GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_READONLY);
+
+    bool success = swfdec_gst_decoder_push(&_decoder, buffer);
+    if (!success) {
+        log_error(_("VideoConverterGst: buffer push failed."));
+        return ret;
+    }
+    
+    GstBuffer* retbuffer = swfdec_gst_decoder_pull (&_decoder);
+
+    if (!retbuffer) {
+        log_error(_("VideoConverterGst: buffer pull failed."));
+        return ret;
+    }
+  
+    ret.reset(new ImgBuf(_dst_fmt, GST_BUFFER_DATA(retbuffer),
+                         GST_BUFFER_SIZE(retbuffer), src.width, src.height));
+
+    GST_BUFFER_MALLOCDATA(retbuffer) = 0; // don't free
+    gst_buffer_unref(retbuffer);
+    
+    ret->dealloc = g_free;
+  
+    return ret;
+}
+
+} // gnash.media.gst namespace
+} // gnash.media namespace 
+} // gnash namespace
+

=== added file 'libmedia/gst/VideoConverterGst.h'
--- a/libmedia/gst/VideoConverterGst.h  1970-01-01 00:00:00 +0000
+++ b/libmedia/gst/VideoConverterGst.h  2009-02-21 14:19:48 +0000
@@ -0,0 +1,53 @@
+//   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
+
+
+#ifndef GNASH_VIDEOCONVERTERGST_H
+#define GNASH_VIDEOCONVERTERGST_H
+
+#include "VideoConverter.h"
+#include "swfdec_codec_gst.h"
+
+
+
+#include <gst/gst.h>
+
+namespace gnash {
+namespace media {
+namespace gst {
+
+/// Base class for video image space conversion.
+
+class VideoConverterGst : public VideoConverter {
+
+public:
+    VideoConverterGst(ImgBuf::Type4CC srcFormat, ImgBuf::Type4CC dstFormat);
+    
+    ~VideoConverterGst();
+  
+    std::auto_ptr<ImgBuf> convert(const ImgBuf& src);
+    
+    bool init(const ImgBuf& src);
+  
+private:
+    SwfdecGstDecoder _decoder;
+};
+
+} // gnash.media.gst namespace
+} // gnash.media namespace 
+} // gnash namespace
+
+#endif // __VIDEOCONVERTERGST_H__

=== modified file 'libmedia/gst/swfdec_codec_gst.c'
--- a/libmedia/gst/swfdec_codec_gst.c   2008-10-05 00:08:38 +0000
+++ b/libmedia/gst/swfdec_codec_gst.c   2009-02-21 14:19:48 +0000
@@ -234,6 +234,37 @@
 }
 
 gboolean
+swfdec_gst_colorspace_init (SwfdecGstDecoder *dec, GstCaps *srccaps, GstCaps 
*sinkcaps)
+{
+  GstElement *converter;
+
+  dec->bin = gst_bin_new ("bin");
+
+  converter = gst_element_factory_make ("ffmpegcolorspace", NULL);
+  if (converter == NULL) {
+    SWFDEC_ERROR ("failed to create converter");
+    return FALSE;
+  }
+  gst_bin_add (GST_BIN (dec->bin), converter);
+  dec->src = swfdec_gst_connect_srcpad (converter, srccaps);
+  if (dec->src == NULL)
+    return FALSE;
+
+  dec->sink = swfdec_gst_connect_sinkpad (converter, sinkcaps);
+  if (dec->sink == NULL)
+    return FALSE;
+  gst_pad_set_chain_function (dec->sink, swfdec_gst_chain_func);
+  dec->queue = g_queue_new ();
+  g_object_set_data (G_OBJECT (dec->sink), "swfdec-queue", dec->queue);
+  if (!gst_element_set_state (dec->bin, GST_STATE_PLAYING) == 
GST_STATE_CHANGE_SUCCESS) {
+    SWFDEC_ERROR ("could not change element state");
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+gboolean
 swfdec_gst_decoder_init (SwfdecGstDecoder *dec, GstCaps *srccaps, GstCaps 
*sinkcaps, ...)
 {
   va_list args;

=== modified file 'libmedia/gst/swfdec_codec_gst.h'
--- a/libmedia/gst/swfdec_codec_gst.h   2008-10-05 00:08:38 +0000
+++ b/libmedia/gst/swfdec_codec_gst.h   2009-02-21 14:19:48 +0000
@@ -37,6 +37,11 @@
                                                 GstCaps *              srccaps,
                                                 GstCaps *              
sinkcaps,
                                                 ...) G_GNUC_NULL_TERMINATED;
+
+gboolean       swfdec_gst_colorspace_init      (SwfdecGstDecoder *     dec,
+                                                GstCaps *              srccaps,
+                                                GstCaps *              
sinkcaps);
+                                                
 void           swfdec_gst_decoder_push_eos     (SwfdecGstDecoder *     dec);
 GstBuffer *    swfdec_gst_decoder_pull         (SwfdecGstDecoder *     dec);
 gboolean       swfdec_gst_decoder_push         (SwfdecGstDecoder *     dec,


reply via email to

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