~ubuntu-branches/ubuntu/saucy/totem/saucy-proposed

« back to all changes in this revision

Viewing changes to src/video-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Loic Minier, Sebastien Bacher, Loic Minier
  • Date: 2007-03-08 14:51:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070308145155-cnu1r0s1z4ffcxza
Tags: 2.16.5-3
[ Sebastien Bacher ]
* debian/patches/30_dlopen_noremove_dbus_glib.dpatch:
  - fix "crash because NPPVpluginKeepLibraryInMemory is broken in gecko",
    patch from Alexander Sack (GNOME bug #415389)

[ Loic Minier ]
* Urgency medium.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
#include "config.h"
3
 
 
4
 
#include "video-utils.h"
5
 
 
6
 
#include <glib/gi18n.h>
7
 
#include <libintl.h>
8
 
 
9
 
#include <gdk/gdk.h>
10
 
#include <gdk/gdkx.h>
11
 
#include <X11/Xlib.h>
12
 
#include <stdlib.h>
13
 
#include <unistd.h>
14
 
#include <string.h>
15
 
#include <stdio.h>
16
 
 
17
 
/* Code taken from:
18
 
 * transcode Copyright (C) Thomas Oestreich - June 2001
19
 
 * enix      enix.berlios.de
20
 
 */
21
 
 
22
 
void yuy2toyv12 (guint8 *y, guint8 *u, guint8 *v, guint8 *input,
23
 
                int width, int height) {
24
 
        int i, j, w2;
25
 
 
26
 
        w2 = width / 2;
27
 
 
28
 
        for (i = 0; i < height; i += 2) {
29
 
                for (j = 0; j < w2; j++) {
30
 
                        /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
31
 
                        *(y++) = *(input++);
32
 
                        *(u++) = *(input++);
33
 
                        *(y++) = *(input++);
34
 
                        *(v++) = *(input++);
35
 
                }
36
 
 
37
 
                /* down sampling */
38
 
                for (j = 0; j < w2; j++) {
39
 
                        /* skip every second line for U and V */
40
 
                        *(y++) = *(input++);
41
 
                        input++;
42
 
                        *(y++) = *(input++);
43
 
                        input++;
44
 
                }
45
 
        }
46
 
}
47
 
 
48
 
#define clip_8_bit(val)                         \
49
 
{                                               \
50
 
        if (val < 0)                            \
51
 
                val = 0;                        \
52
 
        else                                    \
53
 
                if (val > 255) val = 255;       \
54
 
}
55
 
 
56
 
guint8 * yv12torgb (guint8 *src_y, guint8 *src_u, guint8 *src_v,
57
 
                                            int width, int height) {
58
 
          int     i, j;
59
 
 
60
 
          int     y, u, v;
61
 
          int     r, g, b;
62
 
 
63
 
          int     sub_i_uv;
64
 
          int     sub_j_uv;
65
 
 
66
 
          int     uv_width, uv_height;
67
 
 
68
 
          guchar *rgb;
69
 
 
70
 
          uv_width  = width / 2;
71
 
          uv_height = height / 2;
72
 
 
73
 
          rgb = (guchar *) malloc (width * height * 3);
74
 
          if (!rgb)
75
 
                  return NULL;
76
 
 
77
 
          for (i = 0; i < height; ++i) {
78
 
                  /* calculate u & v rows */
79
 
                  sub_i_uv = ((i * uv_height) / height);
80
 
 
81
 
                  for (j = 0; j < width; ++j) {
82
 
                          /* calculate u & v columns */
83
 
                          sub_j_uv = ((j * uv_width) / width);
84
 
 
85
 
          /***************************************************
86
 
           *  Colour conversion from
87
 
           *    http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
88
 
           *
89
 
           *  Thanks to Billy Biggs <vektor@dumbterm.net>
90
 
           *  for the pointer and the following conversion.
91
 
           *
92
 
           *   R' = [ 1.1644         0    1.5960 ]   ([ Y' ]   [  16 ])
93
 
           *   G' = [ 1.1644   -0.3918   -0.8130 ] * ([ Cb ] - [ 128 ])
94
 
           *   B' = [ 1.1644    2.0172         0 ]   ([ Cr ]   [ 128 ])
95
 
           *
96
 
           *  Where in xine the above values are represented as
97
 
           *   Y' == image->y
98
 
           *   Cb == image->u
99
 
           *   Cr == image->v
100
 
           *
101
 
           ***************************************************/
102
 
 
103
 
                          y = src_y[(i * width) + j] - 16;
104
 
                          u = src_u[(sub_i_uv * uv_width) + sub_j_uv] - 128;
105
 
                          v = src_v[(sub_i_uv * uv_width) + sub_j_uv] - 128;
106
 
 
107
 
                          r = (1.1644 * y) + (1.5960 * v);
108
 
                          g = (1.1644 * y) - (0.3918 * u) - (0.8130 * v);
109
 
                          b = (1.1644 * y) + (2.0172 * u);
110
 
 
111
 
                          clip_8_bit (r);
112
 
                          clip_8_bit (g);
113
 
                          clip_8_bit (b);
114
 
 
115
 
                          rgb[(i * width + j) * 3 + 0] = r;
116
 
                          rgb[(i * width + j) * 3 + 1] = g;
117
 
                          rgb[(i * width + j) * 3 + 2] = b;
118
 
                  }
119
 
          }
120
 
 
121
 
          return rgb;
122
 
}
123
 
 
124
 
/* Stolen from GDK */
125
 
static void
126
 
gdk_wmspec_change_state (gboolean   add,
127
 
                         GdkWindow *window,
128
 
                         GdkAtom    state1,
129
 
                         GdkAtom    state2)
130
 
{
131
 
  GdkDisplay *display = gdk_screen_get_display (gdk_drawable_get_screen (GDK_DRAWABLE (window)));
132
 
  XEvent xev;
133
 
  
134
 
#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
135
 
#define _NET_WM_STATE_ADD           1    /* add/set property */
136
 
#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
137
 
  
138
 
  xev.xclient.type = ClientMessage;
139
 
  xev.xclient.serial = 0;
140
 
  xev.xclient.send_event = True;
141
 
  xev.xclient.window = GDK_WINDOW_XID (window);
142
 
  xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
143
 
  xev.xclient.format = 32;
144
 
  xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
145
 
  xev.xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
146
 
  xev.xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
147
 
  
148
 
  XSendEvent (GDK_WINDOW_XDISPLAY (window),
149
 
              GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (gdk_drawable_get_screen (GDK_DRAWABLE (window)))),
150
 
              False, SubstructureRedirectMask | SubstructureNotifyMask,
151
 
              &xev);
152
 
}
153
 
 
154
 
