[vlc-commits] android_window: don't clear full subtitle area

Thomas Guillem git at videolan.org
Tue Nov 25 17:10:50 CET 2014


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Nov 25 16:17:24 2014 +0100| [03b99beed17e940f4f70d08a21adb9cbca7eff4f] | committer: Jean-Baptiste Kempf

android_window: don't clear full subtitle area

Do a memset only on previous area.
Subtitle Display is now 15% - 25% faster (depends on window resolution).

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=03b99beed17e940f4f70d08a21adb9cbca7eff4f
---

 modules/video_output/android/android_window.c |  104 ++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 3 deletions(-)

diff --git a/modules/video_output/android/android_window.c b/modules/video_output/android/android_window.c
index 7538bc8..5929344 100644
--- a/modules/video_output/android/android_window.c
+++ b/modules/video_output/android/android_window.c
@@ -105,6 +105,13 @@ struct android_window
     native_window_priv *p_handle_priv;
 };
 
+typedef struct buffer_bounds buffer_bounds;
+struct buffer_bounds
+{
+    uint8_t *p_pixels;
+    ARect bounds;
+};
+
 struct vout_display_sys_t
 {
     picture_pool_t *pool;
@@ -123,6 +130,7 @@ struct vout_display_sys_t
     bool b_sub_invalid;
     filter_t *p_spu_blend;
     picture_t *p_sub_pic;
+    buffer_bounds *p_sub_buffer_bounds;
 
     bool b_has_subpictures;
 
@@ -718,6 +726,7 @@ static void Close(vlc_object_t *p_this)
         picture_Release(sys->p_sub_pic);
     if (sys->p_spu_blend)
         filter_DeleteBlend(sys->p_spu_blend);
+    free(sys->p_sub_buffer_bounds);
     if (sys->p_sub_window)
         AndroidWindow_Destroy(sys, sys->p_sub_window);
 
@@ -815,11 +824,91 @@ error:
     return pool;
 }
 
-static void SubpictureDisplay(vout_display_t *vd, subpicture_t *subpicture)
+static void SubtitleRegionToBounds(subpicture_t *subpicture,
+                                   ARect *p_out_bounds)
+{
+    if (subpicture) {
+        for (subpicture_region_t *r = subpicture->p_region; r != NULL; r = r->p_next) {
+            ARect new_bounds;
+
+            new_bounds.left = r->i_x;
+            new_bounds.top = r->i_y;
+            new_bounds.right = r->fmt.i_width + r->i_x;
+            new_bounds.bottom = r->fmt.i_height + r->i_y;
+            if (r == &subpicture->p_region[0])
+                *p_out_bounds = new_bounds;
+            else {
+                if (p_out_bounds->left > new_bounds.left)
+                    p_out_bounds->left = new_bounds.left;
+                if (p_out_bounds->right < new_bounds.right)
+                    p_out_bounds->right = new_bounds.right;
+                if (p_out_bounds->top > new_bounds.top)
+                    p_out_bounds->top = new_bounds.top;
+                if (p_out_bounds->bottom < new_bounds.bottom)
+                    p_out_bounds->bottom = new_bounds.bottom;
+            }
+        }
+    } else {
+        p_out_bounds->left = p_out_bounds->top = 0;
+        p_out_bounds->right = p_out_bounds->bottom = 0;
+    }
+}
+
+static void SubtitleGetDirtyBounds(vout_display_t *vd,
+                                   subpicture_t *subpicture,
+                                   ARect *p_out_bounds)
 {
     vout_display_sys_t *sys = vd->sys;
+    int i = 0;
+    bool b_found = false;
+
+    /* Try to find last bounds set by current locked buffer.
+     * Indeed, even if we can lock only one buffer at a time, differents
+     * buffers can be locked. This functions will find the last bounds set by
+     * the current buffer. */
+    if (sys->p_sub_buffer_bounds) {
+        for (; sys->p_sub_buffer_bounds[i].p_pixels != NULL; ++i) {
+            buffer_bounds *p_bb = &sys->p_sub_buffer_bounds[i];
+            if (p_bb->p_pixels == sys->p_sub_pic->p[0].p_pixels) {
+                *p_out_bounds = p_bb->bounds;
+                b_found = true;
+                break;
+            }
+        }
+    }
+
+    /* default is full picture */
+    if (!b_found) {
+        p_out_bounds->left = 0;
+        p_out_bounds->top = 0;
+        p_out_bounds->right = sys->p_sub_pic->format.i_width;
+        p_out_bounds->bottom = sys->p_sub_pic->format.i_height;
+    }
+
+    /* buffer not found, add it to the array */
+    if (!sys->p_sub_buffer_bounds
+     || sys->p_sub_buffer_bounds[i].p_pixels == NULL) {
+        buffer_bounds *p_bb = realloc(sys->p_sub_buffer_bounds,
+                                      (i + 2) * sizeof(buffer_bounds)); 
+        if (p_bb) {
+            sys->p_sub_buffer_bounds = p_bb;
+            sys->p_sub_buffer_bounds[i].p_pixels = sys->p_sub_pic->p[0].p_pixels;
+            sys->p_sub_buffer_bounds[i+1].p_pixels = NULL;
+        }
+    }
 
+    /* set buffer bounds */
+    if (sys->p_sub_buffer_bounds
+     && sys->p_sub_buffer_bounds[i].p_pixels != NULL)
+        SubtitleRegionToBounds(subpicture, &sys->p_sub_buffer_bounds[i].bounds);
+}
+
+static void SubpictureDisplay(vout_display_t *vd, subpicture_t *subpicture)
+{
+    vout_display_sys_t *sys = vd->sys;
     struct md5_s hash;
+    ARect memset_bounds;
+
     InitMD5(&hash);
     if (subpicture) {
         for (subpicture_region_t *r = subpicture->p_region; r != NULL; r = r->p_next) {
@@ -844,9 +933,16 @@ static void SubpictureDisplay(vout_display_t *vd, subpicture_t *subpicture)
     if (AndroidWindow_LockPicture(sys, sys->p_sub_window, sys->p_sub_pic) != 0)
         return;
 
+
     /* Clear the subtitles surface. */
-    memset(sys->p_sub_pic->p[0].p_pixels, 0,
-           sys->p_sub_pic->p[0].i_pitch * sys->p_sub_pic->p[0].i_lines);
+    SubtitleGetDirtyBounds(vd, subpicture, &memset_bounds);
+    const int x_pixels_offset = memset_bounds.left
+                                * sys->p_sub_pic->p[0].i_pixel_pitch;
+    const int i_line_size = (memset_bounds.right - memset_bounds.left)
+                            * sys->p_sub_pic->p->i_pixel_pitch;
+    for (int y = memset_bounds.top; y < memset_bounds.bottom; y++)
+        memset(&sys->p_sub_pic->p[0].p_pixels[y * sys->p_sub_pic->p[0].i_pitch
+                                              + x_pixels_offset], 0, i_line_size);
 
     if (subpicture)
         picture_BlendSubpicture(sys->p_sub_pic, sys->p_spu_blend, subpicture);
@@ -891,6 +987,8 @@ static void Display(vout_display_t *vd, picture_t *picture,
                 filter_DeleteBlend(sys->p_spu_blend);
                 sys->p_spu_blend = NULL;
             }
+            free(sys->p_sub_buffer_bounds);
+            sys->p_sub_buffer_bounds = NULL;
         }
 
         if (!sys->p_sub_pic && SetupWindowSubtitleSurface(sys) == 0)



More information about the vlc-commits mailing list