| /* GStreamer DVD Sub-Picture Unit |
| * Copyright (C) 2007 Fluendo S.A. <info@fluendo.com> |
| * Copyright (C) 2009 Jan Schmidt <thaytan@noraisin.net> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| #ifdef HAVE_CONFIG_H |
| # include <config.h> |
| #endif |
| |
| #include <string.h> |
| |
| #include <gst/gst.h> |
| |
| #include "gstdvdspu.h" |
| |
| GST_DEBUG_CATEGORY_EXTERN (dvdspu_debug); |
| #define GST_CAT_DEFAULT dvdspu_debug |
| |
| void |
| gstspu_clear_comp_buffers (SpuState * state) |
| { |
| /* The area to clear is the line inside the disp_rect, each entry 4 bytes, |
| * of the sub-sampled UV planes. */ |
| gint16 left = state->comp_left / 2; |
| gint16 right = state->comp_right / 2; |
| gint16 uv_width = sizeof (guint32) * (right - left + 1); |
| |
| memset (state->comp_bufs[0] + left, 0, uv_width); |
| memset (state->comp_bufs[1] + left, 0, uv_width); |
| memset (state->comp_bufs[2] + left, 0, uv_width); |
| } |
| |
| void |
| gstspu_blend_comp_buffers (SpuState * state, guint8 * planes[3]) |
| { |
| gint16 uv_end; |
| gint16 left, x; |
| guint8 *out_U; |
| guint8 *out_V; |
| guint32 *in_U; |
| guint32 *in_V; |
| guint32 *in_A; |
| gint16 comp_last_x = state->comp_right; |
| |
| if (comp_last_x < state->comp_left) |
| return; /* Didn't draw in the comp buffers, nothing to do... */ |
| |
| #if 0 |
| GST_LOG ("Blending comp buffers from x=%d to x=%d", |
| state->comp_left, state->comp_right); |
| #endif |
| |
| /* Set up the output pointers */ |
| out_U = planes[1]; /* U plane */ |
| out_V = planes[2]; /* V plane */ |
| |
| /* Input starts at the first pixel of the compositing buffer */ |
| in_U = state->comp_bufs[0]; /* U comp buffer */ |
| in_V = state->comp_bufs[1]; /* V comp buffer */ |
| in_A = state->comp_bufs[2]; /* A comp buffer */ |
| |
| /* Calculate how many pixels to blend based on the maximum X value that was |
| * drawn in the render_line function, divided by 2 (rounding up) to account |
| * for UV sub-sampling */ |
| uv_end = (comp_last_x + 1) / 2; |
| left = state->comp_left / 2; |
| |
| out_U += left * GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 1); |
| out_V += left * GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 2); |
| for (x = left; x < uv_end; x++) { |
| guint32 tmp; |
| /* Each entry in the compositing buffer is 4 summed pixels, so the |
| * inverse alpha is (4 * 0xff) - in_A[x] */ |
| guint16 inv_A = (4 * 0xff) - in_A[x]; |
| |
| tmp = in_U[x] + inv_A * *out_U; |
| *out_U = (guint8) (tmp / (4 * 0xff)); |
| |
| tmp = in_V[x] + inv_A * *out_V; |
| *out_V = (guint8) (tmp / (4 * 0xff)); |
| |
| out_U += GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 1); |
| out_V += GST_VIDEO_INFO_COMP_PSTRIDE (&state->info, 2); |
| } |
| } |