From patchwork Tue Jan 3 22:02:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 6041 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 78AC023F7F for ; Tue, 3 Jan 2012 22:03:11 +0000 (UTC) Received: from mail-ey0-f180.google.com (mail-ey0-f180.google.com [209.85.215.180]) by fiordland.canonical.com (Postfix) with ESMTP id 67647A18096 for ; Tue, 3 Jan 2012 22:03:11 +0000 (UTC) Received: by mail-ey0-f180.google.com with SMTP id c11so16120253eaa.11 for ; Tue, 03 Jan 2012 14:03:11 -0800 (PST) Received: by 10.205.138.136 with SMTP id is8mr12081461bkc.35.1325628189962; Tue, 03 Jan 2012 14:03:09 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.205.82.144 with SMTP id ac16cs352495bkc; Tue, 3 Jan 2012 14:03:09 -0800 (PST) Received: by 10.236.129.173 with SMTP id h33mr69098991yhi.14.1325628187801; Tue, 03 Jan 2012 14:03:07 -0800 (PST) Received: from mail-gx0-f178.google.com (mail-gx0-f178.google.com [209.85.161.178]) by mx.google.com with ESMTPS id c14si22546441anh.105.2012.01.03.14.03.07 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 03 Jan 2012 14:03:07 -0800 (PST) Received-SPF: pass (google.com: domain of robdclark@gmail.com designates 209.85.161.178 as permitted sender) client-ip=209.85.161.178; Authentication-Results: mx.google.com; spf=pass (google.com: domain of robdclark@gmail.com designates 209.85.161.178 as permitted sender) smtp.mail=robdclark@gmail.com; dkim=pass (test mode) header.i=@gmail.com Received: by mail-gx0-f178.google.com with SMTP id q4so11570394ggn.37 for ; Tue, 03 Jan 2012 14:03:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=bajwueOvqnxWZ8ATJtqjOY5EqieMicYVMkfFdq9Pszc=; b=QcDTZdhLu/3oEYyHMzATU2/hiqIGdh35SP+eA+6XPy2a/4CFiEoyOtw6Vw+uKSiAI0 WoVFmegjTBtoaeg2Pxsb4OWbLNozj0fokSPnDX8QIiHvSumPpD1orhyIopkeIkV6VJvQ XyyLBBatxHnyoZISpgwaSh/zim/UzCZzoq5U0= Received: by 10.101.119.4 with SMTP id w4mr20269808anm.39.1325628187357; Tue, 03 Jan 2012 14:03:07 -0800 (PST) Received: from localhost (dragon.ti.com. [192.94.94.33]) by mx.google.com with ESMTPS id o7sm76571064yhl.15.2012.01.03.14.03.06 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 03 Jan 2012 14:03:06 -0800 (PST) Sender: Rob Clark From: Rob Clark To: patches@linaro.org Cc: Rob Clark Subject: [PATCH 15/19] dvdspu: add interlaced support Date: Tue, 3 Jan 2012 16:02:51 -0600 Message-Id: <1325628171-4803-8-git-send-email-rob@ti.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1325628171-4803-1-git-send-email-rob@ti.com> References: <1325628171-4803-1-git-send-email-rob@ti.com> --- See: https://bugzilla.gnome.org/show_bug.cgi?id=667224 gst/dvdspu/gstdvdspu.c | 5 + gst/dvdspu/gstdvdspu.h | 1 + gst/dvdspu/gstspu-vobsub-render.c | 185 ++++++++++++++++++++++--------------- 3 files changed, 116 insertions(+), 75 deletions(-) diff --git a/gst/dvdspu/gstdvdspu.c b/gst/dvdspu/gstdvdspu.c index fa68b24..4b20983 100644 --- a/gst/dvdspu/gstdvdspu.c +++ b/gst/dvdspu/gstdvdspu.c @@ -321,6 +321,7 @@ gst_dvd_spu_video_set_caps (GstPad * pad, GstCaps * caps) gint i; gint fps_n, fps_d; guint32 format; + gboolean interlaced = FALSE; SpuState *state; s = gst_caps_get_structure (caps, 0); @@ -332,12 +333,16 @@ gst_dvd_spu_video_set_caps (GstPad * pad, GstCaps * caps) goto done; } + /* interlaced field is optional: */ + gst_structure_get_boolean (s, "interlaced", &interlaced); + DVD_SPU_LOCK (dvdspu); state = &dvdspu->spu_state; state->fps_n = fps_n; state->fps_d = fps_d; + state->interlaced = interlaced; state->vid_height = h; state->Y_height = GST_ROUND_UP_2 (h); diff --git a/gst/dvdspu/gstdvdspu.h b/gst/dvdspu/gstdvdspu.h index d78f60f..9a2f4d8 100644 --- a/gst/dvdspu/gstdvdspu.h +++ b/gst/dvdspu/gstdvdspu.h @@ -75,6 +75,7 @@ struct SpuState { gint16 Y_height, UV_height; gint32 U_offset, V_offset; gint8 UV_pixstride; + gboolean interlaced; guint32 *comp_bufs[3]; /* Compositing buffers for U+V & A */ guint16 comp_left; diff --git a/gst/dvdspu/gstspu-vobsub-render.c b/gst/dvdspu/gstspu-vobsub-render.c index 83943e9..ad8d96b 100644 --- a/gst/dvdspu/gstspu-vobsub-render.c +++ b/gst/dvdspu/gstspu-vobsub-render.c @@ -392,6 +392,21 @@ gstspu_vobsub_clear_comp_buffers (SpuState * state) state->vobsub.comp_last_x[1] = -1; } +static inline gint +ilaced_y (SpuState * state, gint y) +{ + if (state->interlaced) { + if (y % 2) { + /* odd field */ + y = (y + state->Y_height) / 2; + } else { + /* even field */ + y = y / 2; + } + } + return y; +} + static void gstspu_vobsub_draw_highlight (SpuState * state, GstBuffer * buf, SpuRect *rect) @@ -399,36 +414,113 @@ gstspu_vobsub_draw_highlight (SpuState * state, guint8 *cur; gint16 pos; - cur = GST_BUFFER_DATA (buf) + state->Y_stride * rect->top; + cur = GST_BUFFER_DATA (buf) + state->Y_stride * + ilaced_y (state, rect->top); for (pos = rect->left + 1; pos < rect->right; pos++) cur[pos] = (cur[pos] / 2) + 0x8; - cur = GST_BUFFER_DATA (buf) + state->Y_stride * rect->bottom; + cur = GST_BUFFER_DATA (buf) + state->Y_stride * + ilaced_y (state, rect->bottom); for (pos = rect->left + 1; pos < rect->right; pos++) cur[pos] = (cur[pos] / 2) + 0x8; - cur = GST_BUFFER_DATA (buf) + state->Y_stride * rect->top; for (pos = rect->top; pos <= rect->bottom; pos++) { + cur = GST_BUFFER_DATA (buf) + state->Y_stride * + ilaced_y (state, pos); cur[rect->left] = (cur[rect->left] / 2) + 0x8; cur[rect->right] = (cur[rect->right] / 2) + 0x8; - cur += state->Y_stride; } } +static void +gstspu_vobsub_render_field (SpuState * state, GstBuffer * buf, + gint y, gint last_y, gint y_inc, + guint16 * rle_offset_even, guint16 * rle_offset_odd) +{ + guint8 *planes[3]; /* YUV frame pointers */ + + /* Store the start of each plane */ + planes[0] = GST_BUFFER_DATA (buf); + planes[1] = planes[0] + state->U_offset; + planes[2] = planes[1] + state->V_offset; + + /* Update our plane references to the first line of the disp_rect */ + planes[0] += state->Y_stride * y; + planes[1] += state->UV_stride * (y / 2); + planes[2] += state->UV_stride * (y / 2); + + /* Set up HL or Change Color & Contrast rect tracking */ + if (state->vobsub.hl_rect.top != -1) { + state->vobsub.cur_chg_col = &state->vobsub.hl_ctrl_i; + state->vobsub.cur_chg_col_end = state->vobsub.cur_chg_col + 1; + } else if (state->vobsub.n_line_ctrl_i > 0) { + state->vobsub.cur_chg_col = state->vobsub.line_ctrl_i; + state->vobsub.cur_chg_col_end = + state->vobsub.cur_chg_col + state->vobsub.n_line_ctrl_i; + } else + state->vobsub.cur_chg_col = NULL; + + for (state->vobsub.cur_Y = y; state->vobsub.cur_Y <= last_y; + state->vobsub.cur_Y += y_inc) { + gboolean clip, visible = FALSE; + + clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top + || state->vobsub.cur_Y > state->vobsub.clip_rect.bottom); + + /* Reset the compositing buffer */ + gstspu_vobsub_clear_comp_buffers (state); + /* Render even line */ + state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x; + visible |= gstspu_vobsub_render_line (state, planes, rle_offset_even); + + /* Advance the luminance output pointer */ + planes[0] += state->Y_stride; + + state->vobsub.cur_Y += y_inc; + + /* Render odd line */ + state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x + 1; + visible |= gstspu_vobsub_render_line (state, planes, rle_offset_odd); + + if (visible && !clip) { + /* Blend the accumulated UV compositing buffers onto the output */ + gstspu_vobsub_blend_comp_buffers (state, planes); + } + + /* Update all the output pointers */ + planes[0] += state->Y_stride; + planes[1] += state->UV_stride; + planes[2] += state->UV_stride; + } + if (state->vobsub.cur_Y == state->vobsub.disp_rect.bottom) { + gboolean clip, visible = FALSE; + + clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top + || state->vobsub.cur_Y > state->vobsub.clip_rect.bottom); + + g_assert ((state->vobsub.disp_rect.bottom & 0x01) == 0); + + if (!clip) { + /* Render a remaining lone last even line. y already has the correct value + * after the above loop exited. */ + gstspu_vobsub_clear_comp_buffers (state); + state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x; + visible |= gstspu_vobsub_render_line (state, planes, rle_offset_even); + if (visible) + gstspu_vobsub_blend_comp_buffers (state, planes); + } + } + +} + void gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) { SpuState *state = &dvdspu->spu_state; - guint8 *planes[3]; /* YUV frame pointers */ gint y, last_y; /* Set up our initial state */ if (G_UNLIKELY (state->vobsub.pix_buf == NULL)) return; - /* Store the start of each plane */ - planes[0] = GST_BUFFER_DATA (buf); - planes[1] = planes[0] + state->U_offset; - planes[2] = planes[1] + state->V_offset; - GST_DEBUG_OBJECT (dvdspu, "Rendering SPU. disp_rect %d,%d to %d,%d. hl_rect %d,%d to %d,%d", state->vobsub.disp_rect.left, state->vobsub.disp_rect.top, @@ -447,17 +539,6 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) /* Update all the palette caches */ gstspu_vobsub_update_palettes (dvdspu, state); - /* Set up HL or Change Color & Contrast rect tracking */ - if (state->vobsub.hl_rect.top != -1) { - state->vobsub.cur_chg_col = &state->vobsub.hl_ctrl_i; - state->vobsub.cur_chg_col_end = state->vobsub.cur_chg_col + 1; - } else if (state->vobsub.n_line_ctrl_i > 0) { - state->vobsub.cur_chg_col = state->vobsub.line_ctrl_i; - state->vobsub.cur_chg_col_end = - state->vobsub.cur_chg_col + state->vobsub.n_line_ctrl_i; - } else - state->vobsub.cur_chg_col = NULL; - state->vobsub.clip_rect.left = state->vobsub.disp_rect.left; state->vobsub.clip_rect.right = state->vobsub.disp_rect.right; @@ -533,60 +614,14 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) * single line at the end if the display rect ends on an even line too. */ last_y = (state->vobsub.disp_rect.bottom - 1) & ~(0x01); - /* Update our plane references to the first line of the disp_rect */ - planes[0] += state->Y_stride * y; - planes[1] += state->UV_stride * (y / 2); - planes[2] += state->UV_stride * (y / 2); - - for (state->vobsub.cur_Y = y; state->vobsub.cur_Y <= last_y; - state->vobsub.cur_Y++) { - gboolean clip, visible = FALSE; - - clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top - || state->vobsub.cur_Y > state->vobsub.clip_rect.bottom); - - /* Reset the compositing buffer */ - gstspu_vobsub_clear_comp_buffers (state); - /* Render even line */ - state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x; - visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]); - if (!clip) { - /* Advance the luminance output pointer */ - planes[0] += state->Y_stride; - } - state->vobsub.cur_Y++; - - /* Render odd line */ - state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x + 1; - visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[1]); - - if (visible && !clip) { - /* Blend the accumulated UV compositing buffers onto the output */ - gstspu_vobsub_blend_comp_buffers (state, planes); - - /* Update all the output pointers */ - planes[0] += state->Y_stride; - planes[1] += state->UV_stride; - planes[2] += state->UV_stride; - } - } - if (state->vobsub.cur_Y == state->vobsub.disp_rect.bottom) { - gboolean clip, visible = FALSE; - - clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top - || state->vobsub.cur_Y > state->vobsub.clip_rect.bottom); - - g_assert ((state->vobsub.disp_rect.bottom & 0x01) == 0); - - if (!clip) { - /* Render a remaining lone last even line. y already has the correct value - * after the above loop exited. */ - gstspu_vobsub_clear_comp_buffers (state); - state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x; - visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]); - if (visible) - gstspu_vobsub_blend_comp_buffers (state, planes); - } + if (state->interlaced) { + gstspu_vobsub_render_field (state, buf, y, last_y, 2, + &state->vobsub.cur_offsets[0], &state->vobsub.cur_offsets[0]); + gstspu_vobsub_render_field (state, buf, y+1, last_y, 2, + &state->vobsub.cur_offsets[1], &state->vobsub.cur_offsets[1]); + } else { + gstspu_vobsub_render_field (state, buf, y, last_y, 1, + &state->vobsub.cur_offsets[0], &state->vobsub.cur_offsets[1]); } /* for debugging purposes, draw a faint rectangle at the edges of the disp_rect */