void
155
 
totem_gdk_window_set_always_on_top (GdkWindow *window, gboolean setting)
156
 
{
157
 
  gdk_wmspec_change_state (setting, window, gdk_atom_intern ("_NET_WM_STATE_ABOVE", FALSE), 0);
158
 
}
159
 
 
160
 
void
161
 
eel_gdk_window_set_invisible_cursor (GdkWindow *window)
162
 
{
163
 
        GdkBitmap *empty_bitmap;
164
 
        GdkCursor *cursor;
165
 
        GdkColor useless;
166
 
        char invisible_cursor_bits[] = { 0x0 }; 
167
 
 
168
 
        useless.red = useless.green = useless.blue = 0;
169
 
        useless.pixel = 0;
170
 
 
171
 
        empty_bitmap = gdk_bitmap_create_from_data (window,
172
 
                        invisible_cursor_bits,
173
 
                        1, 1);
174
 
 
175
 
        cursor = gdk_cursor_new_from_pixmap (empty_bitmap,
176
 
                        empty_bitmap,
177
 
                        &useless,
178
 
                        &useless, 0, 0);
179
 
 
180
 
        gdk_window_set_cursor (window, cursor);
181
 
 
182
 
        gdk_cursor_unref (cursor);
183
 
 
184
 
        g_object_unref (empty_bitmap);
185
 
}
186
 
 
187
 
void totem_create_symlinks (const char *orig, const char *dest)
188
 
