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.
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
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
;
40 for (i
= 0; i
< video
->images
->len
; i
++) {
41 cur
= &g_array_index (video
->images
, SwfdecVideoFrame
, i
);
42 if (cur
->frame
> frame
)
46 return &g_array_index (video
->images
, SwfdecVideoFrame
, MAX (1, i
) - 1);
49 /*** VIDEO PROVIDER INTERFACE ***/
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
);
65 if (ratio
!= provider
->current_frame
) {
66 provider
->current_frame
= ratio
;
67 swfdec_video_provider_new_image (prov
);
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
;
87 if (provider
->current_frame
== 0)
90 cached
= SWFDEC_CACHED_VIDEO (swfdec_renderer_get_cache (renderer
, provider
->video
,
91 swfdec_cached_video_compare
, GUINT_TO_POINTER (provider
->current_frame
)));
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
)
105 frame
= &g_array_index (provider
->video
->images
, SwfdecVideoFrame
, 0);
106 g_assert (frame
->frame
<= provider
->current_frame
);
108 frame
= swfdec_video_video_provider_find_frame (provider
->video
, provider
->decoder_frame
);
109 g_assert (provider
->decoder_frame
== frame
->frame
);
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
)
122 surface
= swfdec_video_decoder_get_image (provider
->decoder
, renderer
);
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
);
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
);
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
))
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
);
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
;
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
);