[06/19] dvdspu: some optimizations

Message ID 1325628171-4803-5-git-send-email-rob@ti.com
State New
Headers show

Commit Message

Rob Clark Jan. 3, 2012, 10:02 p.m.
Detect invisible pixels, and skip gstspu_vobsub_blend_comp_buffers()
when there are only invisible pixels.  This significantly reduces the
CPU load in cases of DVDs which don't use the clip_rect to exclude
processing for parts of the screen where the video is visible.
---
See: https://bugzilla.gnome.org/show_bug.cgi?id=667221

 gst/dvdspu/gstspu-common.h        |    1 +
 gst/dvdspu/gstspu-pgs.c           |    4 ++-
 gst/dvdspu/gstspu-vobsub-render.c |   42 ++++++++++++++++++++++--------------
 3 files changed, 30 insertions(+), 17 deletions(-)

Patch

diff --git a/gst/dvdspu/gstspu-common.h b/gst/dvdspu/gstspu-common.h
index 206e882..494dab0 100644
--- a/gst/dvdspu/gstspu-common.h
+++ b/gst/dvdspu/gstspu-common.h
@@ -45,6 +45,7 @@  struct SpuColour {
   guint16 U;
   guint16 V;
   guint8 A;
+  guint8 vis;   /* is this color visible? */
 };
 
 void gstspu_clear_comp_buffers (SpuState * state);
diff --git a/gst/dvdspu/gstspu-pgs.c b/gst/dvdspu/gstspu-pgs.c
index abfa539..ce6156d 100644
--- a/gst/dvdspu/gstspu-pgs.c
+++ b/gst/dvdspu/gstspu-pgs.c
@@ -258,7 +258,7 @@  pgs_composition_object_render (PgsCompositionObject * obj, SpuState * state,
     }
 
     colour = &state->pgs.palette[pal_id];
-    if (colour->A) {
+    if (colour->A && colour->vis) {
       guint32 inv_A = 0xff - colour->A;
       if (G_UNLIKELY (x + run_len > max_x))
         run_len = (max_x - x);
@@ -492,6 +492,8 @@  parse_set_palette (GstDVDSpu * dvdspu, guint8 type, guint8 * payload,
     state->pgs.palette[n].U = U * A;
     state->pgs.palette[n].V = V * A;
     state->pgs.palette[n].A = A;
+    state->pgs.palette[n].vis = state->pgs.palette[n].Y ||
+        state->pgs.palette[n].U || state->pgs.palette[n].V;
 
     payload += PGS_PALETTE_ENTRY_SIZE;
   }
diff --git a/gst/dvdspu/gstspu-vobsub-render.c b/gst/dvdspu/gstspu-vobsub-render.c
index b945592..66abd9f 100644
--- a/gst/dvdspu/gstspu-vobsub-render.c
+++ b/gst/dvdspu/gstspu-vobsub-render.c
@@ -47,6 +47,7 @@  gstspu_vobsub_recalc_palette (GstDVDSpu * dvdspu,
       /* U/V are stored as V/U in the clut words, so switch them */
       dest->V = ((guint16) ((col >> 8) & 0xff)) * dest->A;
       dest->U = ((guint16) (col & 0xff)) * dest->A;
+      dest->vis = dest->Y || dest->V || dest->U;
     }
   } else {
     int y = 240;
@@ -168,7 +169,7 @@  gstspu_vobsub_get_rle_code (SpuState * state, guint16 * rle_offset)
   return code;
 }
 
-static inline void
+static inline gboolean
 gstspu_vobsub_draw_rle_run (SpuState * state, gint16 x, gint16 end,
     SpuColour * colour)
 {
@@ -177,7 +178,7 @@  gstspu_vobsub_draw_rle_run (SpuState * state, gint16 x, gint16 end,
       state->vobsub.cur_Y, x, end, colour->Y, colour->U, colour->V, colour->A);
 #endif
 
-  if (colour->A != 0) {
+  if ((colour->A != 0) && colour->vis) {
     guint32 inv_A = 0xff - colour->A;
 
     /* FIXME: This could be more efficient */
@@ -191,7 +192,10 @@  gstspu_vobsub_draw_rle_run (SpuState * state, gint16 x, gint16 end,
     }
     /* Update the compositing buffer so we know how much to blend later */
     *(state->vobsub.comp_last_x_ptr) = end - 1; /* end is the start of the *next* run */
+
+    return TRUE;
   }
+  return FALSE;
 }
 
 static inline gint16
@@ -204,16 +208,17 @@  rle_end_x (guint16 rle_code, gint16 x, gint16 end)
     return MIN (end, x + (rle_code >> 2));
 }
 
-static void gstspu_vobsub_render_line_with_chgcol (SpuState * state,
+static gboolean gstspu_vobsub_render_line_with_chgcol (SpuState * state,
     guint8 * planes[3], guint16 * rle_offset);
 static gboolean gstspu_vobsub_update_chgcol (SpuState * state);
 
-static void
+static gboolean
 gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3],
     guint16 * rle_offset)
 {
   gint16 x, next_x, end, rle_code, next_draw_x;
   SpuColour *colour;
+  gboolean visible = FALSE;
 
   /* Check for special case of chg_col info to use (either highlight or
    * ChgCol command */
@@ -222,8 +227,7 @@  gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3],
       /* Check the top & bottom, because we might not be within the region yet */
       if (state->vobsub.cur_Y >= state->vobsub.cur_chg_col->top &&
           state->vobsub.cur_Y <= state->vobsub.cur_chg_col->bottom) {
-        gstspu_vobsub_render_line_with_chgcol (state, planes, rle_offset);
-        return;
+        return gstspu_vobsub_render_line_with_chgcol (state, planes, rle_offset);
       }
     }
   }