{
189
 
        GDir *dir;
190
 
        const char *name;
191
 
 
192
 
        dir = g_dir_open (orig, 0, NULL);
193
 
        if (dir == NULL)
194
 
                return;
195
 
 
196
 
        if (g_file_test (dest, G_FILE_TEST_IS_DIR) == FALSE)
197
 
                return;
198
 
 
199
 
        name = g_dir_read_name (dir);
200
 
        while (name != NULL)
201
 
        {
202
 
                char *orig_full, *dest_full;
203
 
 
204
 
                orig_full = g_build_path (G_DIR_SEPARATOR_S, orig, name, NULL);
205
 
                dest_full = g_build_path (G_DIR_SEPARATOR_S, dest, name, NULL);
206
 
 
207
 
                /* We don't check the return value, that's normal,
208
 
                 * we're very silent people */
209
 
                symlink (orig_full, dest_full);
210
 
 
211
 
                g_free (orig_full);
212
 
                g_free (dest_full);
213
 
 
214
 
                name = g_dir_read_name (dir);
215
 
        }
216
 
 
217
 
        g_dir_close (dir);
218
 
}
219
 
 
220
 
gboolean totem_display_is_local (void)
221
 
{
222
 
        const char *name, *work;
223
 
        int display, screen;
224
 
        gboolean has_hostname;
225
 
 
226
 
        name = gdk_display_get_name (gdk_display_get_default ());
227
 
        if (name == NULL)
228
 
                return TRUE;
229
 
 
230
 
        work = strstr (name, ":");
231
 
        if (work == NULL)
232
 
                return TRUE;
233
 
 
234
 
        has_hostname = (work - name) > 0;
235
 
 
236
 
        /* Get to the character after the colon */
237
 
        work++;
238
 
        if (work == NULL)
239
 
                return TRUE;
240
 
 
241
 
        if (sscanf (work, "%d.%d", &display, &screen) != 2)
242
 
                return TRUE;
243
 
 
244
 
        if (has_hostname == FALSE)
245
 
                return TRUE;
246
 
 
247
 
        if (display < 10)
248
 
                return TRUE;
249
 
 
250
 
        return FALSE;
251
 
}
252
 
 
253
 
void
254
 
totem_pixbuf_mirror (GdkPixbuf *pixbuf)
255
 
{
256
 
        int i, j, rowstride, offset, right;
257
 
        guchar *pixels;
258
 
        int width, height, size;
259
 
        guint32 tmp;
260
 
 
261
 
        pixels = gdk_pixbuf_get_pixels (pixbuf);
262
 
        g_return_if_fail (pixels != NULL);
263
 
 
264
 
        width = gdk_pixbuf_get_width (pixbuf);
265
 
        height = gdk_pixbuf_get_height (pixbuf);
266
 
        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
267
 
        size = height * width * sizeof (guint32);
268
 
 
269
 
        for (i = 0; i < size; i += rowstride)
270
 
        {
271
 
                for (j = 0; j < rowstride; j += sizeof(guint32))
272
 
                {
273
 
                        offset = i + j;
274
 
                        right = i + (((width - 1) * sizeof(guint32)) - j);
275
 
 
276
 
                        if (right <= offset)
277
 
                                break;
278
 
 
279
 
                        memcpy (&tmp, pixels + offset, sizeof(guint32));
280
 
                        memcpy (pixels + offset, pixels + right,
281
 
                                        sizeof(guint32));
282
 
                        memcpy (pixels + right, &tmp, sizeof(guint32));
283
 
                }
284
 
        }
285
 
}
286
 
 
287
 
char *
288
 
totem_time_to_string (gint64 msecs)
289
 
{
290
 
        int sec, min, hour, time;
291
 
 
292
 
        time = (int) (msecs / 1000);
293
 
        sec = time % 60;
294
 
        time = time - sec;
295
 
        min = (time % (60*60)) / 60;
296
 
        time = time - (min * 60);
297
 
        hour = time / (60*60);
298
 
 
299
 
        if (hour > 0)
300
 
        {
301
 
                /* hour:minutes:seconds */
302
 
                return g_strdup_printf ("%d:%02d:%02d", hour, min, sec);
303
 
        } else {
304
 
                /* minutes:seconds */
305
 
                return g_strdup_printf ("%d:%02d", min, sec);
306
 
        }
307
 
 
308
 
        return NULL;
309
 
}
310
 
 
311
 
