[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r9656: Fix segfault when video pitch
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r9656: Fix segfault when video pitch is not a multiple of 4. Fix segfault when |
Date: |
Mon, 01 Sep 2008 16:35:49 +0200 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 9656
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Mon 2008-09-01 16:35:49 +0200
message:
Fix segfault when video pitch is not a multiple of 4. Fix segfault when
decoder setup fails for embedded video. Don't abort when an unknown codec
is encountered; instead, log error, fail to construct a VideoDecoder, and
continue. Also don't construct a VideoDecoder when other fatal errors
occur.
Add MediaException class for use in libmedia.
modified:
libbase/GnashException.h
libbase/image.cpp
libcore/asobj/NetStreamFfmpeg.cpp
libcore/video_stream_instance.cpp
libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
libmedia/ffmpeg/VideoDecoderFfmpeg.h
------------------------------------------------------------
revno: 9653.1.8
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-09-01 12:51:19 +0200
message:
Set width to nearest 4-byte boundary, which fixes display (and segfaults)
for some SWFs.
modified:
libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
------------------------------------------------------------
revno: 9653.1.9
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-09-01 15:09:28 +0200
message:
Don't adjust image pitch to be a multiple of four bytes, as this causes
segfaults where that's not the case. If anyone knows of a case where
this is necessary, please let me know.
Add a MediaException subclass of GnashException.
modified:
libbase/GnashException.h
libbase/image.cpp
------------------------------------------------------------
revno: 9653.1.10
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-09-01 15:10:41 +0200
message:
Throw an exception on construction of a VideoDecoder when a fatal error
(such as not finding a suitable codec) means that decoding would be
impossible. This prevents future calls to decode() when there's nothing
to do.
Catch a MediaException in NetStreamFfmpeg.cpp, log and continue.
Wrap AVCodecContext so that it is always closed and freed when it exists
when VideoDecoder is destroyed. This could also be used for AudioDecoder.
modified:
libcore/asobj/NetStreamFfmpeg.cpp
libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
libmedia/ffmpeg/VideoDecoderFfmpeg.h
------------------------------------------------------------
revno: 9653.1.11
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-09-01 15:24:45 +0200
message:
If there's no decoder, don't try to use it.
modified:
libcore/video_stream_instance.cpp
------------------------------------------------------------
revno: 9653.1.12
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-09-01 15:30:43 +0200
message:
Use the actual codec, not 0 (was for testing). Improve logging text.
modified:
libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
=== modified file 'libbase/GnashException.h'
--- a/libbase/GnashException.h 2008-06-11 19:54:43 +0000
+++ b/libbase/GnashException.h 2008-09-01 13:09:28 +0000
@@ -49,8 +49,27 @@
std::string _msg;
};
+class MediaException : public GnashException
+{
+
+public:
+
+ MediaException(const std::string& s)
+ :
+ GnashException(s)
+ {}
+
+ MediaException()
+ :
+ GnashException("Media error")
+ {}
+
+ virtual ~MediaException() throw() {}
+
+};
+
/// An SWF parsing exception
-class ParserException: public GnashException
+class ParserException : public GnashException
{
public:
=== modified file 'libbase/image.cpp'
--- a/libbase/image.cpp 2008-08-18 23:53:04 +0000
+++ b/libbase/image.cpp 2008-09-01 13:09:28 +0000
@@ -104,13 +104,10 @@
ImageRGB::ImageRGB(int width, int height)
:
ImageBase( width, height,
- (width * 3 + 3) & ~3, // round pitch up to nearest
4-byte boundary
- GNASH_IMAGE_RGB)
+ width * 3, GNASH_IMAGE_RGB)
{
assert(width > 0);
assert(height > 0);
- assert(_pitch >= _width * 3);
- assert((_pitch & 3) == 0);
}
ImageRGB::~ImageRGB()
=== modified file 'libcore/asobj/NetStreamFfmpeg.cpp'
--- a/libcore/asobj/NetStreamFfmpeg.cpp 2008-08-27 11:07:07 +0000
+++ b/libcore/asobj/NetStreamFfmpeg.cpp 2008-09-01 13:10:41 +0000
@@ -199,9 +199,13 @@
assert ( _mediaHandler ); // caller should check this
- _videoDecoder = _mediaHandler->createVideoDecoder(*videoInfo);
- if ( ! _videoDecoder.get() )
- log_error(_("Could not create video decoder for codec %d"),
videoInfo->codec);
+ try {
+ _videoDecoder = _mediaHandler->createVideoDecoder(*videoInfo);
+ }
+ catch (MediaException& e) {
+ log_error("Could not create Video decoder: %s", e.what());
+ }
+
}
=== modified file 'libcore/video_stream_instance.cpp'
--- a/libcore/video_stream_instance.cpp 2008-08-18 23:53:04 +0000
+++ b/libcore/video_stream_instance.cpp 2008-09-01 13:24:45 +0000
@@ -161,7 +161,6 @@
void
video_stream_instance::initializeDecoder()
{
- //if ( _decoder.get() ) return; // already initialized
media::MediaHandler* mh = media::MediaHandler::get();
if ( ! mh )
@@ -178,11 +177,13 @@
return;
}
- _decoder = mh->createVideoDecoder(*info);
- if ( ! _decoder.get() )
+ try
+ {
+ _decoder = mh->createVideoDecoder(*info);
+ }
+ catch (MediaException &e)
{
- log_error(_("Could not create video decoder from VideoInfo
%s"), *info);
- return;
+ log_error("Could not create Video Decoder: %s", e.what());
}
}
@@ -247,6 +248,12 @@
// If this is a video from a VideoFrame tag, retrieve a video frame
from there.
else if (_embeddedStream)
{
+
+ // Don't try to do anything if there is no decoder. If it was
+ // never constructed (most likely), we'll return nothing,
+ // otherwise the last decoded frame.
+ if (!_decoder.get()) return _lastDecodedVideoFrame.get();
+
int current_frame = get_ratio();
#ifdef DEBUG_EMBEDDED_VIDEO_DECODING
=== modified file 'libmedia/ffmpeg/VideoDecoderFfmpeg.cpp'
--- a/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp 2008-08-28 22:48:50 +0000
+++ b/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp 2008-09-01 13:30:43 +0000
@@ -1,6 +1,6 @@
// VideoDecoderFfmpeg.cpp: Video decoding using the FFMPEG library.
//
-// Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+// Copyright (C) 2007, 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
@@ -9,17 +9,18 @@
//
// 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
+// 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
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA
//
#include "VideoDecoderFfmpeg.h"
#include "MediaParserFfmpeg.h" // for ExtraVideoInfoFfmpeg
+#include "GnashException.h" // for MediaException
#ifdef HAVE_FFMPEG_SWSCALE_H
#define HAVE_SWSCALE_H 1
@@ -36,6 +37,7 @@
#endif
#include <boost/scoped_array.hpp>
+#include <boost/format.hpp>
#include <algorithm>
namespace gnash {
@@ -58,7 +60,7 @@
sws_freeContext(_context);
}
- SwsContext* getContext() { return _context; }
+ SwsContext* getContext() const { return _context; }
private:
SwsContext* _context;
@@ -66,91 +68,120 @@
};
#endif
+// A Wrapper ensuring an AVCodecContext is closed and freed
+// on destruction.
+class CodecContextWrapper
+{
+public:
+ CodecContextWrapper(AVCodecContext* context)
+ :
+ _codecCtx(context)
+ {}
+
+ ~CodecContextWrapper()
+ {
+ if (_codecCtx)
+ {
+ avcodec_close(_codecCtx);
+ av_free(_codecCtx);
+ }
+ }
+
+ AVCodecContext* getContext() const { return _codecCtx; }
+
+private:
+ AVCodecContext* _codecCtx;
+};
+
+
VideoDecoderFfmpeg::VideoDecoderFfmpeg(videoCodecType format, int width, int
height)
- :
- _videoCodec(NULL),
- _videoCodecCtx(NULL)
+ :
+ _videoCodec(NULL)
{
- enum CodecID codec_id = flashToFfmpegCodec(format);
-
- init(codec_id, width, height);
+
+ CodecID codec_id = flashToFfmpegCodec(format);
+ init(codec_id, width, height);
+
}
VideoDecoderFfmpeg::VideoDecoderFfmpeg(VideoInfo& info)
- :
- _videoCodec(NULL),
- _videoCodecCtx(NULL)
+ :
+ _videoCodec(NULL)
{
- enum CodecID codec_id = CODEC_ID_NONE;
- if ( info.type == FLASH )
- {
- codec_id = flashToFfmpegCodec(static_cast<videoCodecType>(info.codec));
- }
- else codec_id = static_cast<enum CodecID>(info.codec);
-
- // This would cause nasty segfaults.
- assert(codec_id != CODEC_ID_NONE);
-
- boost::uint8_t* extradata=0;
- int extradataSize=0;
- if ( info.extra.get() )
- {
- assert(dynamic_cast<ExtraVideoInfoFfmpeg*>(info.extra.get()));
- const ExtraVideoInfoFfmpeg& ei =
static_cast<ExtraVideoInfoFfmpeg&>(*info.extra);
- extradata = ei.data;
- extradataSize = ei.dataSize;
- }
- init(codec_id, info.width, info.height, extradata, extradataSize);
+
+ CodecID codec_id = CODEC_ID_NONE;
+
+ if ( info.type == FLASH )
+ {
+ codec_id = flashToFfmpegCodec(static_cast<videoCodecType>(info.codec));
+ }
+ else codec_id = static_cast<CodecID>(info.codec);
+
+ // This would cause nasty segfaults.
+ if (codec_id == CODEC_ID_NONE)
+ {
+ boost::format msg = boost::format(_("Cannot find suitable "
+ "decoder for flash codec %d")) % info.codec;
+ throw MediaException(msg.str());
+ }
+
+ boost::uint8_t* extradata=0;
+ int extradataSize=0;
+ if ( info.extra.get() )
+ {
+ assert(dynamic_cast<ExtraVideoInfoFfmpeg*>(info.extra.get()));
+ const ExtraVideoInfoFfmpeg& ei =
static_cast<ExtraVideoInfoFfmpeg&>(*info.extra);
+ extradata = ei.data;
+ extradataSize = ei.dataSize;
+ }
+ init(codec_id, info.width, info.height, extradata, extradataSize);
}
void
VideoDecoderFfmpeg::init(enum CodecID codecId, int width, int height,
boost::uint8_t* extradata, int extradataSize)
{
- // Init the avdecoder-decoder
- avcodec_init();
- avcodec_register_all();// change this to only register need codec?
-
- _videoCodec = avcodec_find_decoder(codecId);
-
- if (!_videoCodec) {
- log_error(_("libavcodec can't decode the current video format"));
- return;
- }
-
- _videoCodecCtx = avcodec_alloc_context();
- if (!_videoCodecCtx) {
- log_error(_("libavcodec couldn't allocate context"));
- return;
- }
-
- _videoCodecCtx->extradata = extradata;
- _videoCodecCtx->extradata_size = extradataSize;
-
- int ret = avcodec_open(_videoCodecCtx, _videoCodec);
- if (ret < 0) {
- log_error(_("VideoDecoderFfmpeg::init: avcodec_open: failed to initialize
FFMPEG codec %s (%d)"),
- _videoCodec->name, (int)codecId);
- av_free(_videoCodecCtx);
- _videoCodecCtx=0;
- return;
- }
- _videoCodecCtx->width = width;
- _videoCodecCtx->height = height;
-
- log_debug(_("VideoDecoderFfmpeg::init: initialized FFMPEG codec %s (%d)"),
- _videoCodec->name, (int)codecId);
-
- assert(_videoCodecCtx->width > 0);
- assert(_videoCodecCtx->height > 0);
+ // Init the avdecoder-decoder
+ avcodec_init();
+ avcodec_register_all();// change this to only register need codec?
+
+ _videoCodec = avcodec_find_decoder(codecId);
+
+ if (!_videoCodec) {
+ throw MediaException(_("libavcodec can't decode this video format"));
+ }
+
+ _videoCodecCtx.reset(new CodecContextWrapper(avcodec_alloc_context()));
+ if (!_videoCodecCtx->getContext()) {
+ throw MediaException(_("libavcodec couldn't allocate context"));
+ }
+
+ AVCodecContext* const ctx = _videoCodecCtx->getContext();
+
+ ctx->extradata = extradata;
+ ctx->extradata_size = extradataSize;
+
+ int ret = avcodec_open(ctx, _videoCodec);
+ if (ret < 0) {
+ boost::format msg = boost::format(_("libavcodec"
+ "failed to initialize FFMPEG "
+ "codec %s (%d)")) %
+ _videoCodec->name % (int)codecId;
+
+ throw MediaException(msg.str());
+ }
+
+ ctx->width = width;
+ ctx->height = height;
+
+ log_debug(_("VideoDecoder: initialized FFMPEG codec %s (%d)"),
+ _videoCodec->name, (int)codecId);
+
+ assert(ctx->width > 0);
+ assert(ctx->height > 0);
}
VideoDecoderFfmpeg::~VideoDecoderFfmpeg()
{
- if (_videoCodecCtx)
- {
- avcodec_close(_videoCodecCtx);
- av_free(_videoCodecCtx);
- }
}
std::auto_ptr<image::ImageBase>
@@ -158,174 +189,179 @@
const AVFrame& srcFrame)
{
- const int width = srcCtx->width;
- const int height = srcCtx->height;
+ // Adjust to next highest 4-pixel value.
+ const int width = srcCtx->width;
+ const int height = srcCtx->height;
- PixelFormat pixFmt;
- std::auto_ptr<image::ImageBase> im;
+ PixelFormat pixFmt;
+ std::auto_ptr<image::ImageBase> im;
#ifdef FFMPEG_VP6A
- if (srcCtx->codec->id == CODEC_ID_VP6A)
+ if (srcCtx->codec->id == CODEC_ID_VP6A)
#else
- if (0)
+ if (0)
#endif // def FFMPEG_VP6A
- {
- // Expect RGBA data
- //log_debug("alpha image");
- pixFmt = PIX_FMT_RGBA;
- im.reset(new image::ImageRGBA(width, height));
- }
- else
- {
- // Expect RGB data
- pixFmt = PIX_FMT_RGB24;
- im.reset(new image::ImageRGB(width, height));
- }
+ {
+ // Expect RGBA data
+ //log_debug("alpha image");
+ pixFmt = PIX_FMT_RGBA;
+ im.reset(new image::ImageRGBA(width, height));
+ }
+ else
+ {
+ // Expect RGB data
+ pixFmt = PIX_FMT_RGB24;
+ im.reset(new image::ImageRGB(width, height));
+ }
#ifdef HAVE_SWSCALE_H
- // Check whether the context wrapper exists
- // already.
- if (!_swsContext.get()) {
-
- _swsContext.reset(
- new SwsContextWrapper(
- sws_getContext(width, height, srcCtx->pix_fmt,
- width, height, pixFmt,
- SWS_BILINEAR, NULL, NULL, NULL)
- ));
-
- // Check that the context was assigned.
- if (!_swsContext->getContext()) {
-
- // This means we will try to assign the
- // context again next time.
- _swsContext.reset();
-
- // Can't do anything now, though.
- im.reset();
- return im;
+ // Check whether the context wrapper exists
+ // already.
+ if (!_swsContext.get()) {
+
+ _swsContext.reset(
+ new SwsContextWrapper(
+ sws_getContext(width, height, srcCtx->pix_fmt,
+ width, height, pixFmt,
+ SWS_BILINEAR, NULL, NULL, NULL)
+ ));
+
+ // Check that the context was assigned.
+ if (!_swsContext->getContext()) {
+
+ // This means we will try to assign the
+ // context again next time.
+ _swsContext.reset();
+
+ // Can't do anything now, though.
+ im.reset();
+ return im;
+ }
}
- }
#endif
- int bufsize = avpicture_get_size(pixFmt, width, height);
- if (bufsize == -1) {
+ int bufsize = avpicture_get_size(pixFmt, width, height);
+ if (bufsize == -1) {
+ im.reset();
+ return im;
+ }
+
+ boost::uint8_t* buffer = new boost::uint8_t[bufsize];
+
+ AVPicture picture;
+ picture.data[0] = NULL;
+
+ avpicture_fill(&picture, buffer, pixFmt, width, height);
+
+#ifndef HAVE_SWSCALE_H
+ img_convert(&picture, PIX_FMT_RGB24, (AVPicture*) &srcFrame,
+ srcCtx->pix_fmt, width, height);
+#else
+
+ // Is it possible for the context to be reset
+ // to NULL once it's been created?
+ assert(_swsContext->getContext());
+
+ int rv = sws_scale(_swsContext->getContext(),
const_cast<uint8_t**>(srcFrame.data),
+ const_cast<int*>(srcFrame.linesize), 0, height, picture.data,
+ picture.linesize);
+
+ if (rv == -1) {
+ delete [] buffer;
im.reset();
return im;
- }
-
- boost::uint8_t* buffer = new boost::uint8_t[bufsize];
-
- AVPicture picture;
- picture.data[0] = NULL;
-
- avpicture_fill(&picture, buffer, pixFmt, width, height);
-
-#ifndef HAVE_SWSCALE_H
- img_convert(&picture, PIX_FMT_RGB24, (AVPicture*) &srcFrame,
- srcCtx->pix_fmt, width, height);
-#else
-
- // Is it possible for the context to be reset
- // to NULL once it's been created?
- assert(_swsContext->getContext());
-
- int rv = sws_scale(_swsContext->getContext(),
const_cast<uint8_t**>(srcFrame.data),
- const_cast<int*>(srcFrame.linesize), 0, height, picture.data,
- picture.linesize);
-
- if (rv == -1) {
- delete [] buffer;
- im.reset();
+ }
+#endif
+
+ im->update(picture.data[0]);
return im;
- }
-#endif
-
- im->update(picture.data[0]);
- return im;
}
std::auto_ptr<image::ImageBase>
VideoDecoderFfmpeg::decode(const boost::uint8_t* input, boost::uint32_t
input_size)
{
- std::auto_ptr<image::ImageBase> ret;
-
- AVFrame* frame = avcodec_alloc_frame();
- if ( ! frame ) {
- log_error(_("Out of memory while allocating avcodec frame"));
- return ret;
- }
-
- int bytes = 0;
- // no idea why avcodec_decode_video wants a non-const input...
- avcodec_decode_video(_videoCodecCtx, frame, &bytes,
const_cast<boost::uint8_t*>(input), input_size);
-
- if (!bytes) {
- log_error("Decoding of a video frame failed");
+
+ // This object shouldn't exist if there's no codec, as it can'
+ // do anything anyway.
+ assert(_videoCodecCtx.get());
+
+ std::auto_ptr<image::ImageBase> ret;
+
+ AVFrame* frame = avcodec_alloc_frame();
+ if ( ! frame ) {
+ log_error(_("Out of memory while allocating avcodec frame"));
+ return ret;
+ }
+
+ int bytes = 0;
+ // no idea why avcodec_decode_video wants a non-const input...
+ avcodec_decode_video(_videoCodecCtx->getContext(), frame, &bytes,
const_cast<boost::uint8_t*>(input), input_size);
+
+ if (!bytes) {
+ log_error("Decoding of a video frame failed");
+ av_free(frame);
+ return ret;
+ }
+
+ ret = frameToImage(_videoCodecCtx->getContext(), *frame);
+
+ // FIXME: av_free doesn't free frame->data!
av_free(frame);
return ret;
- }
-
- ret = frameToImage(_videoCodecCtx, *frame);
-
- // FIXME: av_free doesn't free frame->data!
- av_free(frame);
- return ret;
}
void
VideoDecoderFfmpeg::push(const EncodedVideoFrame& buffer)
{
- _video_frames.push_back(&buffer);
-
+ _video_frames.push_back(&buffer);
}
std::auto_ptr<image::ImageBase>
VideoDecoderFfmpeg::pop()
{
- std::auto_ptr<image::ImageBase> ret;
-
- for (std::vector<const EncodedVideoFrame*>::iterator it =
- _video_frames.begin(), end = _video_frames.end(); it != end; ++it) {
- ret = decode((*it)->data(), (*it)->dataSize());
- }
-
- _video_frames.clear();
-
- return ret;
+ std::auto_ptr<image::ImageBase> ret;
+
+ for (std::vector<const EncodedVideoFrame*>::iterator it =
+ _video_frames.begin(), end = _video_frames.end(); it != end;
++it) {
+ ret = decode((*it)->data(), (*it)->dataSize());
+ }
+
+ _video_frames.clear();
+
+ return ret;
}
-
+
bool
VideoDecoderFfmpeg::peek()
{
- return (!_video_frames.empty());
+ return (!_video_frames.empty());
}
/* public static */
enum CodecID
VideoDecoderFfmpeg::flashToFfmpegCodec(videoCodecType format)
{
- // Find the decoder and init the parser
- switch(format) {
- case VIDEO_CODEC_H263:
- return CODEC_ID_FLV1; // why not CODEC_ID_H263I ?
+ // Find the decoder and init the parser
+ switch(format) {
+ case VIDEO_CODEC_H263:
+ return CODEC_ID_FLV1; // why not CODEC_ID_H263I ?
#ifdef FFMPEG_VP6
- case VIDEO_CODEC_VP6:
- return CODEC_ID_VP6F;
+ case VIDEO_CODEC_VP6:
+ return CODEC_ID_VP6F;
#endif
#ifdef FFMPEG_VP6A
- case VIDEO_CODEC_VP6A:
- return CODEC_ID_VP6A;
+ case VIDEO_CODEC_VP6A:
+ return CODEC_ID_VP6A;
#endif
- case VIDEO_CODEC_SCREENVIDEO:
- return CODEC_ID_FLASHSV;
- default:
- log_error(_("Unsupported video codec %d"),
- static_cast<int>(format));
- return CODEC_ID_NONE;
- }
+ case VIDEO_CODEC_SCREENVIDEO:
+ return CODEC_ID_FLASHSV;
+ default:
+ log_error(_("Unsupported video codec %d"),
+ static_cast<int>(format));
+ return CODEC_ID_NONE;
+ }
}
=== modified file 'libmedia/ffmpeg/VideoDecoderFfmpeg.h'
--- a/libmedia/ffmpeg/VideoDecoderFfmpeg.h 2008-08-28 16:30:58 +0000
+++ b/libmedia/ffmpeg/VideoDecoderFfmpeg.h 2008-09-01 13:10:41 +0000
@@ -53,6 +53,7 @@
/// Forward declarations
+class CodecContextWrapper;
class image::ImageBase;
#ifdef HAVE_SWSCALE_H
class SwsContextWrapper;
@@ -105,7 +106,7 @@
}
AVCodec* _videoCodec;
- AVCodecContext* _videoCodecCtx;
+ std::auto_ptr<CodecContextWrapper> _videoCodecCtx;
#if HAVE_SWSCALE_H
/// A pointer to a wrapper round an SwsContext
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r9656: Fix segfault when video pitch is not a multiple of 4. Fix segfault when,
Benjamin Wolsey <=