add blend mode tests
[swfdec.git] / swfdec / swfdec_video_decoder_gst.c
blob07f48284199bb12a6e8bbb2bc25684d350462483
1 /* Swfdec
2 * Copyright (C) 2007-2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
25 #include <gst/pbutils/pbutils.h>
27 #include "swfdec_video_decoder_gst.h"
28 #include "swfdec_codec_gst.h"
29 #include "swfdec_debug.h"
31 static GstCaps *
32 swfdec_video_decoder_get_caps (guint codec)
34 GstCaps *caps;
36 switch (codec) {
37 case SWFDEC_VIDEO_CODEC_H263:
38 caps = gst_caps_from_string ("video/x-flash-video");
39 break;
40 case SWFDEC_VIDEO_CODEC_VP6:
41 caps = gst_caps_from_string ("video/x-vp6-flash");
42 break;
43 case SWFDEC_VIDEO_CODEC_H264:
44 caps = gst_caps_from_string ("video/x-h264");
45 break;
46 default:
47 return NULL;
49 g_assert (caps);
50 return caps;
53 static GstCaps *
54 swfdec_video_decoder_get_sink_caps (guint codec)
56 switch (swfdec_video_codec_get_format (codec)) {
57 case SWFDEC_VIDEO_FORMAT_RGBA:
58 #if G_BYTE_ORDER == G_BIG_ENDIAN
59 return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
60 "red_mask=16711680, green_mask=65280, blue_mask=255");
61 #else
62 return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
63 "red_mask=65280, green_mask=16711680, blue_mask=-16777216");
64 #endif
65 case SWFDEC_VIDEO_FORMAT_I420:
66 return gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)I420");
67 default:
68 g_return_val_if_reached (NULL);
72 G_DEFINE_TYPE (SwfdecVideoDecoderGst, swfdec_video_decoder_gst, SWFDEC_TYPE_VIDEO_DECODER)
74 static gboolean
75 swfdec_video_decoder_gst_prepare (guint codec, char **missing)
77 GstElementFactory *factory;
78 GstCaps *caps;
80 /* Check if we can handle the format at all. If not, no plugin will help us. */
81 caps = swfdec_video_decoder_get_caps (codec);
82 if (caps == NULL)
83 return FALSE;
85 /* If we can already handle it, woohoo! */
86 factory = swfdec_gst_get_element_factory (caps);
87 if (factory != NULL) {
88 gst_object_unref (factory);
89 gst_caps_unref (caps);
90 return TRUE;
93 /* need to install plugins... */
94 *missing = gst_missing_decoder_installer_detail_new (caps);
95 gst_caps_unref (caps);
96 return FALSE;
99 static SwfdecVideoDecoder *
100 swfdec_video_decoder_gst_create (guint codec)
102 SwfdecVideoDecoderGst *player;
103 GstCaps *srccaps, *sinkcaps;
105 srccaps = swfdec_video_decoder_get_caps (codec);
106 if (srccaps == NULL)
107 return NULL;
108 sinkcaps = swfdec_video_decoder_get_sink_caps (codec);
110 player = g_object_new (SWFDEC_TYPE_VIDEO_DECODER_GST, NULL);
112 if (!swfdec_gst_decoder_init (&player->dec, srccaps, sinkcaps, NULL)) {
113 g_object_unref (player);
114 gst_caps_unref (srccaps);
115 gst_caps_unref (sinkcaps);
116 return NULL;
119 gst_caps_unref (srccaps);
120 gst_caps_unref (sinkcaps);
121 return &player->decoder;
124 static void
125 swfdec_video_decoder_gst_set_codec_data (SwfdecVideoDecoder *dec,
126 SwfdecBuffer *buffer)
128 SwfdecVideoDecoderGst *player = SWFDEC_VIDEO_DECODER_GST (dec);
130 if (buffer) {
131 GstBuffer *buf = swfdec_gst_buffer_new (swfdec_buffer_ref (buffer));
132 swfdec_gst_decoder_set_codec_data (&player->dec, buf);
133 gst_buffer_unref (buf);
134 } else {
135 swfdec_gst_decoder_set_codec_data (&player->dec, NULL);
139 static void
140 swfdec_video_decoder_gst_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer)
142 SwfdecVideoDecoderGst *player = SWFDEC_VIDEO_DECODER_GST (dec);
143 #define SWFDEC_ALIGN(x, n) (((x) + (n) - 1) & (~((n) - 1)))
144 GstBuffer *buf;
145 GstCaps *caps;
146 GstStructure *structure;
148 buf = swfdec_gst_buffer_new (swfdec_buffer_ref (buffer));
149 if (!swfdec_gst_decoder_push (&player->dec, buf)) {
150 swfdec_video_decoder_error (dec, "failed to push buffer");
151 return;
154 buf = swfdec_gst_decoder_pull (&player->dec);
155 if (buf == NULL) {
156 SWFDEC_ERROR ("failed to pull decoded buffer. Broken stream?");
157 return;
158 } else {
159 if (player->last)
160 gst_buffer_unref (player->last);
161 player->last = buf;
164 while ((buf = swfdec_gst_decoder_pull (&player->dec))) {
165 SWFDEC_ERROR ("too many output buffers!");
166 gst_buffer_unref (buf);
168 caps = gst_buffer_get_caps (player->last);
169 if (caps == NULL) {
170 swfdec_video_decoder_error (dec, "no caps on decoded buffer");
171 return;
173 structure = gst_caps_get_structure (caps, 0);
174 if (!gst_structure_get_int (structure, "width", (int *) &dec->width) ||
175 !gst_structure_get_int (structure, "height", (int *) &dec->height)) {
176 swfdec_video_decoder_error (dec, "invalid caps on decoded buffer");
177 return;
179 buf = player->last;
180 switch (swfdec_video_codec_get_format (dec->codec)) {
181 case SWFDEC_VIDEO_FORMAT_RGBA:
182 dec->plane[0] = buf->data;
183 dec->rowstride[0] = dec->width * 4;
184 break;
185 case SWFDEC_VIDEO_FORMAT_I420:
186 dec->plane[0] = buf->data;
187 dec->rowstride[0] = SWFDEC_ALIGN (dec->width, 4);
188 dec->plane[1] = dec->plane[0] + dec->rowstride[0] * SWFDEC_ALIGN (dec->height, 2);
189 dec->rowstride[1] = SWFDEC_ALIGN (dec->width, 8) / 2;
190 dec->plane[2] = dec->plane[1] + dec->rowstride[1] * SWFDEC_ALIGN (dec->height, 2) / 2;
191 dec->rowstride[2] = dec->rowstride[1];
192 g_assert (dec->plane[2] + dec->rowstride[2] * SWFDEC_ALIGN (dec->height, 2) / 2 == dec->plane[0] + buf->size);
193 break;
194 default:
195 g_return_if_reached ();
197 #undef SWFDEC_ALIGN
200 static void
201 swfdec_video_decoder_gst_dispose (GObject *object)
203 SwfdecVideoDecoderGst *player = SWFDEC_VIDEO_DECODER_GST (object);
205 swfdec_gst_decoder_finish (&player->dec);
206 if (player->last)
207 gst_buffer_unref (player->last);
209 G_OBJECT_CLASS (swfdec_video_decoder_gst_parent_class)->dispose (object);
212 static void
213 swfdec_video_decoder_gst_class_init (SwfdecVideoDecoderGstClass *klass)
215 GObjectClass *object_class = G_OBJECT_CLASS (klass);
216 SwfdecVideoDecoderClass *decoder_class = SWFDEC_VIDEO_DECODER_CLASS (klass);
218 object_class->dispose = swfdec_video_decoder_gst_dispose;
220 decoder_class->prepare = swfdec_video_decoder_gst_prepare;
221 decoder_class->create = swfdec_video_decoder_gst_create;
222 decoder_class->set_codec_data = swfdec_video_decoder_gst_set_codec_data;
223 decoder_class->decode = swfdec_video_decoder_gst_decode;
226 static void
227 swfdec_video_decoder_gst_init (SwfdecVideoDecoderGst *dec)