char *
312
 
totem_time_to_string_text (gint64 msecs)
313
 
{
314
 
        char *secs, *mins, *hours, *string;
315
 
        int sec, min, hour, time;
316
 
 
317
 
        time = (int) (msecs / 1000);
318
 
        sec = time % 60;
319
 
        time = time - sec;
320
 
        min = (time % (60*60)) / 60;
321
 
        time = time - (min * 60);
322
 
        hour = time / (60*60);
323
 
 
324
 
        hours = g_strdup_printf (ngettext ("%d hour", "%d hours", hour), hour);
325
 
 
326
 
        mins = g_strdup_printf (ngettext ("%d minute",
327
 
                                          "%d minutes", min), min);
328
 
 
329
 
        secs = g_strdup_printf (ngettext ("%d second",
330
 
                                          "%d seconds", sec), sec);
331
 
 
332
 
        if (hour > 0)
333
 
        {
334
 
                /* hour:minutes:seconds */
335
 
                string = g_strdup_printf (_("%s %s %s"), hours, mins, secs);
336
 
        } else if (min > 0) {
337
 
                /* minutes:seconds */
338
 
                string = g_strdup_printf (_("%s %s"), mins, secs);
339
 
        } else if (sec > 0) {
340
 
                /* seconds */
341
 
                string = g_strdup_printf (_("%s"), secs);
342
 
        } else {
343
 
                /* 0 seconds */
344
 
                string = g_strdup (_("0 seconds"));
345
 
        }
346
 
 
347
 
        g_free (hours);
348
 
        g_free (mins);
349
 
        g_free (secs);
350
 
 
351
 
        return string;
352
 
}
353
 
 
354
 
typedef struct _TotemPrefSize {
355
 
  gint width, height;
356
 
  gulong sig_id;
357
 
} TotemPrefSize;
358
 
 
359
 
static gboolean
360
 
cb_unset_size (gpointer data)
361
 
{
362
 
  GtkWidget *widget = data;
363
 
 
364
 
  gtk_widget_queue_resize_no_redraw (widget);
365
 
 
366
 
  return FALSE;
367
 
}
368
 
 
369
 
static void
370
 
cb_set_preferred_size (GtkWidget *widget, GtkRequisition *req,
371
 
                       gpointer data)
372
 
{
373
 
  TotemPrefSize *size = data;
374
 
 
375
 
  req->width = size->width;
376
 
  req->height = size->height;
377
 
 
378
 
  g_signal_handler_disconnect (widget, size->sig_id);
379
 
  g_free (size);
380
 
  g_idle_add (cb_unset_size, widget);
381
 
}
382
 
 
383
 
void
384
 
totem_widget_set_preferred_size (GtkWidget *widget, gint width,
385
 
                                 gint height)
386
 
{
387
 
  TotemPrefSize *size = g_new (TotemPrefSize, 1);
388
 
 
389
 
  size->width = width;
390
 
  size->height = height;
391
 
  size->sig_id = g_signal_connect (widget, "size-request",
392
 
                                   G_CALLBACK (cb_set_preferred_size),
393
 
                                   size);
394
 
 
395
 
  gtk_widget_queue_resize (widget);
396
 
}
397
 
 
398
 
gboolean
399
 
totem_ratio_fits_screen (GdkWindow *video_window, int video_width,
400
 
                         int video_height, gfloat ratio)
401
 
{
402
 
        GdkRectangle fullscreen_rect;
403
 
        int new_w, new_h;
404
 
 
405
 
        if (video_width <= 0 || video_height <= 0)
406
 
                return TRUE;
407
 
 
408
 
        new_w = video_width * ratio;
409
 
        new_h = video_height * ratio;
410
 
 
411
 
        gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
412
 
                        gdk_screen_get_monitor_at_window
413
 
                        (gdk_screen_get_default (),
414
 
                         video_window),
415
 
                        &fullscreen_rect);
416
 
 
417
 
        if (new_w > (fullscreen_rect.width - 128) ||
418
 
                        new_h > (fullscreen_rect.height - 128))
419
 
        {
420
 
                return FALSE;
421
 
        }
422
 
 
423
 
        return TRUE;
424
 
}