1 /* GStreamer DVD Sub-Picture Unit
2 * Copyright (C) 2007 Fluendo S.A. <info@fluendo.com>
3 * Copyright (C) 2009 Jan Schmidt <thaytan@noraisin.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <string.h>
25
26 #include <gst/gst.h>
27
28 #include "gstdvdspu.h"
29
30 GST_DEBUG_CATEGORY_EXTERN (dvdspu_debug);
31 #define GST_CAT_DEFAULT dvdspu_debug
32
33 void
gstspu_clear_comp_buffers(SpuState * state)34 gstspu_clear_comp_buffers (SpuState * state)
35 {
36 /* The area to clear is the line inside the disp_rect, each entry 4 bytes,
37 * of the sub-sampled UV planes. */
38 gint16 left = state->comp_left / 2;
39 gint16 right = state->comp_right / 2;
40 gint16 uv_width = sizeof (guint32) * (right - left + 1);
41
42 memset (state->comp_bufs[0] + left, 0, uv_width);
43 memset (state->comp_bufs[1] + left, 0, uv_width);
44 memset (state->comp_bufs[2] + left, 0, uv_width);
45 }
46
47 void
gstspu_blend_comp_buffers(SpuState * state,guint8 * planes[3])48 gstspu_blend_comp_buffers (SpuState * state, guint8 * planes[3])
49 {
50 gint16 uv_end;
51 gint16 left, x;
52 guint8 *out_U;
53 guint8 *out_V;
54 guint32 *in_U;
55 guint32 *in_V;
56 guint32 *in_A;
57 gint16 comp_last_x = state->comp_right;
58
59 if (comp_last_x < state->comp_left)
60 return; /* Didn't draw in the comp buffers, nothing to do... */
61
62 #if 0
63 GST_LOG ("Blending comp buffers from x=%d to x=%d",
64 state->comp_left, state->comp_right);
65 #endif
66
67 /* Set up the output pointers */
68 out_U = planes[1]; /* U plane */
69 out_V = planes[2]; /* V plane */
70
71 /* Input starts at the first pixel of the compositing buffer */
72 in_U = state->comp_bufs[0]; /* U comp buffer */
73 in_V = state->comp_bufs[1]; /* V comp buffer */
74 in_A = state->comp_bufs[2]; /* A comp buffer */
75
76 /* Calculate how many pixels to blend based on the maximum X value that was
77 * drawn in the render_line function, divided by 2 (rounding up) to account
78 * for UV sub-sampling */
79 uv_end = (comp_last_x + 1) / 2;
80 left = state->comp_left / 2;
81
82 out_U += left * GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 1);
83 out_V += left * GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 2);
84 for (x = left; x < uv_end; x++) {
85 guint32 tmp;
86 /* Each entry in the compositing buffer is 4 summed pixels, so the
87 * inverse alpha is (4 * 0xff) - in_A[x] */
88 guint16 inv_A = (4 * 0xff) - in_A[x];
89
90 tmp = in_U[x] + inv_A * *out_U;
91 *out_U = (guint8) (tmp / (4 * 0xff));
92
93 tmp = in_V[x] + inv_A * *out_V;
94 *out_V = (guint8) (tmp / (4 * 0xff));
95
96 out_U += GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 1);
97 out_V += GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 2);
98 }
99 }
100