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
24 #include "swfdec_video_decoder_screen.h"
25 #include "swfdec_bits.h"
26 #include "swfdec_debug.h"
28 G_DEFINE_TYPE (SwfdecVideoDecoderScreen
, swfdec_video_decoder_screen
, SWFDEC_TYPE_VIDEO_DECODER
)
31 swfdec_video_decoder_screen_prepare (guint codec
, char **missing
)
33 return codec
== SWFDEC_VIDEO_CODEC_SCREEN
;
36 static SwfdecVideoDecoder
*
37 swfdec_video_decoder_screen_create (guint codec
)
39 if (codec
!= SWFDEC_VIDEO_CODEC_SCREEN
)
42 return g_object_new (SWFDEC_TYPE_VIDEO_DECODER_SCREEN
, NULL
);
46 swfdec_video_decoder_screen_decode (SwfdecVideoDecoder
*dec
, SwfdecBuffer
*buffer
)
49 guint i
, j
, w
, h
, bw
, bh
, stride
;
51 swfdec_bits_init (&bits
, buffer
);
52 bw
= (swfdec_bits_getbits (&bits
, 4) + 1) * 16;
53 w
= swfdec_bits_getbits (&bits
, 12);
54 bh
= (swfdec_bits_getbits (&bits
, 4) + 1) * 16;
55 h
= swfdec_bits_getbits (&bits
, 12);
56 if (dec
->width
== 0 || dec
->height
== 0) {
57 if (w
== 0 || h
== 0) {
58 swfdec_video_decoder_error (dec
, "width or height is 0: %ux%u", w
, h
);
61 /* check for overflow */
62 if (w
* 4 * h
< w
* 4) {
63 swfdec_video_decoder_error (dec
, "overflowing video size: %ux%u", w
, h
);
66 dec
->plane
[0] = g_try_malloc (w
* h
* 4);
67 if (dec
->plane
[0] == NULL
) {
68 swfdec_video_decoder_error (dec
, "could not allocate %u bytes", w
* h
* 4);
73 dec
->rowstride
[0] = w
* 4;
74 } else if (dec
->width
!= w
|| dec
->height
!= h
) {
75 swfdec_video_decoder_error (dec
, "width or height differ from original: was %ux%u, is %ux%u",
76 dec
->width
, dec
->height
, w
, h
);
77 /* FIXME: this is what ffmpeg does, should we be more forgiving? */
81 SWFDEC_LOG ("size: %u x %u - block size %u x %u", w
, h
, bw
, bh
);
82 for (j
= 0; j
< h
; j
+= bh
) {
83 for (i
= 0; i
< w
; i
+= bw
) {
84 guint x
, y
, size
, curw
, curh
;
87 size
= swfdec_bits_get_bu16 (&bits
);
90 curw
= MIN (bw
, w
- i
);
91 curh
= MIN (bh
, h
- j
);
92 buf
= swfdec_bits_decompress (&bits
, size
, curw
* curh
* 3);
94 SWFDEC_ERROR ("could not decode block at %ux%u", i
, j
);
97 /* convert format and write out data */
98 out
= dec
->plane
[0] + stride
* (h
- j
- 1) + i
* 4;
100 for (y
= 0; y
< curh
; y
++) {
101 for (x
= 0; x
< curw
; x
++) {
102 out
[x
* 4 + SWFDEC_COLOR_INDEX_BLUE
] = *in
++;
103 out
[x
* 4 + SWFDEC_COLOR_INDEX_GREEN
] = *in
++;
104 out
[x
* 4 + SWFDEC_COLOR_INDEX_RED
] = *in
++;
105 out
[x
* 4 + SWFDEC_COLOR_INDEX_ALPHA
] = 0xFF;
109 swfdec_buffer_unref (buf
);
115 swfdec_video_decoder_screen_dispose (GObject
*object
)
117 SwfdecVideoDecoder
*dec
= SWFDEC_VIDEO_DECODER (object
);
119 g_free (dec
->plane
[0]);
121 G_OBJECT_CLASS (swfdec_video_decoder_screen_parent_class
)->dispose (object
);
125 swfdec_video_decoder_screen_class_init (SwfdecVideoDecoderScreenClass
*klass
)
127 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
128 SwfdecVideoDecoderClass
*decoder_class
= SWFDEC_VIDEO_DECODER_CLASS (klass
);
130 object_class
->dispose
= swfdec_video_decoder_screen_dispose
;
132 decoder_class
->prepare
= swfdec_video_decoder_screen_prepare
;
133 decoder_class
->create
= swfdec_video_decoder_screen_create
;
134 decoder_class
->decode
= swfdec_video_decoder_screen_decode
;
138 swfdec_video_decoder_screen_init (SwfdecVideoDecoderScreen
*dec
)