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");
43 case SWFDEC_VIDEO_CODEC_H264
:
44 caps
= gst_caps_from_string ("video/x-h264");
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");
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");
65 case SWFDEC_VIDEO_FORMAT_I420
:
66 return gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)I420");
68 g_return_val_if_reached (NULL
);
72 G_DEFINE_TYPE (SwfdecVideoDecoderGst
, swfdec_video_decoder_gst
, SWFDEC_TYPE_VIDEO_DECODER
)
75 swfdec_video_decoder_gst_prepare (guint codec
, char **missing
)
77 GstElementFactory
*factory
;
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
);
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
);
93 /* need to install plugins... */
94 *missing
= gst_missing_decoder_installer_detail_new (caps
);
95 gst_caps_unref (caps
);
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
);
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
);
119 gst_caps_unref (srccaps
);
120 gst_caps_unref (sinkcaps
);
121 return &player
->decoder
;
125 swfdec_video_decoder_gst_set_codec_data (SwfdecVideoDecoder
*dec
,
126 SwfdecBuffer
*buffer
)
128 SwfdecVideoDecoderGst
*player
= SWFDEC_VIDEO_DECODER_GST (dec
);
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
);
135 swfdec_gst_decoder_set_codec_data (&player
->dec
, NULL
);
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)))
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");
154 buf
= swfdec_gst_decoder_pull (&player
->dec
);
156 SWFDEC_ERROR ("failed to pull decoded buffer. Broken stream?");
160 gst_buffer_unref (player
->last
);
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
);
170 swfdec_video_decoder_error (dec
, "no caps on decoded buffer");
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");
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;
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
);
195 g_return_if_reached ();
201 swfdec_video_decoder_gst_dispose (GObject
*object
)
203 SwfdecVideoDecoderGst
*player
= SWFDEC_VIDEO_DECODER_GST (object
);
205 swfdec_gst_decoder_finish (&player
->dec
);
207 gst_buffer_unref (player
->last
);
209 G_OBJECT_CLASS (swfdec_video_decoder_gst_parent_class
)->dispose (object
);
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
;
227 swfdec_video_decoder_gst_init (SwfdecVideoDecoderGst
*dec
)