Fix few bugs in SwfdecGtkSocket that made it unusable
[swfdec.git] / swfdec / swfdec_video_video_provider.c
blob74d6bd353112f43e24645ced667f2d2c9cdebe5a
1 /* Swfdec
2 * Copyright (C) 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.
8 *
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
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <stdlib.h>
26 #include "swfdec_video_video_provider.h"
27 #include "swfdec_cached_video.h"
28 #include "swfdec_debug.h"
29 #include "swfdec_font.h"
30 #include "swfdec_player_internal.h"
31 #include "swfdec_renderer_internal.h"
32 #include "swfdec_swf_decoder.h"
34 static SwfdecVideoFrame *
35 swfdec_video_video_provider_find_frame (SwfdecVideo *video, guint frame)
37 SwfdecVideoFrame *cur;
38 guint i;
40 for (i = 0; i < video->images->len; i++) {
41 cur = &g_array_index (video->images, SwfdecVideoFrame, i);
42 if (cur->frame > frame)
43 break;
46 return &g_array_index (video->images, SwfdecVideoFrame, MAX (1, i) - 1);
49 /*** VIDEO PROVIDER INTERFACE ***/
51 static void
52 swfdec_video_video_provider_set_ratio (SwfdecVideoProvider *prov, guint ratio)
54 SwfdecVideoVideoProvider *provider = SWFDEC_VIDEO_VIDEO_PROVIDER (prov);
55 SwfdecVideoFrame *frame;
57 if (ratio >= provider->video->n_frames) {
58 SWFDEC_ERROR ("ratio %u too big: only %u frames", ratio, provider->video->n_frames);
59 ratio = provider->video->n_frames - 1;
62 frame = swfdec_video_video_provider_find_frame (provider->video, ratio);
63 ratio = frame->frame;
65 if (ratio != provider->current_frame) {
66 provider->current_frame = ratio;
67 swfdec_video_provider_new_image (prov);
71 static gboolean
72 swfdec_cached_video_compare (SwfdecCached *cached, gpointer data)
74 return swfdec_cached_video_get_frame (SWFDEC_CACHED_VIDEO (cached)) == GPOINTER_TO_UINT (data);
77 static cairo_surface_t *
78 swfdec_video_video_provider_get_image (SwfdecVideoProvider *prov,
79 SwfdecRenderer *renderer, guint *width, guint *height)
81 SwfdecVideoVideoProvider *provider = SWFDEC_VIDEO_VIDEO_PROVIDER (prov);
82 SwfdecCachedVideo *cached;
83 SwfdecVideoFrame *frame;
84 cairo_surface_t *surface;
85 guint w, h;
87 if (provider->current_frame == 0)
88 return NULL;
90 cached = SWFDEC_CACHED_VIDEO (swfdec_renderer_get_cache (renderer, provider->video,
91 swfdec_cached_video_compare, GUINT_TO_POINTER (provider->current_frame)));
92 if (cached != NULL) {
93 swfdec_cached_use (SWFDEC_CACHED (cached));
94 swfdec_cached_video_get_size (cached, width, height);
95 return swfdec_cached_video_get_surface (cached);
98 if (provider->decoder == NULL || provider->current_frame < provider->decoder_frame) {
99 if (provider->decoder != NULL) {
100 g_object_unref (provider->decoder);
102 provider->decoder = swfdec_video_decoder_new (provider->video->format);
103 if (provider->decoder == NULL)
104 return NULL;
105 frame = &g_array_index (provider->video->images, SwfdecVideoFrame, 0);
106 g_assert (frame->frame <= provider->current_frame);
107 } else {
108 frame = swfdec_video_video_provider_find_frame (provider->video, provider->decoder_frame);
109 g_assert (provider->decoder_frame == frame->frame);
110 frame++;
113 for (;;) {
114 g_assert (frame->buffer);
115 swfdec_video_decoder_decode (provider->decoder, frame->buffer);
116 provider->decoder_frame = provider->current_frame;
117 if (frame->frame == provider->current_frame)
118 break;
119 frame++;
122 surface = swfdec_video_decoder_get_image (provider->decoder, renderer);
123 if (surface == NULL)
124 return NULL;
125 w = swfdec_video_decoder_get_width (provider->decoder);
126 h = swfdec_video_decoder_get_height (provider->decoder);
127 cached = swfdec_cached_video_new (surface, w * h * 4);
128 swfdec_cached_video_set_frame (cached, provider->current_frame);
129 swfdec_cached_video_set_size (cached, w, h);
130 swfdec_renderer_add_cache (renderer, FALSE, provider->video, SWFDEC_CACHED (cached));
131 g_object_unref (cached);
133 *width = w;
134 *height = h;
136 return surface;
139 static void
140 swfdec_video_video_provider_get_size (SwfdecVideoProvider *prov, guint *width, guint *height)
142 SwfdecVideoVideoProvider *provider = SWFDEC_VIDEO_VIDEO_PROVIDER (prov);
144 if (provider->decoder) {
145 *width = swfdec_video_decoder_get_width (provider->decoder);
146 *height = swfdec_video_decoder_get_height (provider->decoder);
147 } else {
148 *width = 0;
149 *height = 0;
153 static void
154 swfdec_video_video_provider_video_provider_init (SwfdecVideoProviderInterface *iface)
156 iface->get_image = swfdec_video_video_provider_get_image;
157 iface->get_size = swfdec_video_video_provider_get_size;
158 iface->set_ratio = swfdec_video_video_provider_set_ratio;
161 /*** SWFDEC_VIDEO_VIDEO_PROVIDER ***/
163 G_DEFINE_TYPE_WITH_CODE (SwfdecVideoVideoProvider, swfdec_video_video_provider, G_TYPE_OBJECT,
164 G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_VIDEO_PROVIDER, swfdec_video_video_provider_video_provider_init))
166 static void
167 swfdec_video_video_provider_dispose (GObject *object)
169 SwfdecVideoVideoProvider * provider = SWFDEC_VIDEO_VIDEO_PROVIDER (object);
171 if (provider->decoder != NULL) {
172 g_object_unref (provider->decoder);
173 provider->decoder = NULL;
175 g_object_unref (provider->video);
177 G_OBJECT_CLASS (swfdec_video_video_provider_parent_class)->dispose (object);
180 static void
181 swfdec_video_video_provider_class_init (SwfdecVideoVideoProviderClass * g_class)
183 GObjectClass *object_class = G_OBJECT_CLASS (g_class);
185 object_class->dispose = swfdec_video_video_provider_dispose;
188 static void
189 swfdec_video_video_provider_init (SwfdecVideoVideoProvider * video)
193 SwfdecVideoProvider *
194 swfdec_video_video_provider_new (SwfdecVideo *video)
196 SwfdecVideoVideoProvider *ret;
198 g_return_val_if_fail (SWFDEC_IS_VIDEO (video), NULL);
200 ret = g_object_new (SWFDEC_TYPE_VIDEO_VIDEO_PROVIDER, NULL);
201 ret->video = g_object_ref (video);
203 return SWFDEC_VIDEO_PROVIDER (ret);