------------------------------------------------------------
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,
_______________________________________________
Gnash-commit mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/gnash-commit