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
, SwfdecBuffer
*buffer
)
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");
48 swfdec_buffer_ref (buffer
);
49 gstbuf
= swfdec_gst_buffer_new (buffer
);
50 gst_caps_set_simple (caps
, "codec_data", GST_TYPE_BUFFER
, gstbuf
, NULL
);
51 gst_buffer_unref (gstbuf
);
62 swfdec_video_decoder_get_sink_caps (guint codec
)
64 switch (swfdec_video_codec_get_format (codec
)) {
65 case SWFDEC_VIDEO_FORMAT_RGBA
:
66 #if G_BYTE_ORDER == G_BIG_ENDIAN
67 return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
68 "red_mask=16711680, green_mask=65280, blue_mask=255");
70 return gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
71 "red_mask=65280, green_mask=16711680, blue_mask=-16777216");
73 case SWFDEC_VIDEO_FORMAT_I420
:
74 return gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)I420");
76 g_return_val_if_reached (NULL
);
80 G_DEFINE_TYPE (SwfdecVideoDecoderGst
, swfdec_video_decoder_gst
, SWFDEC_TYPE_VIDEO_DECODER
)
83 swfdec_video_decoder_gst_prepare (guint codec
, char **missing
)
85 GstElementFactory
*factory
;
88 /* Check if we can handle the format at all. If not, no plugin will help us. */
89 caps
= swfdec_video_decoder_get_caps (codec
, NULL
);
93 /* If we can already handle it, woohoo! */
94 factory
= swfdec_gst_get_element_factory (caps
);
95 if (factory
!= NULL
) {
96 gst_object_unref (factory
);
97 gst_caps_unref (caps
);
101 /* need to install plugins... */
102 *missing
= gst_missing_decoder_installer_detail_new (caps
);
103 gst_caps_unref (caps
);
107 static SwfdecVideoDecoder
*
108 swfdec_video_decoder_gst_create (guint codec
, SwfdecBuffer
*buffer
)
110 SwfdecVideoDecoderGst
*player
;
111 GstCaps
*srccaps
, *sinkcaps
;
113 srccaps
= swfdec_video_decoder_get_caps (codec
, buffer
);
116 sinkcaps
= swfdec_video_decoder_get_sink_caps (codec
);
118 player
= g_object_new (SWFDEC_TYPE_VIDEO_DECODER_GST
, NULL
);
120 if (!swfdec_gst_decoder_init (&player
->dec
, srccaps
, sinkcaps
, NULL
)) {
121 g_object_unref (player
);
122 gst_caps_unref (srccaps
);
123 gst_caps_unref (sinkcaps
);
127 gst_caps_unref (srccaps
);
128 gst_caps_unref (sinkcaps
);
129 return &player
->decoder
;
133 swfdec_video_decoder_gst_decode (SwfdecVideoDecoder
*dec
, SwfdecBuffer
*buffer
)
135 SwfdecVideoDecoderGst
*player
= SWFDEC_VIDEO_DECODER_GST (dec
);
136 #define SWFDEC_ALIGN(x, n) (((x) + (n) - 1) & (~((n) - 1)))
139 GstStructure
*structure
;
141 buf
= swfdec_gst_buffer_new (swfdec_buffer_ref (buffer
));
142 if (!swfdec_gst_decoder_push (&player
->dec
, buf
)) {
143 swfdec_video_decoder_error (dec
, "failed to push buffer");
147 buf
= swfdec_gst_decoder_pull (&player
->dec
);
149 SWFDEC_ERROR ("failed to pull decoded buffer. Broken stream?");
153 gst_buffer_unref (player
->last
);
157 while ((buf
= swfdec_gst_decoder_pull (&player
->dec
))) {
158 SWFDEC_ERROR ("too many output buffers!");
159 gst_buffer_unref (buf
);
161 caps
= gst_buffer_get_caps (player
->last
);
163 swfdec_video_decoder_error (dec
, "no caps on decoded buffer");
166 structure
= gst_caps_get_structure (caps
, 0);
167 if (!gst_structure_get_int (structure
, "width", (int *) &dec
->width
) ||
168 !gst_structure_get_int (structure
, "height", (int *) &dec
->height
)) {
169 swfdec_video_decoder_error (dec
, "invalid caps on decoded buffer");
173 switch (swfdec_video_codec_get_format (dec
->codec
)) {
174 case SWFDEC_VIDEO_FORMAT_RGBA
:
175 dec
->plane
[0] = buf
->data
;
176 dec
->rowstride
[0] = dec
->width
* 4;
178 case SWFDEC_VIDEO_FORMAT_I420
:
179 dec
->plane
[0] = buf
->data
;
180 dec
->rowstride
[0] = SWFDEC_ALIGN (dec
->width
, 4);
181 dec
->plane
[1] = dec
->plane
[0] + dec
->rowstride
[0] * SWFDEC_ALIGN (dec
->height
, 2);
182 dec
->rowstride
[1] = SWFDEC_ALIGN (dec
->width
, 8) / 2;
183 dec
->plane
[2] = dec
->plane
[1] + dec
->rowstride
[1] * SWFDEC_ALIGN (dec
->height
, 2) / 2;
184 dec
->rowstride
[2] = dec
->rowstride
[1];
185 g_assert (dec
->plane
[2] + dec
->rowstride
[2] * SWFDEC_ALIGN (dec
->height
, 2) / 2 == dec
->plane
[0] + buf
->size
);
188 g_return_if_reached ();
194 swfdec_video_decoder_gst_dispose (GObject
*object
)
196 SwfdecVideoDecoderGst
*player
= SWFDEC_VIDEO_DECODER_GST (object
);
198 swfdec_gst_decoder_finish (&player
->dec
);
200 gst_buffer_unref (player
->last
);
202 G_OBJECT_CLASS (swfdec_video_decoder_gst_parent_class
)->dispose (object
);
206 swfdec_video_decoder_gst_class_init (SwfdecVideoDecoderGstClass
*klass
)
208 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
209 SwfdecVideoDecoderClass
*decoder_class
= SWFDEC_VIDEO_DECODER_CLASS (klass
);
211 object_class
->dispose
= swfdec_video_decoder_gst_dispose
;
213 decoder_class
->prepare
= swfdec_video_decoder_gst_prepare
;
214 decoder_class
->create
= swfdec_video_decoder_gst_create
;
215 decoder_class
->decode
= swfdec_video_decoder_gst_decode
;
219 swfdec_video_decoder_gst_init (SwfdecVideoDecoderGst
*dec
)