@@ -248,9 +252,11 @@  gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3],
     if (next_draw_x > state->vobsub.clip_rect.right)
       next_draw_x = state->vobsub.clip_rect.right;      /* ensure no overflow */
     /* Now draw the run between [x,next_x) */
-    gstspu_vobsub_draw_rle_run (state, x, next_draw_x, colour);
+    visible |= gstspu_vobsub_draw_rle_run (state, x, next_draw_x, colour);
     x = next_x;
   }
+
+  return visible;
 }
 
 static gboolean
@@ -280,7 +286,7 @@  gstspu_vobsub_update_chgcol (SpuState * state)
   return FALSE;
 }
 
-static void
+static gboolean
 gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
     guint16 * rle_offset)
 {
@@ -292,6 +298,7 @@  gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
   SpuVobsubPixCtrlI *next_pix_ctrl;
   SpuVobsubPixCtrlI *end_pix_ctrl;
   SpuVobsubPixCtrlI dummy_pix_ctrl;
+  gboolean visible = FALSE;
   gint16 cur_reg_end;
   gint i;
 
@@ -340,7 +347,7 @@  gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
 
       if (G_LIKELY (x < run_end)) {
         colour = &cur_pix_ctrl->pal_cache[rle_code & 3];
-        gstspu_vobsub_draw_rle_run (state, x, run_draw_end, colour);
+        visible |= gstspu_vobsub_draw_rle_run (state, x, run_draw_end, colour);
         x = run_end;
       }
 
@@ -356,6 +363,8 @@  gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
       }
     }
   }
+
+  return visible;
 }
 
 static void
@@ -510,7 +519,7 @@  gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
 
   for (state->vobsub.cur_Y = y; state->vobsub.cur_Y <= last_y;
       state->vobsub.cur_Y++) {
-    gboolean clip;
+    gboolean clip, visible = FALSE;
 
     clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top
         || state->vobsub.cur_Y > state->vobsub.clip_rect.bottom);
@@ -519,7 +528,7 @@  gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
     gstspu_vobsub_clear_comp_buffers (state);
     /* Render even line */
     state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x;
-    gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
+    visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
     if (!clip) {
       /* Advance the luminance output pointer */
       planes[0] += state->Y_stride;
@@ -528,9 +537,9 @@  gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
 
     /* Render odd line */
     state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x + 1;
-    gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[1]);
+    visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[1]);
 
-    if (!clip) {
+    if (visible && !clip) {
       /* Blend the accumulated UV compositing buffers onto the output */
       gstspu_vobsub_blend_comp_buffers (state, planes);
 
@@ -541,7 +550,7 @@  gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
     }
   }
   if (state->vobsub.cur_Y == state->vobsub.disp_rect.bottom) {
-    gboolean clip;
+    gboolean clip, visible = FALSE;
 
     clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top
         || state->vobsub.cur_Y > state->vobsub.clip_rect.bottom);
@@ -553,8 +562,9 @@  gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
        * after the above loop exited. */
       gstspu_vobsub_clear_comp_buffers (state);
       state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x;
-      gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
-      gstspu_vobsub_blend_comp_buffers (state, planes);
+      visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
+      if (visible)
+        gstspu_vobsub_blend_comp_buffers (state, planes);
     }
   }