[Swfdec-commits] 2 commits - swfdec/Makefile.am swfdec/swfdec_audio_decoder_gst.c swfdec/swfdec_codec_gst.c swfdec/swfdec_codec_screen.c swfdec/swfdec_codec_video.c swfdec/swfdec_codec_video.h swfdec/swfdec_codec_vp6_alpha.c swfdec/swfdec_decoder.c swfdec/swfdec_flv_decoder.c swfdec/swfdec_flv_decoder.h swfdec/swfdec_init.c swfdec/swfdec_internal.h swfdec/swfdec_net_stream.c swfdec/swfdec_net_stream.h swfdec/swfdec_video.c swfdec/swfdec_video_decoder.c swfdec/swfdec_video_decoder_gst.c swfdec/swfdec_video_decoder_gst.h swfdec/swfdec_video_decoder.h swfdec/swfdec_video_decoder_screen.c swfdec/swfdec_video_decoder_screen.h swfdec/swfdec_video_decoder_vp6_alpha.c swfdec/swfdec_video_decoder_vp6_alpha.h swfdec/swfdec_video_movie.c swfdec/swfdec_video_provider.c swfdec/swfdec_video_provider.h swfdec/swfdec_video_video_provider.c swfdec/swfdec_video_video_provider.h
Benjamin Otte
company at kemper.freedesktop.org
Wed Jun 25 02:53:38 PDT 2008
swfdec/Makefile.am | 13 -
swfdec/swfdec_audio_decoder_gst.c | 1
swfdec/swfdec_codec_gst.c | 188 ----------------
swfdec/swfdec_codec_screen.c | 134 -----------
swfdec/swfdec_codec_video.c | 330 ----------------------------
swfdec/swfdec_codec_video.h | 80 ------
swfdec/swfdec_codec_vp6_alpha.c | 111 ---------
swfdec/swfdec_decoder.c | 5
swfdec/swfdec_flv_decoder.c | 1
swfdec/swfdec_flv_decoder.h | 1
swfdec/swfdec_init.c | 6
swfdec/swfdec_internal.h | 13 -
swfdec/swfdec_net_stream.c | 218 +++++++++---------
swfdec/swfdec_net_stream.h | 3
swfdec/swfdec_video.c | 1
swfdec/swfdec_video_decoder.c | 372 ++++++++++++++++++++++++++++++++
swfdec/swfdec_video_decoder.h | 113 +++++++++
swfdec/swfdec_video_decoder_gst.c | 211 ++++++++++++++++++
swfdec/swfdec_video_decoder_gst.h | 56 ++++
swfdec/swfdec_video_decoder_screen.c | 138 +++++++++++
swfdec/swfdec_video_decoder_screen.h | 52 ++++
swfdec/swfdec_video_decoder_vp6_alpha.c | 138 +++++++++++
swfdec/swfdec_video_decoder_vp6_alpha.h | 55 ++++
swfdec/swfdec_video_movie.c | 27 --
swfdec/swfdec_video_provider.c | 28 ++
swfdec/swfdec_video_provider.h | 6
swfdec/swfdec_video_video_provider.c | 30 +-
swfdec/swfdec_video_video_provider.h | 2
28 files changed, 1335 insertions(+), 998 deletions(-)
New commits:
commit 649cee75b316f728fcaa2010d2a863978b1b9c91
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jun 25 11:52:23 2008 +0200
make swfdec's video decoder a proper object
This follows the changes to the audio decoder.
Also, it fixes the last testsuite failure
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 9478371..85dda11 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -3,7 +3,7 @@ SUBDIRS = jpeg
CODEC_FILES =
if HAVE_GST
-CODEC_FILES += swfdec_codec_gst.c swfdec_audio_decoder_gst.c
+CODEC_FILES += swfdec_codec_gst.c swfdec_audio_decoder_gst.c swfdec_video_decoder_gst.c
endif
lib_LTLIBRARIES = libswfdec- at SWFDEC_MAJORMINOR@.la
@@ -59,9 +59,6 @@ libswfdec_source_files = \
swfdec_cached_video.c \
swfdec_camera.c \
swfdec_character.c \
- swfdec_codec_screen.c \
- swfdec_codec_video.c \
- swfdec_codec_vp6_alpha.c \
swfdec_color.c \
swfdec_color_as.c \
swfdec_color_matrix_filter.c \
@@ -162,6 +159,9 @@ libswfdec_source_files = \
swfdec_url.c \
swfdec_utils.c \
swfdec_video.c \
+ swfdec_video_decoder.c \
+ swfdec_video_decoder_screen.c \
+ swfdec_video_decoder_vp6_alpha.c \
swfdec_video_movie.c \
swfdec_video_movie_as.c \
swfdec_video_provider.c \
@@ -255,7 +255,6 @@ noinst_HEADERS = \
swfdec_cached_video.h \
swfdec_character.h \
swfdec_codec_gst.h \
- swfdec_codec_video.h \
swfdec_color.h \
swfdec_constant_pool.h \
swfdec_debug.h \
@@ -316,6 +315,10 @@ noinst_HEADERS = \
swfdec_types.h \
swfdec_utils.h \
swfdec_video.h \
+ swfdec_video_decoder.h \
+ swfdec_video_decoder_gst.h \
+ swfdec_video_decoder_screen.h \
+ swfdec_video_decoder_vp6_alpha.h \
swfdec_video_movie.h \
swfdec_video_provider.h \
swfdec_video_video_provider.h \
diff --git a/swfdec/swfdec_codec_gst.c b/swfdec/swfdec_codec_gst.c
index 919c8e8..638e8a6 100644
--- a/swfdec/swfdec_codec_gst.c
+++ b/swfdec/swfdec_codec_gst.c
@@ -24,31 +24,9 @@
#include <gst/pbutils/pbutils.h>
#include "swfdec_codec_gst.h"
-#include "swfdec_codec_video.h"
#include "swfdec_debug.h"
#include "swfdec_internal.h"
-/*** CAPS MATCHING ***/
-
-static GstCaps *
-swfdec_video_decoder_get_caps (guint codec)
-{
- GstCaps *caps;
-
- switch (codec) {
- case SWFDEC_VIDEO_CODEC_H263:
- caps = gst_caps_from_string ("video/x-flash-video");
- break;
- case SWFDEC_VIDEO_CODEC_VP6:
- caps = gst_caps_from_string ("video/x-vp6-flash");
- break;
- default:
- return NULL;
- }
- g_assert (caps);
- return caps;
-}
-
/*** BUFFER ***/
GstBuffer *
@@ -332,169 +310,3 @@ swfdec_gst_decoder_pull (SwfdecGstDecoder *dec)
return g_queue_pop_head (dec->queue);
}
-/*** VIDEO ***/
-
-/* NB: We don't put a colorspace tansform here, we just assume that the codecs
- * in GStreamer decode to the native format that we enforce. */
-typedef struct _SwfdecGstVideo SwfdecGstVideo;
-struct _SwfdecGstVideo {
- SwfdecVideoDecoder decoder;
-
- gboolean error;
- SwfdecGstDecoder dec; /* the decoder element */
- GstBuffer * last; /* last decoded buffer */
-};
-
-static void
-swfdec_video_decoder_gst_free (SwfdecVideoDecoder *dec)
-{
- SwfdecGstVideo *player = (SwfdecGstVideo *) dec;
-
- swfdec_gst_decoder_finish (&player->dec);
- if (player->last)
- gst_buffer_unref (player->last);
-
- g_slice_free (SwfdecGstVideo, player);
-}
-
-static gboolean
-swfdec_video_decoder_gst_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer,
- SwfdecVideoImage *image)
-{
- SwfdecGstVideo *player = (SwfdecGstVideo *) dec;
-#define SWFDEC_ALIGN(x, n) (((x) + (n) - 1) & (~((n) - 1)))
- GstBuffer *buf;
- GstCaps *caps;
- GstStructure *structure;
-
- if (player->error)
- return FALSE;
- if (player->last) {
- gst_buffer_unref (player->last);
- player->last = NULL;
- }
-
- buf = swfdec_gst_buffer_new (swfdec_buffer_ref (buffer));
- if (!swfdec_gst_decoder_push (&player->dec, buf)) {
- SWFDEC_ERROR ("failed to push buffer");
- player->error = TRUE;
- return FALSE;
- }
-
- player->last = swfdec_gst_decoder_pull (&player->dec);
- if (player->last == NULL) {
- SWFDEC_ERROR ("failed to pull decoded buffer");
- player->error = TRUE;
- return FALSE;
- }
- while ((buf = swfdec_gst_decoder_pull (&player->dec))) {
- SWFDEC_WARNING ("too many output buffers!");
- }
- caps = gst_buffer_get_caps (player->last);
- if (caps == NULL) {
- SWFDEC_ERROR ("no caps on decoded buffer");
- player->error = TRUE;
- return FALSE;
- }
- structure = gst_caps_get_structure (caps, 0);
- if (!gst_structure_get_int (structure, "width", (int *) &image->width) ||
- !gst_structure_get_int (structure, "height", (int *) &image->height)) {
- SWFDEC_ERROR ("invalid caps on decoded buffer");
- player->error = TRUE;
- return FALSE;
- }
- image->mask = NULL;
- buf = player->last;
- switch (swfdec_video_codec_get_format (dec->codec)) {
- case SWFDEC_VIDEO_FORMAT_RGBA:
- image->plane[0] = buf->data;
- image->rowstride[0] = image->width * 4;
- break;
- case SWFDEC_VIDEO_FORMAT_I420:
- image->plane[0] = buf->data;
- image->rowstride[0] = SWFDEC_ALIGN (image->width, 4);
- image->plane[1] = image->plane[0] + image->rowstride[0] * SWFDEC_ALIGN (image->height, 2);
- image->rowstride[1] = SWFDEC_ALIGN (image->width, 8) / 2;
- image->plane[2] = image->plane[1] + image->rowstride[1] * SWFDEC_ALIGN (image->height, 2) / 2;
- image->rowstride[2] = image->rowstride[1];
- g_assert (image->plane[2] + image->rowstride[2] * SWFDEC_ALIGN (image->height, 2) / 2 == image->plane[0] + buf->size);
- break;
- default:
- g_return_val_if_reached (FALSE);
- }
- return TRUE;
-#undef SWFDEC_ALIGN
-}
-
-static GstCaps *
-swfdec_video_decoder_get_sink_caps (guint codec)
-{
- switch (swfdec_video_codec_get_format (codec)) {
- case SWFDEC_VIDEO_FORMAT_RGBA:
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
- "red_mask=16711680, green_mask=65280, blue_mask=255");
-#else
- return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
- "red_mask=65280, green_mask=16711680, blue_mask=-16777216");
-#endif
- case SWFDEC_VIDEO_FORMAT_I420:
- return gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)I420");
- default:
- g_return_val_if_reached (NULL);
- }
-}
-
-SwfdecVideoDecoder *
-swfdec_video_decoder_gst_new (guint codec)
-{
- SwfdecGstVideo *player;
- GstCaps *srccaps, *sinkcaps;
-
- srccaps = swfdec_video_decoder_get_caps (codec);
- if (srccaps == NULL)
- return NULL;
- sinkcaps = swfdec_video_decoder_get_sink_caps (codec);
-
- player = g_slice_new0 (SwfdecGstVideo);
- player->decoder.decode = swfdec_video_decoder_gst_decode;
- player->decoder.free = swfdec_video_decoder_gst_free;
-
- if (!swfdec_gst_decoder_init (&player->dec, srccaps, sinkcaps, NULL)) {
- swfdec_video_decoder_gst_free (&player->decoder);
- gst_caps_unref (srccaps);
- gst_caps_unref (sinkcaps);
- return NULL;
- }
-
- gst_caps_unref (srccaps);
- gst_caps_unref (sinkcaps);
- return &player->decoder;
-}
-
-/*** MISSING PLUGIN SUPPORT ***/
-
-gboolean
-swfdec_video_decoder_gst_prepare (guint codec, char **detail)
-{
- GstElementFactory *factory;
- GstCaps *caps;
-
- /* Check if we can handle the format at all. If not, no plugin will help us. */
- caps = swfdec_video_decoder_get_caps (codec);
- if (caps == NULL)
- return FALSE;
-
- /* If we can already handle it, woohoo! */
- factory = swfdec_gst_get_element_factory (caps);
- if (factory != NULL) {
- gst_object_unref (factory);
- return TRUE;
- }
-
- /* need to install plugins... */
- *detail = gst_missing_decoder_installer_detail_new (caps);
- gst_caps_unref (caps);
- return FALSE;
-}
-
diff --git a/swfdec/swfdec_codec_screen.c b/swfdec/swfdec_codec_screen.c
deleted file mode 100644
index 5dbdfce..0000000
--- a/swfdec/swfdec_codec_screen.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <zlib.h>
-#include <liboil/liboil.h>
-
-#include "swfdec_codec_video.h"
-#include "swfdec_bits.h"
-#include "swfdec_debug.h"
-#include "swfdec_internal.h"
-
-typedef struct _SwfdecCodecScreen SwfdecCodecScreen;
-
-struct _SwfdecCodecScreen {
- SwfdecVideoDecoder decoder; /* the decoder */
- gulong width; /* width of last image */
- gulong height; /* height of last image */
- guint8 * data; /* contains decoded image */
-};
-
-static gboolean
-swfdec_video_decoder_screen_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer,
- SwfdecVideoImage *image)
-{
- SwfdecCodecScreen *screen = (SwfdecCodecScreen *) dec;
- SwfdecBits bits;
- gulong i, j, w, h, bw, bh, stride;
-
- swfdec_bits_init (&bits, buffer);
- bw = (swfdec_bits_getbits (&bits, 4) + 1) * 16;
- w = swfdec_bits_getbits (&bits, 12);
- bh = (swfdec_bits_getbits (&bits, 4) + 1) * 16;
- h = swfdec_bits_getbits (&bits, 12);
- if (screen->width == 0 || screen->height == 0) {
- if (w == 0 || h == 0) {
- SWFDEC_ERROR ("width or height is 0: %lux%lu", w, h);
- return FALSE;
- }
- screen->data = g_try_malloc (w * h * 4);
- if (screen->data == NULL) {
- SWFDEC_ERROR ("could not allocate %lu bytes", w * h * 4);
- return FALSE;
- }
- screen->width = w;
- screen->height = h;
- } else if (screen->width != w || screen->height != h) {
- SWFDEC_ERROR ("width or height differ from original: was %lux%lu, is %lux%lu",
- screen->width, screen->height, w, h);
- /* FIXME: this is what ffmpeg does, should we be more forgiving? */
- return FALSE;
- }
- stride = w * 4;
- SWFDEC_LOG ("size: %lu x %lu - block size %lu x %lu\n", w, h, bw, bh);
- for (j = 0; j < h; j += bh) {
- for (i = 0; i < w; i += bw) {
- guint x, y, size;
- SwfdecBuffer *buf;
- guint8 *in, *out;
- size = swfdec_bits_get_bu16 (&bits);
- if (size == 0)
- continue;
- buf = swfdec_bits_decompress (&bits, size, bw * bh * 4);
- if (buf == NULL) {
- SWFDEC_WARNING ("error decoding block");
- continue;
- }
- /* convert format and write out data */
- out = screen->data + stride * (h - j - 1) + i * 4;
- in = buf->data;
- for (y = 0; y < MIN (bh, h - j); y++) {
- for (x = 0; x < MIN (bw, w - i); x++) {
- out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_BLUE] = *in++;
- out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_GREEN] = *in++;
- out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_RED] = *in++;
- out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_ALPHA] = 0xFF;
- }
- }
- swfdec_buffer_unref (buf);
- }
- }
- image->width = screen->width;
- image->height = screen->height;
- image->plane[0] = screen->data;
- image->rowstride[0] = stride;
- image->mask = NULL;
- return TRUE;
-}
-
-static void
-swfdec_video_decoder_screen_free (SwfdecVideoDecoder *dec)
-{
- SwfdecCodecScreen *screen = (SwfdecCodecScreen *) dec;
-
- if (screen->data)
- g_free (screen->data);
- g_free (screen);
-}
-
-SwfdecVideoDecoder *
-swfdec_video_decoder_screen_new (guint type)
-{
- SwfdecCodecScreen *screen;
-
- if (type != SWFDEC_VIDEO_CODEC_SCREEN)
- return NULL;
-
- screen = g_new0 (SwfdecCodecScreen, 1);
- screen->decoder.decode = swfdec_video_decoder_screen_decode;
- screen->decoder.free = swfdec_video_decoder_screen_free;
-
- return &screen->decoder;
-}
-
diff --git a/swfdec/swfdec_codec_video.c b/swfdec/swfdec_codec_video.c
deleted file mode 100644
index 8260945..0000000
--- a/swfdec/swfdec_codec_video.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* Swfdec
- * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <liboil/liboil.h>
-#include "swfdec_codec_video.h"
-#include "swfdec_color.h"
-#include "swfdec_debug.h"
-#include "swfdec_internal.h"
-#include "swfdec_renderer_internal.h"
-
-static gboolean
-swfdec_video_decoder_builtin_prepare (guint codec, char **detail)
-{
- return codec == SWFDEC_VIDEO_CODEC_SCREEN;
-}
-
-static SwfdecVideoDecoder *
-swfdec_video_decoder_builtin_new (guint codec)
-{
- SwfdecVideoDecoder *ret;
-
- ret = swfdec_video_decoder_screen_new (codec);
- if (ret == NULL)
- ret = swfdec_video_decoder_vp6_alpha_new (codec);
-
- return ret;
-}
-
-static const struct {
- const char * name;
- SwfdecVideoDecoder * (* func) (guint);
- gboolean (* prepare) (guint, char **);
-} video_codecs[] = {
- { "builtin", swfdec_video_decoder_builtin_new, swfdec_video_decoder_builtin_prepare }
-#ifdef HAVE_GST
- , { "gst", swfdec_video_decoder_gst_new, swfdec_video_decoder_gst_prepare }
-#endif
-};
-
-char *
-swfdec_video_decoder_prepare (guint codec)
-{
- char *detail = NULL, *s = NULL;
- guint i;
-
- /* the builtin codec is implemented as a wrapper around VP6 */
- if (codec == SWFDEC_VIDEO_CODEC_VP6_ALPHA)
- codec = SWFDEC_VIDEO_CODEC_VP6;
-
- for (i = 0; i < G_N_ELEMENTS (video_codecs); i++) {
- if (video_codecs[i].prepare (codec, &s)) {
- g_free (detail);
- g_free (s);
- return NULL;
- }
- if (s) {
- if (detail == NULL)
- detail = s;
- else
- g_free (s);
- s = NULL;
- }
- }
- return detail;
-}
-
-/**
- * swfdec_video_decoder_new:
- * @codec: #SwfdecVideoCodec to create the #SwfdecVideoDecoder for
- *
- * Creates a new decoder to decode videos of type @codec. If no suitable
- * decoder could be created, %NULL is returned.
- *
- * Returns:
- **/
-SwfdecVideoDecoder *
-swfdec_video_decoder_new (guint codec)
-{
- SwfdecVideoDecoder *ret = NULL;
- guint i;
-
- for (i = 0; i < G_N_ELEMENTS (video_codecs); i++) {
- ret = video_codecs[i].func (codec);
- if (ret)
- break;
- }
-
- if (ret != NULL) {
- ret->codec = codec;
- g_return_val_if_fail (ret->decode, ret);
- g_return_val_if_fail (ret->free, ret);
- } else {
- SWFDEC_WARNING ("no decoder found for codec %u", (guint) codec);
- }
- return ret;
-}
-
-/**
- * swfdec_video_decoder_free:
- * @decoder: a #SwfdecVideoDecoder
- *
- * Frees the given @decoder and all associated ressources.
- **/
-void
-swfdec_video_decoder_free (SwfdecVideoDecoder *decoder)
-{
- g_return_if_fail (decoder);
-
- decoder->free (decoder);
-}
-
-#define oil_argb(a,r,g,b) (((a) << 24) | ((r) << 16) | ((g) << 8) | b)
-static gint16 jfif_matrix[24] = {
- 0, 0, -8192, -8192,
- 16384, 0, 0, 0,
- 0, 16384, 16384, 16384,
- 0, 0, -5638, 29032,
- 0, 22970, -11700, 0,
- 0, 0, 0, 0
-};
-
-static void
-yuv_mux (guint32 *dest, const guint8 *src_y, const guint8 *src_u, const guint8 *src_v,
- int n)
-{
- int i;
- for (i = 0; i < n; i++) {
- dest[i] = oil_argb(255, src_y[i], src_u[i], src_v[i]);
- }
-}
-
-static void
-upsample (guint8 *d, guint8 *s, int n)
-{
- int i;
-
- d[0] = s[0];
-
- for (i = 0; i < n-3; i+=2) {
- d[i + 1] = (3*s[i/2] + s[i/2+1] + 2)>>2;
- d[i + 2] = (s[i/2] + 3*s[i/2+1] + 2)>>2;
- }
-
- if (n&1) {
- i = n-3;
- d[n-2] = s[n/2];
- d[n-1] = s[n/2];
- } else {
- d[n-1] = s[n/2-1];
- }
-}
-
-static guint8 *
-swfdec_video_i420_to_rgb (SwfdecVideoImage *image)
-{
- guint32 *tmp;
- guint8 *tmp_u;
- guint8 *tmp_v;
- guint8 *tmp1;
- guint32 *argb_image;
- const guint8 *yp, *up, *vp;
- guint32 *argbp;
- int j;
- guint halfwidth;
- int halfheight;
-
- halfwidth = (image->width + 1)>>1;
- tmp = g_malloc (4 * image->width * image->height);
- tmp_u = g_malloc (image->width);
- tmp_v = g_malloc (image->width);
- tmp1 = g_malloc (halfwidth);
- argb_image = g_malloc (4 * image->width * image->height);
-
- yp = image->plane[0];
- up = image->plane[1];
- vp = image->plane[2];
- argbp = argb_image;
- halfheight = (image->height+1)>>1;
- for(j=0;(guint)j<image->height;j++){
- guint32 weight = 192 - 128*(j&1);
-
- oil_merge_linear_u8(tmp1,
- up + image->rowstride[1] * CLAMP((j-1)/2,0,halfheight-1),
- up + image->rowstride[1] * CLAMP((j+1)/2,0,halfheight-1),
- &weight, halfwidth);
- upsample (tmp_u, tmp1, image->width);
- oil_merge_linear_u8(tmp1,
- vp + image->rowstride[2] * CLAMP((j-1)/2,0,halfheight-1),
- vp + image->rowstride[2] * CLAMP((j+1)/2,0,halfheight-1),
- &weight, halfwidth);
- upsample (tmp_v, tmp1, image->width);
-
- yuv_mux (tmp, yp, tmp_u, tmp_v, image->width);
- oil_colorspace_argb(argbp, tmp, jfif_matrix, image->width);
- yp += image->rowstride[0];
- argbp += image->width;
- }
- g_free(tmp);
- g_free(tmp_u);
- g_free(tmp_v);
- g_free(tmp1);
- return (unsigned char *)argb_image;
-}
-
-/* FIXME: use liboil for this */
-static void
-swfdec_video_codec_apply_mask (guint8 *data, guint rowstride, const guint8 *mask,
- guint mask_rowstride, guint width, guint height)
-{
- const guint8 *in;
- guint8 *out;
- guint x, y;
-
- data += SWFDEC_COLOR_INDEX_ALPHA;
- for (y = 0; y < height; y++) {
- in = mask;
- out = data;
- for (x = 0; x < width; x++) {
- *out = *in;
- out += 4;
- in++;
- }
- mask += mask_rowstride;
- data += rowstride;
- }
-}
-
-/**
- * swfdec_video_decoder_decode:
- * @decoder: a #SwfdecVideoDecoder
- * @renderer: renderer the resulting surface should belong to
- * @buffer: buffer to decode
- * @width: relevant width of resulting image
- * @height: relevant height of resulting image
- *
- * Decodes the given buffer into a surface. On success, the relevant area of
- * the surface will be indicated by @width and @height.
- *
- * Returns: a new cairo image surface or %NULL on error.
- **/
-cairo_surface_t *
-swfdec_video_decoder_decode (SwfdecVideoDecoder *decoder, SwfdecRenderer *renderer,
- SwfdecBuffer *buffer, guint *width, guint *height)
-{
- SwfdecVideoImage image;
- cairo_surface_t *surface;
- guint8 *data;
- guint rowstride;
-
- g_return_val_if_fail (decoder != NULL, NULL);
- g_return_val_if_fail (SWFDEC_IS_RENDERER (renderer), NULL);
- g_return_val_if_fail (buffer != NULL, NULL);
- g_return_val_if_fail (width != NULL, NULL);
- g_return_val_if_fail (height != NULL, NULL);
-
- if (!decoder->decode (decoder, buffer, &image)) {
- SWFDEC_ERROR ("failed to decode video");
- return NULL;
- }
- g_assert (image.width != 0 && image.height != 0);
- /* FIXME: use cairo for all of this when cairo accelerates it */
- if (swfdec_video_codec_get_format (decoder->codec) == SWFDEC_VIDEO_FORMAT_I420) {
- data = swfdec_video_i420_to_rgb (&image);
- if (data == NULL) {
- SWFDEC_ERROR ("I420 => RGB conversion failed");
- return NULL;
- }
- rowstride = image.width * 4;
- } else {
- rowstride = image.rowstride[0];
- data = g_memdup (image.plane[0], rowstride * image.height);
- }
- if (image.mask) {
- swfdec_video_codec_apply_mask (data, image.width * 4, image.mask,
- image.mask_rowstride, image.width, image.height);
- }
- surface = swfdec_renderer_create_for_data (renderer, data,
- image.mask ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
- image.width, image.height, rowstride);
- *width = image.width;
- *height = image.height;
- return surface;
-}
-
-/**
- * swfdec_video_codec_get_format:
- * @codec: codec to check
- *
- * Returns the output format used for this codec. Video codecs must use these
- * codecs when decoding video.
- *
- * Returns: the output format to use for this format
- **/
-SwfdecVideoFormat
-swfdec_video_codec_get_format (guint codec)
-{
- switch (codec) {
- case SWFDEC_VIDEO_CODEC_H263:
- case SWFDEC_VIDEO_CODEC_VP6:
- case SWFDEC_VIDEO_CODEC_VP6_ALPHA:
- return SWFDEC_VIDEO_FORMAT_I420;
- case SWFDEC_VIDEO_CODEC_UNDEFINED:
- case SWFDEC_VIDEO_CODEC_SCREEN:
- case SWFDEC_VIDEO_CODEC_SCREEN2:
- return SWFDEC_VIDEO_FORMAT_RGBA;
- default:
- g_return_val_if_reached (SWFDEC_VIDEO_FORMAT_RGBA);
- }
-}
-
diff --git a/swfdec/swfdec_codec_video.h b/swfdec/swfdec_codec_video.h
deleted file mode 100644
index 5ad961f..0000000
--- a/swfdec/swfdec_codec_video.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Swfdec
- * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef _SWFDEC_CODEC_VIDEO_H_
-#define _SWFDEC_CODEC_VIDEO_H_
-
-#include <glib.h>
-#include <cairo.h>
-#include <swfdec/swfdec_buffer.h>
-#include <swfdec/swfdec_renderer.h>
-
-#define SWFDEC_VIDEO_CODEC_UNDEFINED 0
-#define SWFDEC_VIDEO_CODEC_H263 2
-#define SWFDEC_VIDEO_CODEC_SCREEN 3
-#define SWFDEC_VIDEO_CODEC_VP6 4
-#define SWFDEC_VIDEO_CODEC_VP6_ALPHA 5
-#define SWFDEC_VIDEO_CODEC_SCREEN2 6
-
-typedef enum {
- SWFDEC_VIDEO_FORMAT_RGBA,
- SWFDEC_VIDEO_FORMAT_I420
-} SwfdecVideoFormat;
-
-typedef struct {
- guint width; /* width of image in pixels */
- guint height; /* height of image in pixels */
- const guint8 * plane[3]; /* planes of the image, not all might be used */
- const guint8 * mask; /* A8 mask or NULL if none */
- guint rowstride[3]; /* rowstrides of the planes */
- guint mask_rowstride; /* rowstride of mask plane */
-} SwfdecVideoImage;
-
-typedef struct _SwfdecVideoDecoder SwfdecVideoDecoder;
-typedef SwfdecVideoDecoder * (SwfdecVideoDecoderNewFunc) (guint format);
-
-/* notes about the decode function:
- * - the data must be in the format specified by swfdec_video_codec_get_format()
- * - the data returned in the image belongs to the decoder and must be valid
- * until the next function is called on the decoder.
- * - you need to explicitly set mask to %NULL.
- */
-struct _SwfdecVideoDecoder {
- guint codec;
- gboolean (* decode) (SwfdecVideoDecoder * decoder,
- SwfdecBuffer * buffer,
- SwfdecVideoImage * result);
- void (* free) (SwfdecVideoDecoder * decoder);
-};
-
-SwfdecVideoFormat swfdec_video_codec_get_format (guint codec);
-
-char * swfdec_video_decoder_prepare (guint codec);
-SwfdecVideoDecoder * swfdec_video_decoder_new (guint codec);
-void swfdec_video_decoder_free (SwfdecVideoDecoder * decoder);
-
-cairo_surface_t * swfdec_video_decoder_decode (SwfdecVideoDecoder * decoder,
- SwfdecRenderer * renderer,
- SwfdecBuffer * buffer,
- guint * width,
- guint * height);
-
-
-G_END_DECLS
-#endif
diff --git a/swfdec/swfdec_codec_vp6_alpha.c b/swfdec/swfdec_codec_vp6_alpha.c
deleted file mode 100644
index 672d3d7..0000000
--- a/swfdec/swfdec_codec_vp6_alpha.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <zlib.h>
-#include <liboil/liboil.h>
-
-#include "swfdec_codec_video.h"
-#include "swfdec_bits.h"
-#include "swfdec_debug.h"
-#include "swfdec_internal.h"
-
-typedef struct _SwfdecCodecVp6Alpha SwfdecCodecVp6Alpha;
-
-struct _SwfdecCodecVp6Alpha {
- SwfdecVideoDecoder decoder; /* the decoder */
- SwfdecVideoDecoder * image; /* the image decoder */
- SwfdecVideoDecoder * alpha; /* the alpha decoder */
-};
-
-static gboolean
-swfdec_video_decoder_vp6_alpha_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer,
- SwfdecVideoImage *image)
-{
- SwfdecCodecVp6Alpha *vp6 = (SwfdecCodecVp6Alpha *) dec;
- SwfdecBuffer *tmp;
- SwfdecVideoImage alpha;
- SwfdecBits bits;
- guint size;
-
- swfdec_bits_init (&bits, buffer);
- size = swfdec_bits_get_bu24 (&bits);
- tmp = swfdec_bits_get_buffer (&bits, size);
- if (tmp == NULL)
- return FALSE;
- if (!vp6->image->decode (vp6->image, tmp, image)) {
- swfdec_buffer_unref (tmp);
- return FALSE;
- }
- swfdec_buffer_unref (tmp);
- tmp = swfdec_bits_get_buffer (&bits, -1);
- if (tmp == NULL)
- return FALSE;
- if (!vp6->alpha->decode (vp6->alpha, tmp, &alpha)) {
- swfdec_buffer_unref (tmp);
- return FALSE;
- }
- swfdec_buffer_unref (tmp);
- if (alpha.width != image->width || alpha.height != image->height) {
- SWFDEC_ERROR ("size of mask doesn't match image: %ux%u vs %ux%u",
- alpha.width, alpha.height, image->width, image->height);
- return FALSE;
- }
- image->mask = alpha.plane[0];
- image->mask_rowstride = alpha.rowstride[0];
- return TRUE;
-}
-
-static void
-swfdec_video_decoder_vp6_alpha_free (SwfdecVideoDecoder *dec)
-{
- SwfdecCodecVp6Alpha *vp6 = (SwfdecCodecVp6Alpha *) dec;
-
- if (vp6->image)
- swfdec_video_decoder_free (vp6->image);
- if (vp6->alpha)
- swfdec_video_decoder_free (vp6->alpha);
- g_free (vp6);
-}
-
-SwfdecVideoDecoder *
-swfdec_video_decoder_vp6_alpha_new (guint type)
-{
- SwfdecCodecVp6Alpha *vp6;
-
- if (type != SWFDEC_VIDEO_CODEC_VP6_ALPHA)
- return NULL;
-
- vp6 = g_new0 (SwfdecCodecVp6Alpha, 1);
- vp6->decoder.decode = swfdec_video_decoder_vp6_alpha_decode;
- vp6->decoder.free = swfdec_video_decoder_vp6_alpha_free;
- vp6->image = swfdec_video_decoder_new (SWFDEC_VIDEO_CODEC_VP6);
- vp6->alpha = swfdec_video_decoder_new (SWFDEC_VIDEO_CODEC_VP6);
- if (vp6->alpha == NULL || vp6->image == NULL) {
- swfdec_video_decoder_vp6_alpha_free (&vp6->decoder);
- return NULL;
- }
-
- return &vp6->decoder;
-}
-
diff --git a/swfdec/swfdec_decoder.c b/swfdec/swfdec_decoder.c
index 4991ea7..9ce55b8 100644
--- a/swfdec/swfdec_decoder.c
+++ b/swfdec/swfdec_decoder.c
@@ -25,12 +25,12 @@
#include "swfdec_decoder.h"
#include "swfdec_audio_decoder.h"
-#include "swfdec_codec_video.h"
#include "swfdec_debug.h"
#include "swfdec_decoder.h"
#include "swfdec_image.h"
#include "swfdec_image_decoder.h"
#include "swfdec_swf_decoder.h"
+#include "swfdec_video_decoder.h"
enum {
MISSING_PLUGINS,
@@ -135,7 +135,8 @@ swfdec_decoder_use_video_codec (SwfdecDecoder *decoder, guint codec)
g_return_if_fail (SWFDEC_IS_DECODER (decoder));
- detail = swfdec_video_decoder_prepare (codec);
+ if (swfdec_video_decoder_prepare (codec, &detail))
+ return;
if (detail == NULL)
return;
diff --git a/swfdec/swfdec_flv_decoder.c b/swfdec/swfdec_flv_decoder.c
index a8d1aba..29c6817 100644
--- a/swfdec/swfdec_flv_decoder.c
+++ b/swfdec/swfdec_flv_decoder.c
@@ -27,6 +27,7 @@
#include "swfdec_bits.h"
#include "swfdec_debug.h"
#include "swfdec_player_internal.h"
+#include "swfdec_video_decoder.h"
enum {
SWFDEC_STATE_HEADER, /* need to parse header */
diff --git a/swfdec/swfdec_flv_decoder.h b/swfdec/swfdec_flv_decoder.h
index 3bf7b4b..ab1b1dd 100644
--- a/swfdec/swfdec_flv_decoder.h
+++ b/swfdec/swfdec_flv_decoder.h
@@ -21,7 +21,6 @@
#define __SWFDEC_FLV_DECODER_H__
#include <swfdec/swfdec_audio_internal.h>
-#include <swfdec/swfdec_codec_video.h>
#include <swfdec/swfdec_decoder.h>
G_BEGIN_DECLS
diff --git a/swfdec/swfdec_init.c b/swfdec/swfdec_init.c
index 12aef51..91e14e8 100644
--- a/swfdec/swfdec_init.c
+++ b/swfdec/swfdec_init.c
@@ -27,12 +27,15 @@
#include <gst/gst.h>
#include <gst/pbutils/pbutils.h>
#include "swfdec_audio_decoder_gst.h"
+#include "swfdec_video_decoder_gst.h"
#endif
#include <liboil/liboil.h>
#include "swfdec_audio_decoder_adpcm.h"
#include "swfdec_audio_decoder_uncompressed.h"
#include "swfdec_debug.h"
+#include "swfdec_video_decoder_screen.h"
+#include "swfdec_video_decoder_vp6_alpha.h"
/**
* swfdec_init:
@@ -76,8 +79,11 @@ swfdec_init (void)
* NB: The order is important! */
swfdec_audio_decoder_register (SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED);
swfdec_audio_decoder_register (SWFDEC_TYPE_AUDIO_DECODER_ADPCM);
+ swfdec_video_decoder_register (SWFDEC_TYPE_VIDEO_DECODER_SCREEN);
+ swfdec_video_decoder_register (SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA);
#ifdef HAVE_GST
swfdec_audio_decoder_register (SWFDEC_TYPE_AUDIO_DECODER_GST);
+ swfdec_video_decoder_register (SWFDEC_TYPE_VIDEO_DECODER_GST);
#endif
}
diff --git a/swfdec/swfdec_internal.h b/swfdec/swfdec_internal.h
index 6af7e94..d42af09 100644
--- a/swfdec/swfdec_internal.h
+++ b/swfdec/swfdec_internal.h
@@ -22,22 +22,13 @@
#ifndef _SWFDEC_INTERNAL_H_
#define _SWFDEC_INTERNAL_H_
+#include <swfdec/swfdec_buffer.h>
+#include <swfdec/swfdec_player.h>
#include <swfdec/swfdec_types.h>
-#include <swfdec/swfdec_codec_video.h>
G_BEGIN_DECLS
-/* video codecs */
-
-SwfdecVideoDecoder * swfdec_video_decoder_screen_new (guint format);
-SwfdecVideoDecoder * swfdec_video_decoder_vp6_alpha_new (guint format);
-#ifdef HAVE_GST
-SwfdecVideoDecoder * swfdec_video_decoder_gst_new (guint format);
-gboolean swfdec_video_decoder_gst_prepare (guint codec,
- char ** detail);
-#endif
-
/* AS engine setup code */
void swfdec_player_preinit_global (SwfdecAsContext * context);
diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c
index 350fc67..5df42f3 100644
--- a/swfdec/swfdec_net_stream.c
+++ b/swfdec/swfdec_net_stream.c
@@ -62,6 +62,39 @@ swfdec_net_stream_onstatus (SwfdecNetStream *stream, const char *code, const cha
swfdec_sandbox_unuse (stream->sandbox);
}
+static void
+swfdec_net_stream_decode_video (SwfdecVideoDecoder *decoder, SwfdecBuffer *buffer)
+{
+ if (decoder->codec == SWFDEC_VIDEO_CODEC_VP6 ||
+ decoder->codec == SWFDEC_VIDEO_CODEC_VP6_ALPHA) {
+ /* FIXME: This is somewhat nasty as we modify values in the decoder
+ * directly. I know the current decoders don't mind, but if we expose
+ * the decoder API... */
+ guint wsub, hsub;
+ SwfdecBuffer *tmp;
+ if (buffer->length == 0) {
+ swfdec_video_decoder_error (decoder, "0-byte VP6 video image buffer?");
+ return;
+ }
+ wsub = *buffer->data;
+ hsub = wsub & 0xF;
+ wsub >>= 4;
+ tmp = swfdec_buffer_new_subbuffer (buffer, 1, buffer->length - 1);
+ swfdec_video_decoder_decode (decoder, tmp);
+ swfdec_buffer_unref (tmp);
+ if (hsub || wsub) {
+ if (hsub >= decoder->height || wsub >= decoder->width) {
+ swfdec_video_decoder_error (decoder, "can't reduce size by more than available");
+ return;
+ }
+ decoder->width -= wsub;
+ decoder->height -= hsub;
+ }
+ } else {
+ swfdec_video_decoder_decode (decoder, buffer);
+ }
+}
+
static void swfdec_net_stream_update_playing (SwfdecNetStream *stream);
static void
swfdec_net_stream_video_goto (SwfdecNetStream *stream, guint timestamp)
@@ -91,12 +124,64 @@ swfdec_net_stream_video_goto (SwfdecNetStream *stream, guint timestamp)
if (buffer == NULL) {
SWFDEC_ERROR ("got no buffer - no video available?");
} else {
- if (format != stream->format) {
- if (stream->decoder)
- swfdec_video_decoder_free (stream->decoder);
- stream->format = format;
+ guint next;
+
+ if (stream->decoder && swfdec_video_decoder_get_codec (stream->decoder) != format) {
+ g_object_unref (stream->decoder);
stream->decoder = NULL;
}
+ if (stream->decoder != NULL &&
+ (stream->decoder_time >= stream->current_time)) {
+ g_object_unref (stream->decoder);
+ stream->decoder = NULL;
+ }
+
+ if (stream->decoder == NULL) {
+ buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
+ stream->current_time, TRUE, &format, &stream->decoder_time,
+ &next);
+ stream->decoder = swfdec_video_decoder_new (format);
+ } else {
+ swfdec_flv_decoder_get_video (stream->flvdecoder,
+ stream->decoder_time, FALSE, NULL, NULL, &next);
+ if (next != stream->current_time) {
+ guint key_time, key_next;
+ buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
+ stream->current_time, TRUE, &format, &key_time, &key_next);
+ if (key_time > stream->decoder_time) {
+ stream->decoder_time = key_time;
+ next = key_next;
+ } else {
+ buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
+ next, FALSE, &format, &stream->decoder_time,
+ &next);
+ }
+ } else {
+ buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
+ next, FALSE, &format, &stream->decoder_time,
+ &next);
+ }
+ }
+
+ /* the following things hold:
+ * buffer: next buffer to decode
+ * format: format of that buffer
+ * stream->decoder_time: timestamp of buffer to decode
+ * stream->decoder: non-null, using stream->format
+ */
+ for (;;) {
+ if (format != swfdec_video_decoder_get_codec (stream->decoder)) {
+ g_object_unref (stream->decoder);
+ stream->decoder = swfdec_video_decoder_new (format);
+ }
+ swfdec_net_stream_decode_video (stream->decoder, buffer);
+ if (stream->decoder_time >= stream->current_time)
+ break;
+
+ buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
+ next, FALSE, &format, &stream->decoder_time, &next);
+ }
+
swfdec_video_provider_new_image (SWFDEC_VIDEO_PROVIDER (stream));
}
if (stream->next_time <= stream->current_time) {
@@ -296,49 +381,12 @@ swfdec_net_stream_stream_target_init (SwfdecStreamTargetInterface *iface)
/*** SWFDEC VIDEO PROVIDER ***/
static cairo_surface_t *
-swfdec_net_stream_decode_video (SwfdecVideoDecoder *decoder, SwfdecRenderer *renderer,
- SwfdecBuffer *buffer, guint *width, guint *height)
-{
- cairo_surface_t *surface;
-
- if (decoder->codec == SWFDEC_VIDEO_CODEC_VP6 ||
- decoder->codec == SWFDEC_VIDEO_CODEC_VP6_ALPHA) {
- guint wsub, hsub;
- SwfdecBuffer *tmp;
- if (buffer->length == 0) {
- SWFDEC_ERROR ("0-byte VP6 video image buffer?");
- return NULL;
- }
- wsub = *buffer->data;
- hsub = wsub & 0xF;
- wsub >>= 4;
- tmp = swfdec_buffer_new_subbuffer (buffer, 1, buffer->length - 1);
- surface = swfdec_video_decoder_decode (decoder, renderer, tmp, width, height);
- swfdec_buffer_unref (tmp);
- if (hsub || wsub) {
- if (hsub >= *height || wsub >= *width) {
- SWFDEC_ERROR ("can't reduce size by more than available");
- cairo_surface_destroy (surface);
- return NULL;
- }
- *width -= wsub;
- *height -= hsub;
- }
- } else {
- surface = swfdec_video_decoder_decode (decoder, renderer, buffer, width, height);
- }
- return surface;
-}
-
-static cairo_surface_t *
swfdec_net_stream_video_provider_get_image (SwfdecVideoProvider *provider,
SwfdecRenderer *renderer, guint *width, guint *height)
{
SwfdecNetStream *stream = SWFDEC_NET_STREAM (provider);
SwfdecCachedVideo *cached;
cairo_surface_t *surface;
- SwfdecBuffer *buffer;
- guint next, format;
cached = SWFDEC_CACHED_VIDEO (swfdec_renderer_get_cache (renderer, stream, NULL, NULL));
if (cached != NULL && swfdec_cached_video_get_frame (cached) == stream->current_time) {
@@ -347,70 +395,14 @@ swfdec_net_stream_video_provider_get_image (SwfdecVideoProvider *provider,
return swfdec_cached_video_get_surface (cached);
}
- if (stream->flvdecoder == NULL || stream->flvdecoder->video == NULL)
+ if (stream->decoder == NULL)
return NULL;
- if (stream->decoder != NULL &&
- (stream->decoder_time >= stream->current_time)) {
- swfdec_video_decoder_free (stream->decoder);
- stream->decoder = NULL;
- }
- if (stream->decoder == NULL) {
- buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
- stream->current_time, TRUE, &stream->format, &stream->decoder_time,
- &next);
- stream->decoder = swfdec_video_decoder_new (stream->format);
- if (stream->decoder == NULL)
- return NULL;
- format = stream->format;
- } else {
- swfdec_flv_decoder_get_video (stream->flvdecoder,
- stream->decoder_time, FALSE, NULL, NULL, &next);
- if (next != stream->current_time) {
- guint key_time, key_next;
- buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
- stream->current_time, TRUE, &format, &key_time, &key_next);
- if (key_time > stream->decoder_time) {
- stream->decoder_time = key_time;
- next = key_next;
- } else {
- buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
- next, FALSE, &format, &stream->decoder_time,
- &next);
- }
- } else {
- buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
- next, FALSE, &format, &stream->decoder_time,
- &next);
- }
- }
-
- /* the following things hold:
- * buffer: next buffer to decode
- * format: format of that buffer
- * stream->decoder_time: timestamp of buffer to decode
- * stream->decoder: non-null, using stream->format
- */
- for (;;) {
- if (format != stream->format) {
- swfdec_video_decoder_free (stream->decoder);
- stream->format = format;
- stream->decoder = swfdec_video_decoder_new (stream->format);
- if (stream->decoder == NULL)
- return NULL;
- }
- surface = swfdec_net_stream_decode_video (stream->decoder, renderer,
- buffer, width, height);
- if (surface == NULL)
- return NULL;
- if (stream->decoder_time >= stream->current_time)
- break;
-
- cairo_surface_destroy (surface);
- buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
- next, FALSE, &format, &stream->decoder_time, &next);
- }
-
+ surface = swfdec_video_decoder_get_image (stream->decoder, renderer);
+ if (surface == NULL)
+ return NULL;
+ *width = swfdec_video_decoder_get_width (stream->decoder);
+ *height = swfdec_video_decoder_get_height (stream->decoder);
cached = swfdec_cached_video_new (surface, *width * *height * 4);
swfdec_cached_video_set_frame (cached, stream->decoder_time);
swfdec_cached_video_set_size (cached, *width, *height);
@@ -421,9 +413,25 @@ swfdec_net_stream_video_provider_get_image (SwfdecVideoProvider *provider,
}
static void
+swfdec_net_stream_video_provider_get_size (SwfdecVideoProvider *provider,
+ guint *width, guint *height)
+{
+ SwfdecNetStream *stream = SWFDEC_NET_STREAM (provider);
+
+ if (stream->decoder) {
+ *width = swfdec_video_decoder_get_width (stream->decoder);
+ *height = swfdec_video_decoder_get_height (stream->decoder);
+ } else {
+ *width = 0;
+ *height = 0;
+ }
+}
+
+static void
swfdec_net_stream_video_provider_init (SwfdecVideoProviderInterface *iface)
{
iface->get_image = swfdec_net_stream_video_provider_get_image;
+ iface->get_size = swfdec_net_stream_video_provider_get_size;
}
/*** SWFDEC_NET_STREAM ***/
@@ -443,7 +451,7 @@ swfdec_net_stream_dispose (GObject *object)
stream->surface = NULL;
}
if (stream->decoder) {
- swfdec_video_decoder_free (stream->decoder);
+ g_object_unref (stream->decoder);
stream->decoder = NULL;
}
swfdec_net_stream_set_loader (stream, NULL);
@@ -686,7 +694,7 @@ swfdec_net_stream_seek (SwfdecNetStream *stream, double secs)
return;
}
if (stream->decoder) {
- swfdec_video_decoder_free (stream->decoder);
+ g_object_unref (stream->decoder);
stream->decoder = NULL;
}
msecs = secs * 1000;
diff --git a/swfdec/swfdec_net_stream.h b/swfdec/swfdec_net_stream.h
index 2f7783d..78356c6 100644
--- a/swfdec/swfdec_net_stream.h
+++ b/swfdec/swfdec_net_stream.h
@@ -22,11 +22,11 @@
#include <swfdec/swfdec.h>
#include <swfdec/swfdec_as_object.h>
-#include <swfdec/swfdec_codec_video.h>
#include <swfdec/swfdec_net_connection.h>
#include <swfdec/swfdec_flv_decoder.h>
#include <swfdec/swfdec_player_internal.h>
#include <swfdec/swfdec_sandbox.h>
+#include <swfdec/swfdec_video_decoder.h>
#include <swfdec/swfdec_video_movie.h>
G_BEGIN_DECLS
@@ -60,7 +60,6 @@ struct _SwfdecNetStream
/* video decoding */
guint current_time; /* current playback timestamp */
guint next_time; /* next video image at this timestamp */
- guint format; /* current format */
SwfdecVideoDecoder * decoder; /* decoder used for decoding */
guint decoder_time; /* last timestamp the decoder decoded */
cairo_surface_t * surface; /* current image */
diff --git a/swfdec/swfdec_video.c b/swfdec/swfdec_video.c
index 322a376..a03c758 100644
--- a/swfdec/swfdec_video.c
+++ b/swfdec/swfdec_video.c
@@ -25,6 +25,7 @@
#include "swfdec_debug.h"
#include "swfdec_player_internal.h"
#include "swfdec_swf_decoder.h"
+#include "swfdec_video_decoder.h"
#include "swfdec_video_movie.h"
#include "swfdec_video_video_provider.h"
diff --git a/swfdec/swfdec_video_decoder.c b/swfdec/swfdec_video_decoder.c
new file mode 100644
index 0000000..439f59a
--- /dev/null
+++ b/swfdec/swfdec_video_decoder.c
@@ -0,0 +1,372 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <liboil/liboil.h>
+#include "swfdec_video_decoder.h"
+#include "swfdec_color.h"
+#include "swfdec_debug.h"
+#include "swfdec_renderer_internal.h"
+
+G_DEFINE_TYPE (SwfdecVideoDecoder, swfdec_video_decoder, G_TYPE_OBJECT)
+
+static void
+swfdec_video_decoder_class_init (SwfdecVideoDecoderClass *klass)
+{
+}
+
+static void
+swfdec_video_decoder_init (SwfdecVideoDecoder *video_decoder)
+{
+}
+
+static GSList *video_codecs = NULL;
+
+void
+swfdec_video_decoder_register (GType type)
+{
+ g_return_if_fail (g_type_is_a (type, SWFDEC_TYPE_VIDEO_DECODER));
+
+ video_codecs = g_slist_append (video_codecs, GSIZE_TO_POINTER ((gsize) type));
+}
+
+/**
+ * swfdec_video_codec_get_format:
+ * @codec: codec to check
+ *
+ * Returns the output format used for this codec. Video codecs must use these
+ * codecs when decoding video.
+ *
+ * Returns: the output format to use for this format
+ **/
+SwfdecVideoFormat
+swfdec_video_codec_get_format (guint codec)
+{
+ switch (codec) {
+ case SWFDEC_VIDEO_CODEC_H263:
+ case SWFDEC_VIDEO_CODEC_VP6:
+ case SWFDEC_VIDEO_CODEC_VP6_ALPHA:
+ return SWFDEC_VIDEO_FORMAT_I420;
+ case SWFDEC_VIDEO_CODEC_UNDEFINED:
+ case SWFDEC_VIDEO_CODEC_SCREEN:
+ case SWFDEC_VIDEO_CODEC_SCREEN2:
+ return SWFDEC_VIDEO_FORMAT_RGBA;
+ default:
+ SWFDEC_ERROR ("unknown codec %u, assuming RGBA format", codec);
+ return SWFDEC_VIDEO_FORMAT_RGBA;
+ }
+}
+
+gboolean
+swfdec_video_decoder_prepare (guint codec, char **missing)
+{
+ char *detail = NULL, *s = NULL;
+ GSList *walk;
+
+ for (walk = video_codecs; walk; walk = walk->next) {
+ SwfdecVideoDecoderClass *klass = g_type_class_ref (GPOINTER_TO_SIZE (walk->data));
+ if (klass->prepare (codec, &s)) {
+ g_free (detail);
+ g_free (s);
+ if (missing)
+ *missing = NULL;
+ g_type_class_unref (klass);
+ return TRUE;
+ }
+ if (s) {
+ if (detail == NULL)
+ detail = s;
+ else
+ g_free (s);
+ s = NULL;
+ }
+ g_type_class_unref (klass);
+ }
+ if (missing)
+ *missing = detail;
+ return FALSE;
+}
+
+/**
+ * swfdec_video_decoder_new:
+ * @codec: codec id
+ *
+ * Creates a decoder suitable for decoding @format. If no decoder is available
+ * for the given for mat, %NULL is returned.
+ *
+ * Returns: a new decoder or %NULL
+ **/
+SwfdecVideoDecoder *
+swfdec_video_decoder_new (guint codec)
+{
+ SwfdecVideoDecoder *ret = NULL;
+ GSList *walk;
+
+ for (walk = video_codecs; walk; walk = walk->next) {
+ SwfdecVideoDecoderClass *klass = g_type_class_ref (GPOINTER_TO_SIZE (walk->data));
+ ret = klass->create (codec);
+ g_type_class_unref (klass);
+ if (ret)
+ break;
+ }
+
+ if (ret == NULL) {
+ ret = g_object_new (SWFDEC_TYPE_VIDEO_DECODER, NULL);
+ swfdec_video_decoder_error (ret, "no suitable decoder for video codec %u", codec);
+ }
+
+ ret->codec = codec;
+
+ return ret;
+}
+
+/**
+ * swfdec_video_decoder_decode:
+ * @decoder: a #SwfdecVideoDecoder
+ * @buffer: a #SwfdecBuffer to process
+ *
+ * Hands the decoder a new buffer for decoding. The buffer should be decoded
+ * immediately. It is assumed that width, height and data areas are set to the
+ * correct values upon return from this function.
+ **/
+void
+swfdec_video_decoder_decode (SwfdecVideoDecoder *decoder, SwfdecBuffer *buffer)
+{
+ SwfdecVideoDecoderClass *klass;
+
+ g_return_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder));
+
+ if (decoder->error)
+ return;
+ klass = SWFDEC_VIDEO_DECODER_GET_CLASS (decoder);
+ klass->decode (decoder, buffer);
+}
+
+guint
+swfdec_video_decoder_get_codec (SwfdecVideoDecoder *decoder)
+{
+ g_return_val_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder), SWFDEC_VIDEO_CODEC_UNDEFINED);
+
+ return decoder->codec;
+}
+
+gboolean
+swfdec_video_decoder_get_error (SwfdecVideoDecoder *decoder)
+{
+ g_return_val_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder), TRUE);
+
+ return decoder->error;
+}
+
+guint
+swfdec_video_decoder_get_width (SwfdecVideoDecoder *decoder)
+{
+ g_return_val_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder), 0);
+
+ return decoder->width;
+}
+
+guint
+swfdec_video_decoder_get_height (SwfdecVideoDecoder *decoder)
+{
+ g_return_val_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder), 0);
+
+ return decoder->height;
+}
+
+#define oil_argb(a,r,g,b) (((a) << 24) | ((r) << 16) | ((g) << 8) | b)
+static gint16 jfif_matrix[24] = {
+ 0, 0, -8192, -8192,
+ 16384, 0, 0, 0,
+ 0, 16384, 16384, 16384,
+ 0, 0, -5638, 29032,
+ 0, 22970, -11700, 0,
+ 0, 0, 0, 0
+};
+
+static void
+yuv_mux (guint32 *dest, const guint8 *src_y, const guint8 *src_u, const guint8 *src_v,
+ int n)
+{
+ int i;
+ for (i = 0; i < n; i++) {
+ dest[i] = oil_argb(255, src_y[i], src_u[i], src_v[i]);
+ }
+}
+
+static void
+upsample (guint8 *d, guint8 *s, int n)
+{
+ int i;
+
+ d[0] = s[0];
+
+ for (i = 0; i < n-3; i+=2) {
+ d[i + 1] = (3*s[i/2] + s[i/2+1] + 2)>>2;
+ d[i + 2] = (s[i/2] + 3*s[i/2+1] + 2)>>2;
+ }
+
+ if (n&1) {
+ i = n-3;
+ d[n-2] = s[n/2];
+ d[n-1] = s[n/2];
+ } else {
+ d[n-1] = s[n/2-1];
+ }
+}
+
+static guint8 *
+swfdec_video_i420_to_rgb (SwfdecVideoDecoder *decoder)
+{
+ guint32 *tmp;
+ guint8 *tmp_u;
+ guint8 *tmp_v;
+ guint8 *tmp1;
+ guint32 *argb_image;
+ const guint8 *yp, *up, *vp;
+ guint32 *argbp;
+ int j;
+ guint halfwidth;
+ int halfheight;
+
+ halfwidth = (decoder->width + 1)>>1;
+ tmp = g_malloc (4 * decoder->width * decoder->height);
+ tmp_u = g_malloc (decoder->width);
+ tmp_v = g_malloc (decoder->width);
+ tmp1 = g_malloc (halfwidth);
+ argb_image = g_malloc (4 * decoder->width * decoder->height);
+
+ yp = decoder->plane[0];
+ up = decoder->plane[1];
+ vp = decoder->plane[2];
+ argbp = argb_image;
+ halfheight = (decoder->height+1)>>1;
+ for(j=0;(guint)j<decoder->height;j++){
+ guint32 weight = 192 - 128*(j&1);
+
+ oil_merge_linear_u8(tmp1,
+ up + decoder->rowstride[1] * CLAMP((j-1)/2,0,halfheight-1),
+ up + decoder->rowstride[1] * CLAMP((j+1)/2,0,halfheight-1),
+ &weight, halfwidth);
+ upsample (tmp_u, tmp1, decoder->width);
+ oil_merge_linear_u8(tmp1,
+ vp + decoder->rowstride[2] * CLAMP((j-1)/2,0,halfheight-1),
+ vp + decoder->rowstride[2] * CLAMP((j+1)/2,0,halfheight-1),
+ &weight, halfwidth);
+ upsample (tmp_v, tmp1, decoder->width);
+
+ yuv_mux (tmp, yp, tmp_u, tmp_v, decoder->width);
+ oil_colorspace_argb(argbp, tmp, jfif_matrix, decoder->width);
+ yp += decoder->rowstride[0];
+ argbp += decoder->width;
+ }
+ g_free(tmp);
+ g_free(tmp_u);
+ g_free(tmp_v);
+ g_free(tmp1);
+ return (unsigned char *)argb_image;
+}
+
+/* FIXME: use liboil (or better: cairo) for this */
+static void
+swfdec_video_codec_apply_mask (guint8 *data, guint rowstride, const guint8 *mask,
+ guint mask_rowstride, guint width, guint height)
+{
+ const guint8 *in;
+ guint8 *out;
+ guint x, y;
+
+ data += SWFDEC_COLOR_INDEX_ALPHA;
+ for (y = 0; y < height; y++) {
+ in = mask;
+ out = data;
+ for (x = 0; x < width; x++) {
+ *out = *in;
+ out += 4;
+ in++;
+ }
+ mask += mask_rowstride;
+ data += rowstride;
+ }
+}
+
+cairo_surface_t *
+swfdec_video_decoder_get_image (SwfdecVideoDecoder *decoder, SwfdecRenderer *renderer)
+{
+ cairo_surface_t *surface;
+ guint rowstride;
+ guint8 *data;
+
+ g_return_val_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder), NULL);
+ g_return_val_if_fail (SWFDEC_IS_RENDERER (renderer), NULL);
+
+ if (decoder->error)
+ return NULL;
+
+ if (swfdec_video_codec_get_format (decoder->codec) == SWFDEC_VIDEO_FORMAT_I420) {
+ data = swfdec_video_i420_to_rgb (decoder);
+ if (data == NULL) {
+ SWFDEC_ERROR ("I420 => RGB conversion failed");
+ return NULL;
+ }
+ rowstride = decoder->width * 4;
+ } else {
+ rowstride = decoder->rowstride[0];
+ data = g_memdup (decoder->plane[0], rowstride * decoder->height);
+ }
+ if (decoder->mask) {
+ swfdec_video_codec_apply_mask (data, rowstride, decoder->mask,
+ decoder->mask_rowstride, decoder->width, decoder->height);
+ }
+ surface = swfdec_renderer_create_for_data (renderer, data,
+ decoder->mask ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
+ decoder->width, decoder->height, rowstride);
+ return surface;
+}
+
+void
+swfdec_video_decoder_error (SwfdecVideoDecoder *decoder, const char *error, ...)
+{
+ va_list args;
+
+ g_return_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder));
+ g_return_if_fail (error != NULL);
+
+ va_start (args, error);
+ swfdec_video_decoder_errorv (decoder, error, args);
+ va_end (args);
+}
+
+void
+swfdec_video_decoder_errorv (SwfdecVideoDecoder *decoder, const char *error, va_list args)
+{
+ char *real;
+
+ g_return_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder));
+ g_return_if_fail (error != NULL);
+
+ real = g_strdup_vprintf (error, args);
+ SWFDEC_ERROR ("error decoding video: %s", real);
+ g_free (real);
+ decoder->error = TRUE;
+}
+
diff --git a/swfdec/swfdec_video_decoder.h b/swfdec/swfdec_video_decoder.h
new file mode 100644
index 0000000..2b1b663
--- /dev/null
+++ b/swfdec/swfdec_video_decoder.h
@@ -0,0 +1,113 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SWFDEC_VIDEO_DECODER_H_
+#define _SWFDEC_VIDEO_DECODER_H_
+
+#include <swfdec/swfdec_buffer.h>
+#include <swfdec/swfdec_renderer.h>
+
+G_BEGIN_DECLS
+
+
+#define SWFDEC_VIDEO_CODEC_UNDEFINED 0
+#define SWFDEC_VIDEO_CODEC_H263 2
+#define SWFDEC_VIDEO_CODEC_SCREEN 3
+#define SWFDEC_VIDEO_CODEC_VP6 4
+#define SWFDEC_VIDEO_CODEC_VP6_ALPHA 5
+#define SWFDEC_VIDEO_CODEC_SCREEN2 6
+
+typedef enum {
+ SWFDEC_VIDEO_FORMAT_RGBA,
+ SWFDEC_VIDEO_FORMAT_I420
+} SwfdecVideoFormat;
+
+
+typedef struct _SwfdecVideoDecoder SwfdecVideoDecoder;
+typedef struct _SwfdecVideoDecoderClass SwfdecVideoDecoderClass;
+
+#define SWFDEC_TYPE_VIDEO_DECODER (swfdec_video_decoder_get_type())
+#define SWFDEC_IS_VIDEO_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_VIDEO_DECODER))
+#define SWFDEC_IS_VIDEO_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_VIDEO_DECODER))
+#define SWFDEC_VIDEO_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_VIDEO_DECODER, SwfdecVideoDecoder))
+#define SWFDEC_VIDEO_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_VIDEO_DECODER, SwfdecVideoDecoderClass))
+#define SWFDEC_VIDEO_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_VIDEO_DECODER, SwfdecVideoDecoderClass))
+
+struct _SwfdecVideoDecoder
+{
+ GObject object;
+
+ /*< protected >*/
+ guint width; /* width of the current image */
+ guint height; /* height of the current image */
+ guint8 * plane[3]; /* planes of the image, not all might be used */
+ guint rowstride[3]; /* rowstrides of the planes */
+ guint8 * mask; /* A8 mask or NULL if none */
+ guint mask_rowstride; /* rowstride of mask plane */
+ /*< private >*/
+ guint codec; /* codec this decoder uses */
+ gboolean error; /* if this codec is in an error state */
+};
+
+struct _SwfdecVideoDecoderClass
+{
+ /*< private >*/
+ GObjectClass object_class;
+
+ /*< public >*/
+ gboolean (* prepare) (guint codec,
+ char ** missing);
+ SwfdecVideoDecoder * (* create) (guint codec);
+
+ void (* decode) (SwfdecVideoDecoder * decoder,
+ SwfdecBuffer * buffer);
+};
+
+SwfdecVideoFormat swfdec_video_codec_get_format (guint codec);
+
+GType swfdec_video_decoder_get_type (void);
+
+void swfdec_video_decoder_register (GType type);
+
+gboolean swfdec_video_decoder_prepare (guint codec,
+ char ** missing);
+
+SwfdecVideoDecoder * swfdec_video_decoder_new (guint codec);
+
+void swfdec_video_decoder_decode (SwfdecVideoDecoder * decoder,
+ SwfdecBuffer * buffer);
+guint swfdec_video_decoder_get_codec (SwfdecVideoDecoder * decoder);
+guint swfdec_video_decoder_get_width (SwfdecVideoDecoder * decoder);
+guint swfdec_video_decoder_get_height (SwfdecVideoDecoder * decoder);
+cairo_surface_t * swfdec_video_decoder_get_image (SwfdecVideoDecoder * decoder,
+ SwfdecRenderer * renderer);
+gboolean swfdec_video_decoder_get_error (SwfdecVideoDecoder * decoder);
+
+/* for subclasses */
+void swfdec_video_decoder_error (SwfdecVideoDecoder * decoder,
+ const char * error,
+ ...) G_GNUC_PRINTF (2, 3);
+void swfdec_video_decoder_errorv (SwfdecVideoDecoder * decoder,
+ const char * error,
+ va_list args);
+
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_video_decoder_gst.c b/swfdec/swfdec_video_decoder_gst.c
new file mode 100644
index 0000000..8122bc6
--- /dev/null
+++ b/swfdec/swfdec_video_decoder_gst.c
@@ -0,0 +1,211 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <gst/pbutils/pbutils.h>
+
+#include "swfdec_video_decoder_gst.h"
+#include "swfdec_codec_gst.h"
+#include "swfdec_debug.h"
+
+static GstCaps *
+swfdec_video_decoder_get_caps (guint codec)
+{
+ GstCaps *caps;
+
+ switch (codec) {
+ case SWFDEC_VIDEO_CODEC_H263:
+ caps = gst_caps_from_string ("video/x-flash-video");
+ break;
+ case SWFDEC_VIDEO_CODEC_VP6:
+ caps = gst_caps_from_string ("video/x-vp6-flash");
+ break;
+ default:
+ return NULL;
+ }
+ g_assert (caps);
+ return caps;
+}
+
+static GstCaps *
+swfdec_video_decoder_get_sink_caps (guint codec)
+{
+ switch (swfdec_video_codec_get_format (codec)) {
+ case SWFDEC_VIDEO_FORMAT_RGBA:
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
+ "red_mask=16711680, green_mask=65280, blue_mask=255");
+#else
+ return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
+ "red_mask=65280, green_mask=16711680, blue_mask=-16777216");
+#endif
+ case SWFDEC_VIDEO_FORMAT_I420:
+ return gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)I420");
+ default:
+ g_return_val_if_reached (NULL);
+ }
+}
+
+G_DEFINE_TYPE (SwfdecVideoDecoderGst, swfdec_video_decoder_gst, SWFDEC_TYPE_VIDEO_DECODER)
+
+static gboolean
+swfdec_video_decoder_gst_prepare (guint codec, char **missing)
+{
+ GstElementFactory *factory;
+ GstCaps *caps;
+
+ /* Check if we can handle the format at all. If not, no plugin will help us. */
+ caps = swfdec_video_decoder_get_caps (codec);
+ if (caps == NULL)
+ return FALSE;
+
+ /* If we can already handle it, woohoo! */
+ factory = swfdec_gst_get_element_factory (caps);
+ if (factory != NULL) {
+ gst_object_unref (factory);
+ gst_caps_unref (caps);
+ return TRUE;
+ }
+
+ /* need to install plugins... */
+ *missing = gst_missing_decoder_installer_detail_new (caps);
+ gst_caps_unref (caps);
+ return FALSE;
+}
+
+static SwfdecVideoDecoder *
+swfdec_video_decoder_gst_create (guint codec)
+{
+ SwfdecVideoDecoderGst *player;
+ GstCaps *srccaps, *sinkcaps;
+
+ srccaps = swfdec_video_decoder_get_caps (codec);
+ if (srccaps == NULL)
+ return NULL;
+ sinkcaps = swfdec_video_decoder_get_sink_caps (codec);
+
+ player = g_object_new (SWFDEC_TYPE_VIDEO_DECODER_GST, NULL);
+
+ if (!swfdec_gst_decoder_init (&player->dec, srccaps, sinkcaps, NULL)) {
+ g_object_unref (player);
+ gst_caps_unref (srccaps);
+ gst_caps_unref (sinkcaps);
+ return NULL;
+ }
+
+ gst_caps_unref (srccaps);
+ gst_caps_unref (sinkcaps);
+ return &player->decoder;
+}
+
+static void
+swfdec_video_decoder_gst_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer)
+{
+ SwfdecVideoDecoderGst *player = SWFDEC_VIDEO_DECODER_GST (dec);
+#define SWFDEC_ALIGN(x, n) (((x) + (n) - 1) & (~((n) - 1)))
+ GstBuffer *buf;
+ GstCaps *caps;
+ GstStructure *structure;
+
+ if (player->last) {
+ gst_buffer_unref (player->last);
+ player->last = NULL;
+ }
+
+ buf = swfdec_gst_buffer_new (swfdec_buffer_ref (buffer));
+ if (!swfdec_gst_decoder_push (&player->dec, buf)) {
+ swfdec_video_decoder_error (dec, "failed to push buffer");
+ return;
+ }
+
+ player->last = swfdec_gst_decoder_pull (&player->dec);
+ if (player->last == NULL) {
+ swfdec_video_decoder_error (dec, "failed to pull decoded buffer");
+ return;
+ }
+ while ((buf = swfdec_gst_decoder_pull (&player->dec))) {
+ SWFDEC_ERROR ("too many output buffers!");
+ gst_buffer_unref (buf);
+ }
+ caps = gst_buffer_get_caps (player->last);
+ if (caps == NULL) {
+ swfdec_video_decoder_error (dec, "no caps on decoded buffer");
+ return;
+ }
+ structure = gst_caps_get_structure (caps, 0);
+ if (!gst_structure_get_int (structure, "width", (int *) &dec->width) ||
+ !gst_structure_get_int (structure, "height", (int *) &dec->height)) {
+ swfdec_video_decoder_error (dec, "invalid caps on decoded buffer");
+ return;
+ }
+ buf = player->last;
+ switch (swfdec_video_codec_get_format (dec->codec)) {
+ case SWFDEC_VIDEO_FORMAT_RGBA:
+ dec->plane[0] = buf->data;
+ dec->rowstride[0] = dec->width * 4;
+ break;
+ case SWFDEC_VIDEO_FORMAT_I420:
+ dec->plane[0] = buf->data;
+ dec->rowstride[0] = SWFDEC_ALIGN (dec->width, 4);
+ dec->plane[1] = dec->plane[0] + dec->rowstride[0] * SWFDEC_ALIGN (dec->height, 2);
+ dec->rowstride[1] = SWFDEC_ALIGN (dec->width, 8) / 2;
+ dec->plane[2] = dec->plane[1] + dec->rowstride[1] * SWFDEC_ALIGN (dec->height, 2) / 2;
+ dec->rowstride[2] = dec->rowstride[1];
+ g_assert (dec->plane[2] + dec->rowstride[2] * SWFDEC_ALIGN (dec->height, 2) / 2 == dec->plane[0] + buf->size);
+ break;
+ default:
+ g_return_if_reached ();
+ }
+#undef SWFDEC_ALIGN
+}
+
+static void
+swfdec_video_decoder_gst_dispose (GObject *object)
+{
+ SwfdecVideoDecoderGst *player = SWFDEC_VIDEO_DECODER_GST (object);
+
+ swfdec_gst_decoder_finish (&player->dec);
+ if (player->last)
+ gst_buffer_unref (player->last);
+
+ G_OBJECT_CLASS (swfdec_video_decoder_gst_parent_class)->dispose (object);
+}
+
+static void
+swfdec_video_decoder_gst_class_init (SwfdecVideoDecoderGstClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SwfdecVideoDecoderClass *decoder_class = SWFDEC_VIDEO_DECODER_CLASS (klass);
+
+ object_class->dispose = swfdec_video_decoder_gst_dispose;
+
+ decoder_class->prepare = swfdec_video_decoder_gst_prepare;
+ decoder_class->create = swfdec_video_decoder_gst_create;
+ decoder_class->decode = swfdec_video_decoder_gst_decode;
+}
+
+static void
+swfdec_video_decoder_gst_init (SwfdecVideoDecoderGst *dec)
+{
+}
+
diff --git a/swfdec/swfdec_video_decoder_gst.h b/swfdec/swfdec_video_decoder_gst.h
new file mode 100644
index 0000000..4fcc151
--- /dev/null
+++ b/swfdec/swfdec_video_decoder_gst.h
@@ -0,0 +1,56 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SWFDEC_VIDEO_DECODER_GST_H_
+#define _SWFDEC_VIDEO_DECODER_GST_H_
+
+#include <swfdec/swfdec_codec_gst.h>
+#include <swfdec/swfdec_video_decoder.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecVideoDecoderGst SwfdecVideoDecoderGst;
+typedef struct _SwfdecVideoDecoderGstClass SwfdecVideoDecoderGstClass;
+
+#define SWFDEC_TYPE_VIDEO_DECODER_GST (swfdec_video_decoder_gst_get_type())
+#define SWFDEC_IS_VIDEO_DECODER_GST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_VIDEO_DECODER_GST))
+#define SWFDEC_IS_VIDEO_DECODER_GST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_VIDEO_DECODER_GST))
+#define SWFDEC_VIDEO_DECODER_GST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_VIDEO_DECODER_GST, SwfdecVideoDecoderGst))
+#define SWFDEC_VIDEO_DECODER_GST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_VIDEO_DECODER_GST, SwfdecVideoDecoderGstClass))
+#define SWFDEC_VIDEO_DECODER_GST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_VIDEO_DECODER_GST, SwfdecVideoDecoderGstClass))
+
+struct _SwfdecVideoDecoderGst
+{
+ SwfdecVideoDecoder decoder;
+
+ SwfdecGstDecoder dec; /* the decoder element */
+ GstBuffer * last; /* last decoded buffer */
+};
+
+struct _SwfdecVideoDecoderGstClass
+{
+ SwfdecVideoDecoderClass decoder_class;
+};
+
+GType swfdec_video_decoder_gst_get_type (void);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_video_decoder_screen.c b/swfdec/swfdec_video_decoder_screen.c
new file mode 100644
index 0000000..8a7b91d
--- /dev/null
+++ b/swfdec/swfdec_video_decoder_screen.c
@@ -0,0 +1,138 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "swfdec_video_decoder_screen.h"
+#include "swfdec_bits.h"
+#include "swfdec_debug.h"
+
+G_DEFINE_TYPE (SwfdecVideoDecoderScreen, swfdec_video_decoder_screen, SWFDEC_TYPE_VIDEO_DECODER)
+
+static gboolean
+swfdec_video_decoder_screen_prepare (guint codec, char **missing)
+{
+ return codec == SWFDEC_VIDEO_CODEC_SCREEN;
+}
+
+static SwfdecVideoDecoder *
+swfdec_video_decoder_screen_create (guint codec)
+{
+ if (codec != SWFDEC_VIDEO_CODEC_SCREEN)
+ return NULL;
+
+ return g_object_new (SWFDEC_TYPE_VIDEO_DECODER_SCREEN, NULL);
+}
+
+static void
+swfdec_video_decoder_screen_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer)
+{
+ SwfdecBits bits;
+ guint i, j, w, h, bw, bh, stride;
+
+ swfdec_bits_init (&bits, buffer);
+ bw = (swfdec_bits_getbits (&bits, 4) + 1) * 16;
+ w = swfdec_bits_getbits (&bits, 12);
+ bh = (swfdec_bits_getbits (&bits, 4) + 1) * 16;
+ h = swfdec_bits_getbits (&bits, 12);
+ if (dec->width == 0 || dec->height == 0) {
+ if (w == 0 || h == 0) {
+ swfdec_video_decoder_error (dec, "width or height is 0: %ux%u", w, h);
+ return;
+ }
+ /* check for overflow */
+ if (w * 4 * h < w * 4) {
+ swfdec_video_decoder_error (dec, "overflowing video size: %ux%u", w, h);
+ return;
+ }
+ dec->plane[0] = g_try_malloc (w * h * 4);
+ if (dec->plane[0] == NULL) {
+ swfdec_video_decoder_error (dec, "could not allocate %u bytes", w * h * 4);
+ return;
+ }
+ dec->width = w;
+ dec->height = h;
+ dec->rowstride[0] = w * 4;
+ } else if (dec->width != w || dec->height != h) {
+ swfdec_video_decoder_error (dec, "width or height differ from original: was %ux%u, is %ux%u",
+ dec->width, dec->height, w, h);
+ /* FIXME: this is what ffmpeg does, should we be more forgiving? */
+ return;
+ }
+ stride = w * 4;
+ SWFDEC_LOG ("size: %u x %u - block size %u x %u\n", w, h, bw, bh);
+ for (j = 0; j < h; j += bh) {
+ for (i = 0; i < w; i += bw) {
+ guint x, y, size;
+ SwfdecBuffer *buf;
+ guint8 *in, *out;
+ size = swfdec_bits_get_bu16 (&bits);
+ if (size == 0)
+ continue;
+ buf = swfdec_bits_decompress (&bits, size, bw * bh * 4);
+ if (buf == NULL) {
+ SWFDEC_ERROR ("could not decode block at %ux%u", i, j);
+ continue;
+ }
+ /* convert format and write out data */
+ out = dec->plane[0] + stride * (h - j - 1) + i * 4;
+ in = buf->data;
+ for (y = 0; y < MIN (bh, h - j); y++) {
+ for (x = 0; x < MIN (bw, w - i); x++) {
+ out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_BLUE] = *in++;
+ out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_GREEN] = *in++;
+ out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_RED] = *in++;
+ out[x * 4 - y * stride + SWFDEC_COLOR_INDEX_ALPHA] = 0xFF;
+ }
+ }
+ swfdec_buffer_unref (buf);
+ }
+ }
+}
+
+static void
+swfdec_video_decoder_screen_dispose (GObject *object)
+{
+ SwfdecVideoDecoder *dec = SWFDEC_VIDEO_DECODER (object);
+
+ g_free (dec->plane[0]);
+
+ G_OBJECT_CLASS (swfdec_video_decoder_screen_parent_class)->dispose (object);
+}
+
+static void
+swfdec_video_decoder_screen_class_init (SwfdecVideoDecoderScreenClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SwfdecVideoDecoderClass *decoder_class = SWFDEC_VIDEO_DECODER_CLASS (klass);
+
+ object_class->dispose = swfdec_video_decoder_screen_dispose;
+
+ decoder_class->prepare = swfdec_video_decoder_screen_prepare;
+ decoder_class->create = swfdec_video_decoder_screen_create;
+ decoder_class->decode = swfdec_video_decoder_screen_decode;
+}
+
+static void
+swfdec_video_decoder_screen_init (SwfdecVideoDecoderScreen *dec)
+{
+}
+
diff --git a/swfdec/swfdec_video_decoder_screen.h b/swfdec/swfdec_video_decoder_screen.h
new file mode 100644
index 0000000..2c84515
--- /dev/null
+++ b/swfdec/swfdec_video_decoder_screen.h
@@ -0,0 +1,52 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SWFDEC_VIDEO_DECODER_SCREEN_H_
+#define _SWFDEC_VIDEO_DECODER_SCREEN_H_
+
+#include <swfdec/swfdec_video_decoder.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecVideoDecoderScreen SwfdecVideoDecoderScreen;
+typedef struct _SwfdecVideoDecoderScreenClass SwfdecVideoDecoderScreenClass;
+
+#define SWFDEC_TYPE_VIDEO_DECODER_SCREEN (swfdec_video_decoder_screen_get_type())
+#define SWFDEC_IS_VIDEO_DECODER_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_VIDEO_DECODER_SCREEN))
+#define SWFDEC_IS_VIDEO_DECODER_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_VIDEO_DECODER_SCREEN))
+#define SWFDEC_VIDEO_DECODER_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_VIDEO_DECODER_SCREEN, SwfdecVideoDecoderScreen))
+#define SWFDEC_VIDEO_DECODER_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_VIDEO_DECODER_SCREEN, SwfdecVideoDecoderScreenClass))
+#define SWFDEC_VIDEO_DECODER_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_VIDEO_DECODER_SCREEN, SwfdecVideoDecoderScreenClass))
+
+struct _SwfdecVideoDecoderScreen
+{
+ SwfdecVideoDecoder decoder;
+};
+
+struct _SwfdecVideoDecoderScreenClass
+{
+ SwfdecVideoDecoderClass decoder_class;
+};
+
+GType swfdec_video_decoder_screen_get_type (void);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_video_decoder_vp6_alpha.c b/swfdec/swfdec_video_decoder_vp6_alpha.c
new file mode 100644
index 0000000..54b50bc
--- /dev/null
+++ b/swfdec/swfdec_video_decoder_vp6_alpha.c
@@ -0,0 +1,138 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <liboil/liboil.h>
+#include "swfdec_video_decoder_vp6_alpha.h"
+#include "swfdec_bits.h"
+#include "swfdec_debug.h"
+
+G_DEFINE_TYPE (SwfdecVideoDecoderVp6Alpha, swfdec_video_decoder_vp6_alpha, SWFDEC_TYPE_VIDEO_DECODER)
+
+static gboolean
+swfdec_video_decoder_vp6_alpha_prepare (guint codec, char **missing)
+{
+ if (codec != SWFDEC_VIDEO_CODEC_VP6_ALPHA)
+ return FALSE;
+
+ return swfdec_video_decoder_prepare (SWFDEC_VIDEO_CODEC_VP6, missing);
+}
+
+static SwfdecVideoDecoder *
+swfdec_video_decoder_vp6_alpha_create (guint codec)
+{
+ if (codec != SWFDEC_VIDEO_CODEC_VP6_ALPHA)
+ return NULL;
+
+ return g_object_new (SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA, NULL);
+}
+
+static void
+swfdec_video_decoder_vp6_alpha_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer)
+{
+ SwfdecVideoDecoderVp6Alpha *vp6 = SWFDEC_VIDEO_DECODER_VP6_ALPHA (dec);
+ SwfdecBuffer *tmp;
+ SwfdecBits bits;
+ guint size;
+
+ swfdec_bits_init (&bits, buffer);
+ size = swfdec_bits_get_bu24 (&bits);
+ tmp = swfdec_bits_get_buffer (&bits, size);
+ if (tmp == NULL) {
+ swfdec_video_decoder_error (dec, "invalid buffer size for image buffer");
+ return;
+ }
+ swfdec_video_decoder_decode (vp6->image, tmp);
+ swfdec_buffer_unref (tmp);
+ tmp = swfdec_bits_get_buffer (&bits, -1);
+ if (tmp == NULL) {
+ swfdec_video_decoder_error (dec, "invalid buffer size for mask buffer");
+ return;
+ }
+ swfdec_video_decoder_decode (vp6->mask, tmp);
+ swfdec_buffer_unref (tmp);
+ if (swfdec_video_decoder_get_error (vp6->image) ||
+ swfdec_video_decoder_get_error (vp6->mask)) {
+ swfdec_video_decoder_error (dec, "decoding of VP6 data failed");
+ return;
+ }
+
+ if (swfdec_video_decoder_get_width (vp6->image) != swfdec_video_decoder_get_width (vp6->mask) ||
+ swfdec_video_decoder_get_height (vp6->image) != swfdec_video_decoder_get_height (vp6->mask)) {
+ SWFDEC_ERROR ("size of mask %ux%u doesn't match image size %ux%u",
+ swfdec_video_decoder_get_width (vp6->mask), swfdec_video_decoder_get_height (vp6->mask),
+ swfdec_video_decoder_get_width (vp6->image), swfdec_video_decoder_get_height (vp6->image));
+ return;
+ }
+ dec->plane[0] = vp6->image->plane[0];
+ dec->plane[1] = vp6->image->plane[1];
+ dec->plane[2] = vp6->image->plane[2];
+ dec->rowstride[0] = vp6->image->rowstride[0];
+ dec->rowstride[1] = vp6->image->rowstride[1];
+ dec->rowstride[2] = vp6->image->rowstride[2];
+ dec->mask = vp6->mask->plane[0];
+ dec->mask_rowstride = vp6->mask->rowstride[0];
+}
+
+static void
+swfdec_video_decoder_vp6_alpha_dispose (GObject *object)
+{
+ SwfdecVideoDecoderVp6Alpha *vp6 = SWFDEC_VIDEO_DECODER_VP6_ALPHA (object);
+
+ if (vp6->image) {
+ g_object_unref (vp6->image);
+ vp6->image = NULL;
+ }
+ if (vp6->mask) {
+ g_object_unref (vp6->mask);
+ vp6->mask = NULL;
+ }
+
+ G_OBJECT_CLASS (swfdec_video_decoder_vp6_alpha_parent_class)->dispose (object);
+}
+
+static void
+swfdec_video_decoder_vp6_alpha_class_init (SwfdecVideoDecoderVp6AlphaClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SwfdecVideoDecoderClass *decoder_class = SWFDEC_VIDEO_DECODER_CLASS (klass);
+
+ object_class->dispose = swfdec_video_decoder_vp6_alpha_dispose;
+
+ decoder_class->prepare = swfdec_video_decoder_vp6_alpha_prepare;
+ decoder_class->create = swfdec_video_decoder_vp6_alpha_create;
+ decoder_class->decode = swfdec_video_decoder_vp6_alpha_decode;
+}
+
+static void
+swfdec_video_decoder_vp6_alpha_init (SwfdecVideoDecoderVp6Alpha *vp6)
+{
+ vp6->image = swfdec_video_decoder_new (SWFDEC_VIDEO_CODEC_VP6);
+ vp6->mask = swfdec_video_decoder_new (SWFDEC_VIDEO_CODEC_VP6);
+
+ if (swfdec_video_decoder_get_error (vp6->image) ||
+ swfdec_video_decoder_get_error (vp6->mask)) {
+ swfdec_video_decoder_error (SWFDEC_VIDEO_DECODER (vp6),
+ "error initializing children VP6 decoders");
+ }
+}
+
diff --git a/swfdec/swfdec_video_decoder_vp6_alpha.h b/swfdec/swfdec_video_decoder_vp6_alpha.h
new file mode 100644
index 0000000..2610c24
--- /dev/null
+++ b/swfdec/swfdec_video_decoder_vp6_alpha.h
@@ -0,0 +1,55 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SWFDEC_VIDEO_DECODER_VP6_ALPHA_H_
+#define _SWFDEC_VIDEO_DECODER_VP6_ALPHA_H_
+
+#include <swfdec/swfdec_video_decoder.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecVideoDecoderVp6Alpha SwfdecVideoDecoderVp6Alpha;
+typedef struct _SwfdecVideoDecoderVp6AlphaClass SwfdecVideoDecoderVp6AlphaClass;
+
+#define SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA (swfdec_video_decoder_vp6_alpha_get_type())
+#define SWFDEC_IS_VIDEO_DECODER_VP6_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA))
+#define SWFDEC_IS_VIDEO_DECODER_VP6_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA))
+#define SWFDEC_VIDEO_DECODER_VP6_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA, SwfdecVideoDecoderVp6Alpha))
+#define SWFDEC_VIDEO_DECODER_VP6_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA, SwfdecVideoDecoderVp6AlphaClass))
+#define SWFDEC_VIDEO_DECODER_VP6_ALPHA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_VIDEO_DECODER_VP6_ALPHA, SwfdecVideoDecoderVp6AlphaClass))
+
+struct _SwfdecVideoDecoderVp6Alpha
+{
+ SwfdecVideoDecoder decoder;
+
+ SwfdecVideoDecoder * image;
+ SwfdecVideoDecoder * mask;
+};
+
+struct _SwfdecVideoDecoderVp6AlphaClass
+{
+ SwfdecVideoDecoderClass decoder_class;
+};
+
+GType swfdec_video_decoder_vp6_alpha_get_type (void);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_video_movie.c b/swfdec/swfdec_video_movie.c
index 2b81519..c846058 100644
--- a/swfdec/swfdec_video_movie.c
+++ b/swfdec/swfdec_video_movie.c
@@ -108,41 +108,26 @@ swfdec_video_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
{
guint version = object->context->version;
SwfdecVideoMovie *video;
- guint w, h;
video = SWFDEC_VIDEO_MOVIE (object);
if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_width) == 0) {
- /* FIXME: find better solution here */
- cairo_surface_t *surface;
+ guint w;
if (video->provider) {
- surface = swfdec_video_provider_get_image (video->provider,
- SWFDEC_PLAYER (object->context)->priv->renderer, &w, &h);
- } else {
- surface = NULL;
- }
- if (surface) {
- cairo_surface_destroy (surface);
+ w = swfdec_video_provider_get_width (video->provider);
} else {
w = 0;
}
- SWFDEC_AS_VALUE_SET_NUMBER (val, w);
+ SWFDEC_AS_VALUE_SET_INT (val, w);
return TRUE;
} else if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_height) == 0) {
- /* FIXME: find better solution here */
- cairo_surface_t *surface;
+ guint h;
if (video->provider) {
- surface = swfdec_video_provider_get_image (video->provider,
- SWFDEC_PLAYER (object->context)->priv->renderer, &w, &h);
- } else {
- surface = NULL;
- }
- if (surface) {
- cairo_surface_destroy (surface);
+ h = swfdec_video_provider_get_height (video->provider);
} else {
h = 0;
}
- SWFDEC_AS_VALUE_SET_NUMBER (val, h);
+ SWFDEC_AS_VALUE_SET_INT (val, h);
return TRUE;
} else if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_deblocking) == 0) {
SWFDEC_STUB ("Video.deblocking (get)");
diff --git a/swfdec/swfdec_video_provider.c b/swfdec/swfdec_video_provider.c
index 4006648..e5c7e0e 100644
--- a/swfdec/swfdec_video_provider.c
+++ b/swfdec/swfdec_video_provider.c
@@ -89,6 +89,34 @@ swfdec_video_provider_get_image (SwfdecVideoProvider *provider,
return iface->get_image (provider, renderer, width, height);
}
+guint
+swfdec_video_provider_get_width (SwfdecVideoProvider *provider)
+{
+ SwfdecVideoProviderInterface *iface;
+ guint w, h;
+
+ g_return_val_if_fail (SWFDEC_IS_VIDEO_PROVIDER (provider), 0);
+
+ iface = SWFDEC_VIDEO_PROVIDER_GET_INTERFACE (provider);
+ g_assert (iface->get_size != NULL);
+ iface->get_size (provider, &w, &h);
+ return w;
+}
+
+guint
+swfdec_video_provider_get_height (SwfdecVideoProvider *provider)
+{
+ SwfdecVideoProviderInterface *iface;
+ guint w, h;
+
+ g_return_val_if_fail (SWFDEC_IS_VIDEO_PROVIDER (provider), 0);
+
+ iface = SWFDEC_VIDEO_PROVIDER_GET_INTERFACE (provider);
+ g_assert (iface->get_size != NULL);
+ iface->get_size (provider, &w, &h);
+ return h;
+}
+
void
swfdec_video_provider_set_ratio (SwfdecVideoProvider *provider, guint ratio)
{
diff --git a/swfdec/swfdec_video_provider.h b/swfdec/swfdec_video_provider.h
index b59f437..b939fee 100644
--- a/swfdec/swfdec_video_provider.h
+++ b/swfdec/swfdec_video_provider.h
@@ -44,6 +44,10 @@ struct _SwfdecVideoProviderInterface {
SwfdecRenderer * renderer,
guint * width,
guint * height);
+ /* get size of current image */
+ void (* get_size) (SwfdecVideoProvider * provider,
+ guint * width,
+ guint * height);
};
GType swfdec_video_provider_get_type (void) G_GNUC_CONST;
@@ -54,6 +58,8 @@ cairo_surface_t * swfdec_video_provider_get_image (SwfdecVideoProvider * p
guint * height);
void swfdec_video_provider_set_ratio (SwfdecVideoProvider * provider,
guint ratio);
+guint swfdec_video_provider_get_width (SwfdecVideoProvider * provider);
+guint swfdec_video_provider_get_height (SwfdecVideoProvider * provider);
/* for subclasses */
void swfdec_video_provider_new_image (SwfdecVideoProvider * provider);
diff --git a/swfdec/swfdec_video_video_provider.c b/swfdec/swfdec_video_video_provider.c
index 0b785c2..74d6bd3 100644
--- a/swfdec/swfdec_video_video_provider.c
+++ b/swfdec/swfdec_video_video_provider.c
@@ -97,7 +97,7 @@ swfdec_video_video_provider_get_image (SwfdecVideoProvider *prov,
if (provider->decoder == NULL || provider->current_frame < provider->decoder_frame) {
if (provider->decoder != NULL) {
- swfdec_video_decoder_free (provider->decoder);
+ g_object_unref (provider->decoder);
}
provider->decoder = swfdec_video_decoder_new (provider->video->format);
if (provider->decoder == NULL)
@@ -112,17 +112,18 @@ swfdec_video_video_provider_get_image (SwfdecVideoProvider *prov,
for (;;) {
g_assert (frame->buffer);
- surface = swfdec_video_decoder_decode (provider->decoder, renderer,
- frame->buffer, &w, &h);
+ swfdec_video_decoder_decode (provider->decoder, frame->buffer);
provider->decoder_frame = provider->current_frame;
- if (surface == NULL)
- return NULL;
if (frame->frame == provider->current_frame)
break;
frame++;
- cairo_surface_destroy (surface);
};
+ surface = swfdec_video_decoder_get_image (provider->decoder, renderer);
+ if (surface == NULL)
+ return NULL;
+ w = swfdec_video_decoder_get_width (provider->decoder);
+ h = swfdec_video_decoder_get_height (provider->decoder);
cached = swfdec_cached_video_new (surface, w * h * 4);
swfdec_cached_video_set_frame (cached, provider->current_frame);
swfdec_cached_video_set_size (cached, w, h);
@@ -136,9 +137,24 @@ swfdec_video_video_provider_get_image (SwfdecVideoProvider *prov,
}
static void
+swfdec_video_video_provider_get_size (SwfdecVideoProvider *prov, guint *width, guint *height)
+{
+ SwfdecVideoVideoProvider *provider = SWFDEC_VIDEO_VIDEO_PROVIDER (prov);
+
+ if (provider->decoder) {
+ *width = swfdec_video_decoder_get_width (provider->decoder);
+ *height = swfdec_video_decoder_get_height (provider->decoder);
+ } else {
+ *width = 0;
+ *height = 0;
+ }
+}
+
+static void
swfdec_video_video_provider_video_provider_init (SwfdecVideoProviderInterface *iface)
{
iface->get_image = swfdec_video_video_provider_get_image;
+ iface->get_size = swfdec_video_video_provider_get_size;
iface->set_ratio = swfdec_video_video_provider_set_ratio;
}
@@ -153,7 +169,7 @@ swfdec_video_video_provider_dispose (GObject *object)
SwfdecVideoVideoProvider * provider = SWFDEC_VIDEO_VIDEO_PROVIDER (object);
if (provider->decoder != NULL) {
- swfdec_video_decoder_free (provider->decoder);
+ g_object_unref (provider->decoder);
provider->decoder = NULL;
}
g_object_unref (provider->video);
diff --git a/swfdec/swfdec_video_video_provider.h b/swfdec/swfdec_video_video_provider.h
index d4804ba..cd9b153 100644
--- a/swfdec/swfdec_video_video_provider.h
+++ b/swfdec/swfdec_video_video_provider.h
@@ -21,8 +21,8 @@
#define _SWFDEC_VIDEO_VIDEO_PROVIDER_H_
#include <swfdec/swfdec_graphic.h>
-#include <swfdec/swfdec_codec_video.h>
#include <swfdec/swfdec_video.h>
+#include <swfdec/swfdec_video_decoder.h>
#include <swfdec/swfdec_video_provider.h>
G_BEGIN_DECLS
commit 49dc3363ac4329f6b4190185b940f828a504a8ae
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jun 25 09:57:46 2008 +0200
fix memleak
diff --git a/swfdec/swfdec_audio_decoder_gst.c b/swfdec/swfdec_audio_decoder_gst.c
index ea343fa..9b29957 100644
--- a/swfdec/swfdec_audio_decoder_gst.c
+++ b/swfdec/swfdec_audio_decoder_gst.c
@@ -74,6 +74,7 @@ swfdec_audio_decoder_gst_prepare (guint codec, SwfdecAudioFormat format, char **
factory = swfdec_gst_get_element_factory (caps);
if (factory != NULL) {
gst_object_unref (factory);
+ gst_caps_unref (caps);
return TRUE;
}
More information about the Swfdec-commits
mailing list