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.
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
25 #include <gst/pbutils/pbutils.h>
27 #include "swfdec_video_decoder_gst.h"
28 #include "swfdec_codec_gst.h"
29 #include "swfdec_debug.h"
32 swfdec_video_decoder_get_caps (guint codec
)
37 case SWFDEC_VIDEO_CODEC_H263
:
38 caps
= gst_caps_from_string ("video/x-flash-video");
40 case SWFDEC_VIDEO_CODEC_VP6
:
41 caps
= gst_caps_from_string ("video/x-vp6-flash");
51 swfdec_video_decoder_get_sink_caps (guint codec
)
53 switch (swfdec_video_codec_get_format (codec
)) {
54 case SWFDEC_VIDEO_FORMAT_RGBA
:
55 #if G_BYTE_ORDER == G_BIG_ENDIAN
56 return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
57 "red_mask=16711680, green_mask=65280, blue_mask=255");
59 return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
60 "red_mask=65280, green_mask=16711680, blue_mask=-16777216");
62 case SWFDEC_VIDEO_FORMAT_I420
:
63 return gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)I420");
65 g_return_val_if_reached (NULL
);
69 G_DEFINE_TYPE (SwfdecVideoDecoderGst
, swfdec_video_decoder_gst
, SWFDEC_TYPE_VIDEO_DECODER
)
72 swfdec_video_decoder_gst_prepare (guint codec
, char **missing
)
74 GstElementFactory
*factory
;
77 /* Check if we can handle the format at all. If not, no plugin will help us. */
78 caps
= swfdec_video_decoder_get_caps (codec
);
82 /* If we can already handle it, woohoo! */
83 factory
= swfdec_gst_get_element_factory (caps
);
84 if (factory
!= NULL
) {
85 gst_object_unref (factory
);
86 gst_caps_unref (caps
);
90 /* need to install plugins... */
91 *missing
= gst_missing_decoder_installer_detail_new (caps
);
92 gst_caps_unref (caps
);
96 static SwfdecVideoDecoder
*
97 swfdec_video_decoder_gst_create (guint codec
)
99 SwfdecVideoDecoderGst
*player
;
100 GstCaps
*srccaps
, *sinkcaps
;
102 srccaps
= swfdec_video_decoder_get_caps (codec
);
105 sinkcaps
= swfdec_video_decoder_get_sink_caps (codec
);
107 player
= g_object_new (SWFDEC_TYPE_VIDEO_DECODER_GST
, NULL
);
109 if (!swfdec_gst_decoder_init (&player
->dec
, srccaps
, sinkcaps
, NULL
)) {
110 g_object_unref (player
);
111 gst_caps_unref (srccaps
);
112 gst_caps_unref (sinkcaps
);
116 gst_caps_unref (srccaps
);
117 gst_caps_unref (sinkcaps
);
118 return &player
->decoder
;
122 swfdec_video_decoder_gst_decode (SwfdecVideoDecoder
*dec
, SwfdecBuffer
*buffer
)
124 SwfdecVideoDecoderGst
*player
= SWFDEC_VIDEO_DECODER_GST (dec
);
125 #define SWFDEC_ALIGN(x, n) (((x) + (n) - 1) & (~((n) - 1)))
128 GstStructure
*structure
;
130 buf
= swfdec_gst_buffer_new (swfdec_buffer_ref (buffer
));
131 if (!swfdec_gst_decoder_push (&player
->dec
, buf
)) {
132 swfdec_video_decoder_error (dec
, "failed to push buffer");
136 buf
= swfdec_gst_decoder_pull (&player
->dec
);
138 SWFDEC_ERROR ("failed to pull decoded buffer. Broken stream?");
142 gst_buffer_unref (player
->last
);
146 while ((buf
= swfdec_gst_decoder_pull (&player
->dec
))) {
147 SWFDEC_ERROR ("too many output buffers!");
148 gst_buffer_unref (buf
);
150 caps
= gst_buffer_get_caps (player
->last
);
152 swfdec_video_decoder_error (dec
, "no caps on decoded buffer");
155 structure
= gst_caps_get_structure (caps
, 0);
156 if (!gst_structure_get_int (structure
, "width", (int *) &dec
->width
) ||
157 !gst_structure_get_int (structure
, "height", (int *) &dec
->height
)) {
158 swfdec_video_decoder_error (dec
, "invalid caps on decoded buffer");
162 switch (swfdec_video_codec_get_format (dec
->codec
)) {
163 case SWFDEC_VIDEO_FORMAT_RGBA
:
164 dec
->plane
[0] = buf
->data
;
165 dec
->rowstride
[0] = dec
->width
* 4;
167 case SWFDEC_VIDEO_FORMAT_I420
:
168 dec
->plane
[0] = buf
->data
;
169 dec
->rowstride
[0] = SWFDEC_ALIGN (dec
->width
, 4);
170 dec
->plane
[1] = dec
->plane
[0] + dec
->rowstride
[0] * SWFDEC_ALIGN (dec
->height
, 2);
171 dec
->rowstride
[1] = SWFDEC_ALIGN (dec
->width
, 8) / 2;
172 dec
->plane
[2] = dec
->plane
[1] + dec
->rowstride
[1] * SWFDEC_ALIGN (dec
->height
, 2) / 2;
173 dec
->rowstride
[2] = dec
->rowstride
[1];
174 g_assert (dec
->plane
[2] + dec
->rowstride
[2] * SWFDEC_ALIGN (dec
->height
, 2) / 2 == dec
->plane
[0] + buf
->size
);
177 g_return_if_reached ();
183 swfdec_video_decoder_gst_dispose (GObject
*object
)
185 SwfdecVideoDecoderGst
*player
= SWFDEC_VIDEO_DECODER_GST (object
);
187 swfdec_gst_decoder_finish (&player
->dec
);
189 gst_buffer_unref (player
->last
);
191 G_OBJECT_CLASS (swfdec_video_decoder_gst_parent_class
)->dispose (object
);
195 swfdec_video_decoder_gst_class_init (SwfdecVideoDecoderGstClass
*klass
)
197 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
198 SwfdecVideoDecoderClass
*decoder_class
= SWFDEC_VIDEO_DECODER_CLASS (klass
);
200 object_class
->dispose
= swfdec_video_decoder_gst_dispose
;
202 decoder_class
->prepare
= swfdec_video_decoder_gst_prepare
;
203 decoder_class
->create
= swfdec_video_decoder_gst_create
;
204 decoder_class
->decode
= swfdec_video_decoder_gst_decode
;
208 swfdec_video_decoder_gst_init (SwfdecVideoDecoderGst
*dec
)