actually set the variable here
[swfdec.git] / swfdec / swfdec_swf_decoder.c
blob46e9960e15b0e5c6c1a337d66227f17545c7e74d
1 /* Swfdec
2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <zlib.h>
27 #include <math.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <liboil/liboil.h>
32 #include "swfdec_swf_decoder.h"
33 #include "swfdec.h"
34 #include "swfdec_bits.h"
35 #include "swfdec_cached.h"
36 #include "swfdec_debug.h"
37 #include "swfdec_player_internal.h"
38 #include "swfdec_script.h"
39 #include "swfdec_script_internal.h"
40 #include "swfdec_sprite.h"
41 #include "swfdec_tag.h"
43 enum {
44 SWFDEC_STATE_INIT1 = 0,
45 SWFDEC_STATE_INIT2,
46 SWFDEC_STATE_PARSE_FIRST_TAG,
47 SWFDEC_STATE_PARSE_TAG,
48 SWFDEC_STATE_EOF,
51 G_DEFINE_TYPE (SwfdecSwfDecoder, swfdec_swf_decoder, SWFDEC_TYPE_DECODER)
53 static void
54 swfdec_swf_decoder_dispose (GObject *object)
56 SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (object);
58 g_hash_table_destroy (s->characters);
59 g_object_unref (s->main_sprite);
60 g_hash_table_destroy (s->scripts);
62 if (s->compressed)
63 inflateEnd (&s->z);
64 if (s->buffer) {
65 swfdec_buffer_unref (s->buffer);
66 s->buffer = NULL;
69 if (s->jpegtables) {
70 swfdec_buffer_unref (s->jpegtables);
71 s->jpegtables = NULL;
74 g_free (s->password);
75 s->password = NULL;
76 g_free (s->metadata);
77 s->metadata = NULL;
79 G_OBJECT_CLASS (swfdec_swf_decoder_parent_class)->dispose (object);
82 static void *
83 zalloc (void *opaque, guint items, guint size)
85 return g_malloc (items * size);
88 static void
89 zfree (void *opaque, void *addr)
91 g_free (addr);
94 static SwfdecBuffer *
95 swfdec_buffer_merge (const SwfdecBuffer *front, const SwfdecBuffer *end)
97 SwfdecBuffer *new;
99 g_return_val_if_fail (front != NULL, NULL);
100 g_return_val_if_fail (end != NULL, NULL);
102 new = swfdec_buffer_new (front->length + end->length);
103 if (front->length)
104 memcpy (new->data, front->data, front->length);
105 if (end->length)
106 memcpy (new->data + front->length, end->data, end->length);
107 return new;
110 static gboolean
111 swfdec_swf_decoder_deflate (SwfdecSwfDecoder * s, SwfdecBuffer *buffer)
113 int ret;
114 SwfdecDecoder *dec = SWFDEC_DECODER (s);
116 if (s->buffer == NULL) {
117 /* never written to */
118 g_assert (s->state == SWFDEC_STATE_INIT1);
119 s->buffer = buffer;
120 } else if (s->state == SWFDEC_STATE_INIT1) {
121 /* not initialized yet */
122 SwfdecBuffer *merge = swfdec_buffer_merge (s->buffer, buffer);
123 swfdec_buffer_unref (s->buffer);
124 swfdec_buffer_unref (buffer);
125 s->buffer = merge;
126 } else if (s->compressed) {
127 s->z.next_in = buffer->data;
128 s->z.avail_in = buffer->length;
129 ret = inflate (&s->z, Z_SYNC_FLUSH);
130 if (ret < Z_OK) {
131 SWFDEC_ERROR ("error uncompressing data: %s", s->z.msg);
132 return FALSE;
135 dec->bytes_loaded = s->z.total_out + 8;
136 swfdec_buffer_unref (buffer);
137 } else {
138 guint max = buffer->length;
140 if (dec->bytes_loaded + max > s->buffer->length) {
141 SWFDEC_WARNING ("%"G_GSIZE_FORMAT" bytes more than declared filesize",
142 dec->bytes_loaded + max - s->buffer->length);
143 max = s->buffer->length - dec->bytes_loaded;
145 memcpy (s->buffer->data + dec->bytes_loaded, buffer->data, max);
146 dec->bytes_loaded += max;
147 swfdec_buffer_unref (buffer);
150 return TRUE;
153 static gboolean
154 swf_inflate_init (SwfdecSwfDecoder * s)
156 z_stream *z;
157 int ret;
158 z = &s->z;
159 z->zalloc = zalloc;
160 z->zfree = zfree;
161 ret = inflateInit (z);
162 SWFDEC_DEBUG ("inflateInit returned %d", ret);
164 z->next_out = s->buffer->data + 8;
165 z->avail_out = s->buffer->length - 8;
166 z->opaque = NULL;
167 return TRUE;
170 static void
171 swfdec_swf_decoder_init_bits (SwfdecSwfDecoder *dec, SwfdecBits *bits)
173 swfdec_bits_init (bits, dec->buffer);
174 bits->end = bits->ptr + SWFDEC_DECODER (dec)->bytes_loaded;
175 bits->ptr += dec->bytes_parsed;
176 g_assert (bits->ptr <= bits->end);
179 static void
180 swfdec_swf_decoder_flush_bits (SwfdecSwfDecoder *dec, SwfdecBits *bits)
182 g_assert (bits->idx == 0);
183 g_assert (bits->buffer == dec->buffer);
185 dec->bytes_parsed = bits->ptr - dec->buffer->data;
186 g_assert (dec->bytes_parsed <= SWFDEC_DECODER (dec)->bytes_loaded);
189 static int
190 swf_parse_header1 (SwfdecSwfDecoder * s)
192 SwfdecDecoder *dec = SWFDEC_DECODER (s);
193 int sig1, sig2, sig3;
194 SwfdecBuffer *buffer, *rest;
195 SwfdecBits bits;
196 guint8 *data;
198 g_assert (s->buffer != NULL);
199 if (s->buffer->length <= 8) {
200 return SWFDEC_STATUS_NEEDBITS;
203 swfdec_bits_init (&bits, s->buffer);
205 sig1 = swfdec_bits_get_u8 (&bits);
206 sig2 = swfdec_bits_get_u8 (&bits);
207 sig3 = swfdec_bits_get_u8 (&bits);
208 if ((sig1 != 'F' && sig1 != 'C') || sig2 != 'W' || sig3 != 'S') {
209 return SWFDEC_STATUS_ERROR;
212 s->version = swfdec_bits_get_u8 (&bits);
213 dec->bytes_total = swfdec_bits_get_u32 (&bits);
214 if (dec->bytes_total <= 8) {
215 SWFDEC_ERROR ("Joke? Flash files need to be bigger than %u bytes", dec->bytes_total);
216 dec->bytes_total = 0;
217 return SWFDEC_STATUS_ERROR;
219 rest = swfdec_bits_get_buffer (&bits, -1);
221 data = g_try_malloc (dec->bytes_total);
222 if (data == NULL)
223 return SWFDEC_STATUS_ERROR;
224 buffer = swfdec_buffer_new_for_data (data, dec->bytes_total);
225 memcpy (buffer->data, s->buffer->data, 8);
226 swfdec_buffer_unref (s->buffer);
227 s->buffer = buffer;
229 s->compressed = (sig1 == 'C');
230 if (s->compressed) {
231 SWFDEC_DEBUG ("compressed");
232 if (!swf_inflate_init (s))
233 return SWFDEC_STATUS_ERROR;
234 } else {
235 SWFDEC_DEBUG ("not compressed");
237 SWFDEC_DECODER (s)->bytes_loaded = 8;
238 s->bytes_parsed = 8;
239 s->state = SWFDEC_STATE_INIT2;
240 swfdec_swf_decoder_deflate (s, rest);
241 dec->data_type = SWFDEC_LOADER_DATA_SWF;
243 return SWFDEC_STATUS_OK;
246 static int
247 swf_parse_header2 (SwfdecSwfDecoder * s)
249 guint n;
250 SwfdecRect rect;
251 SwfdecDecoder *dec = SWFDEC_DECODER (s);
253 swfdec_swf_decoder_init_bits (s, &s->b);
254 n = swfdec_bits_peekbits (&s->b, 5);
255 /* rect rate + total_frames */
256 n = ((5 + 4 * n + 7) / 8 + (2 + 2)) * 8;
257 if (swfdec_bits_left (&s->b) < n)
258 return SWFDEC_STATUS_NEEDBITS;
260 swfdec_bits_get_rect (&s->b, &rect);
261 if (rect.x0 != 0.0 || rect.y0 != 0.0)
262 SWFDEC_ERROR ("SWF window doesn't start at 0 0 but at %g %g", rect.x0, rect.y0);
263 SWFDEC_INFO ("SWF size: %g x %g pixels", rect.x1 / SWFDEC_TWIPS_SCALE_FACTOR,
264 rect.y1 / SWFDEC_TWIPS_SCALE_FACTOR);
265 dec->width = MAX (0, ceil (rect.x1 / SWFDEC_TWIPS_SCALE_FACTOR));
266 dec->height = MAX (0, ceil (rect.y1 / SWFDEC_TWIPS_SCALE_FACTOR));
267 swfdec_bits_syncbits (&s->b);
268 dec->rate = swfdec_bits_get_u16 (&s->b);
269 if (dec->rate == 0) {
270 SWFDEC_INFO ("rate is 0, setting to 65536");
271 dec->rate = 65536;
273 SWFDEC_LOG ("rate = %g", dec->rate / 256.0);
274 dec->frames_total = swfdec_bits_get_u16 (&s->b);
275 SWFDEC_LOG ("n_frames = %d", dec->frames_total);
276 swfdec_sprite_set_n_frames (s->main_sprite, dec->frames_total, dec->rate);
278 swfdec_swf_decoder_flush_bits (s, &s->b);
280 s->state = SWFDEC_STATE_PARSE_FIRST_TAG;
281 return SWFDEC_STATUS_INIT;
284 static SwfdecStatus
285 swfdec_swf_decoder_parse_one (SwfdecSwfDecoder *s)
287 int ret = SWFDEC_STATUS_OK;
289 s->b = s->parse;
291 switch (s->state) {
292 case SWFDEC_STATE_INIT1:
293 ret = swf_parse_header1 (s);
294 break;
295 case SWFDEC_STATE_INIT2:
296 ret = swf_parse_header2 (s);
297 break;
298 case SWFDEC_STATE_PARSE_FIRST_TAG:
299 case SWFDEC_STATE_PARSE_TAG:
301 guint header_length;
302 guint x;
303 SwfdecTagFunc func;
304 guint tag;
305 guint tag_len;
306 SwfdecBits bits;
308 /* we're parsing tags */
309 swfdec_swf_decoder_init_bits (s, &bits);
310 if (swfdec_bits_left (&bits) < 2 * 8)
311 return SWFDEC_STATUS_NEEDBITS;
313 x = swfdec_bits_get_u16 (&bits);
314 tag = x >> 6;
315 SWFDEC_DEBUG ("tag %d %s", tag, swfdec_swf_decoder_get_tag_name (tag));
316 tag_len = x & 0x3f;
317 if (tag_len == 0x3f) {
318 if (swfdec_bits_left (&bits) < 4 * 8)
319 return SWFDEC_STATUS_NEEDBITS;
321 tag_len = swfdec_bits_get_u32 (&bits);
322 header_length = 6;
323 } else {
324 header_length = 2;
327 SWFDEC_INFO ("parsing at %d, tag %d %s, length %d",
328 s->bytes_parsed, tag,
329 swfdec_swf_decoder_get_tag_name (tag), tag_len);
331 if (swfdec_bits_left (&bits) / 8 < tag_len)
332 return SWFDEC_STATUS_NEEDBITS;
334 swfdec_bits_init_bits (&s->b, &bits, tag_len);
335 swfdec_swf_decoder_flush_bits (s, &bits);
337 func = swfdec_swf_decoder_get_tag_func (tag);
338 if (tag == 0) {
339 s->state = SWFDEC_STATE_EOF;
340 } else if ((swfdec_swf_decoder_get_tag_flag (tag) & SWFDEC_TAG_FIRST_ONLY)
341 && s->state == SWFDEC_STATE_PARSE_TAG) {
342 SWFDEC_WARNING ("tag %d %s must be first tag in file, ignoring",
343 tag, swfdec_swf_decoder_get_tag_name (tag));
344 } else if (func == NULL) {
345 SWFDEC_FIXME ("tag function not implemented for %d %s",
346 tag, swfdec_swf_decoder_get_tag_name (tag));
347 } else if (s->main_sprite->parse_frame < s->main_sprite->n_frames) {
348 s->parse_sprite = s->main_sprite;
349 ret = func (s, tag);
350 s->parse_sprite = NULL;
352 if (swfdec_bits_left (&s->b)) {
353 SWFDEC_WARNING
354 ("early finish (%d bytes) at %d, tag %d %s, length %d",
355 swfdec_bits_left (&s->b) / 8,
356 s->bytes_parsed, tag,
357 swfdec_swf_decoder_get_tag_name (tag), tag_len);
359 } else {
360 ret = SWFDEC_STATE_EOF;
361 SWFDEC_ERROR ("data after last frame");
363 s->state = SWFDEC_STATE_PARSE_TAG;
365 break;
367 case SWFDEC_STATE_EOF:
368 if (s->bytes_parsed < SWFDEC_DECODER (s)->bytes_loaded) {
369 SWFDEC_WARNING ("%u bytes after EOF", SWFDEC_DECODER (s)->bytes_loaded - s->bytes_parsed);
371 return SWFDEC_STATUS_EOF;
372 default:
373 g_assert_not_reached ();
376 /* copy state */
377 SWFDEC_DECODER (s)->frames_loaded = s->main_sprite->parse_frame;
379 return ret;
382 static SwfdecStatus
383 swfdec_swf_decoder_parse (SwfdecDecoder *dec, SwfdecBuffer *buffer)
385 SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (dec);
386 SwfdecStatus status = 0;
388 swfdec_swf_decoder_deflate (s, buffer);
389 do {
390 status |= swfdec_swf_decoder_parse_one (s);
391 } while ((status & (SWFDEC_STATUS_EOF | SWFDEC_STATUS_NEEDBITS | SWFDEC_STATUS_ERROR)) == 0);
392 return status;
395 static SwfdecStatus
396 swfdec_swf_decoder_eof (SwfdecDecoder *dec)
398 if (dec->bytes_loaded < dec->bytes_total) {
399 SWFDEC_ERROR ("only %u of %u bytes provided, broken transmission?",
400 dec->bytes_loaded, dec->bytes_total);
403 return 0;
406 static void
407 swfdec_swf_decoder_class_init (SwfdecSwfDecoderClass *class)
409 GObjectClass *object_class = G_OBJECT_CLASS (class);
410 SwfdecDecoderClass *decoder_class = SWFDEC_DECODER_CLASS (class);
412 object_class->dispose = swfdec_swf_decoder_dispose;
414 decoder_class->parse = swfdec_swf_decoder_parse;
415 decoder_class->eof = swfdec_swf_decoder_eof;
418 static void
419 swfdec_swf_decoder_init (SwfdecSwfDecoder *s)
421 s->main_sprite = g_object_new (SWFDEC_TYPE_SPRITE, NULL);
423 s->characters = g_hash_table_new_full (g_direct_hash, g_direct_equal,
424 NULL, g_object_unref);
425 s->scripts = g_hash_table_new_full (g_direct_hash, g_direct_equal,
426 NULL, (GDestroyNotify) swfdec_script_unref);
429 gpointer
430 swfdec_swf_decoder_get_character (SwfdecSwfDecoder * s, guint id)
432 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (s), NULL);
434 return g_hash_table_lookup (s->characters, GUINT_TO_POINTER (id));
438 * swfdec_swf_decoder_create_character:
439 * @s: a #SwfdecDecoder
440 * @id: id of the character
441 * @type: the required type for the character
443 * Gets the character of the requested @type and with the given @id from @s.
444 * If there is already a different character with the given id, return NULL.
445 * If the character doesn't exist yet, create it.
447 * Returns: The requested character or NULL on failure;
449 gpointer
450 swfdec_swf_decoder_create_character (SwfdecSwfDecoder * s, guint id, GType type)
452 SwfdecCharacter *result;
454 g_return_val_if_fail (SWFDEC_IS_DECODER (s), NULL);
455 g_return_val_if_fail (g_type_is_a (type, SWFDEC_TYPE_CHARACTER), NULL);
457 SWFDEC_INFO (" id = %d", id);
458 result = swfdec_swf_decoder_get_character (s, id);
459 if (result) {
460 SWFDEC_WARNING ("character with id %d already exists", id);
461 return NULL;
463 result = g_object_new (type, NULL);
464 result->id = id;
465 g_hash_table_insert (s->characters, GUINT_TO_POINTER (id), result);
467 return result;
470 void
471 swfdec_swf_decoder_add_script (SwfdecSwfDecoder *s, SwfdecScript *script)
473 g_return_if_fail (SWFDEC_IS_SWF_DECODER (s));
474 g_return_if_fail (script != NULL);
475 g_return_if_fail (script->buffer != NULL);
477 g_hash_table_insert (s->scripts, (gpointer) script->main, script);
480 SwfdecScript *
481 swfdec_swf_decoder_get_script (SwfdecSwfDecoder *s, guint8 *data)
483 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (s), NULL);
484 g_return_val_if_fail (data != NULL, NULL);
486 return g_hash_table_lookup (s->scripts, data);