[libbluray-devel] rle: check for encoding errors

hpi1 git at videolan.org
Sun Aug 7 19:01:48 CEST 2016


libbluray | branch: master | hpi1 <hpi1 at anonymous.org> | Sun Aug  7 17:30:29 2016 +0300| [0a5b36f3c434b1760087fe68bd2f5d8a61484e02] | committer: hpi1

rle: check for encoding errors

> http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=0a5b36f3c434b1760087fe68bd2f5d8a61484e02
---

 src/libbluray/decoders/graphics_controller.c | 41 ++++++++++-----
 src/libbluray/decoders/rle.c                 | 75 ++++++++++++++++++++--------
 src/libbluray/decoders/rle.h                 | 22 ++++++--
 3 files changed, 99 insertions(+), 39 deletions(-)

diff --git a/src/libbluray/decoders/graphics_controller.c b/src/libbluray/decoders/graphics_controller.c
index c801f80..f4fc5bf 100644
--- a/src/libbluray/decoders/graphics_controller.c
+++ b/src/libbluray/decoders/graphics_controller.c
@@ -628,8 +628,13 @@ static void _render_composition_object(GRAPHICS_CONTROLLER *gc,
 
         if (cobj->crop_flag) {
             if (cobj->crop_x || cobj->crop_y || cobj->crop_w != object->width) {
-                ov.img = cropped_img = rle_crop_object(object->img, object->width,
-                                                       cobj->crop_x, cobj->crop_y, cobj->crop_w, cobj->crop_h);
+                cropped_img = rle_crop_object(object->img, object->width,
+                                              cobj->crop_x, cobj->crop_y, cobj->crop_w, cobj->crop_h);
+                if (!cropped_img) {
+                    BD_DEBUG(DBG_DECODE | DBG_CRIT, "Error cropping PG object\n");
+                    return;
+                }
+                ov.img = cropped_img;
             }
             ov.w  = cobj->crop_w;
             ov.h  = cobj->crop_h;
@@ -971,28 +976,38 @@ static int _render_textst_region(GRAPHICS_CONTROLLER *p, int64_t pts, BD_TEXTST_
     uint16_t y;
     RLE_ENC  rle;
 
-    if (!rle_begin(&rle)) {
+    if (rle_begin(&rle) < 0) {
         return -1;
     }
 
     for (y = 0, bmp_y = 0; y < style->region_info.region.height; y++) {
         if (y < style->text_box.ypos || y >= style->text_box.ypos + style->text_box.height) {
-            rle_add_bite(&rle, style->region_info.background_color, style->region_info.region.width);
+            if (rle_add_bite(&rle, style->region_info.background_color, style->region_info.region.width) < 0)
+                break;
         } else {
-            rle_add_bite(&rle, style->region_info.background_color, style->text_box.xpos);
-            rle_compress_chunk(&rle, bmp->mem + bmp->stride * bmp_y, bmp->width);
+            if (rle_add_bite(&rle, style->region_info.background_color, style->text_box.xpos) < 0)
+                break;
+            if (rle_compress_chunk(&rle, bmp->mem + bmp->stride * bmp_y, bmp->width) < 0)
+                break;
             bmp_y++;
-            rle_add_bite(&rle, style->region_info.background_color,
-                         style->region_info.region.width - style->text_box.width - style->text_box.xpos);
+            if (rle_add_bite(&rle, style->region_info.background_color,
+                             style->region_info.region.width - style->text_box.width - style->text_box.xpos) < 0)
+                break;
         }
 
-        rle_add_eol(&rle);
+        if (rle_add_eol(&rle) < 0)
+            break;
     }
 
-    _render_rle(p, pts, rle_get(&rle),
-                style->region_info.region.xpos, style->region_info.region.ypos,
-                style->region_info.region.width, style->region_info.region.height,
-                palette);
+    BD_PG_RLE_ELEM *img = rle_get(&rle);
+    if (img) {
+        _render_rle(p, pts, img,
+                    style->region_info.region.xpos, style->region_info.region.ypos,
+                    style->region_info.region.width, style->region_info.region.height,
+                    palette);
+    } else {
+        BD_DEBUG(DBG_DECODE | DBG_CRIT, "Error encoding Text Subtitle region\n");
+    }
 
     rle_end(&rle);
 
diff --git a/src/libbluray/decoders/rle.c b/src/libbluray/decoders/rle.c
index 4420542..1439565 100644
--- a/src/libbluray/decoders/rle.c
+++ b/src/libbluray/decoders/rle.c
@@ -29,47 +29,58 @@
  * util
  */
 
-static void _rle_ensure_size(RLE_ENC *p)
+static int _rle_ensure_size(RLE_ENC *p)
 {
     if (BD_UNLIKELY(!p->free_elem)) {
         BD_PG_RLE_ELEM *start = rle_get(p);
         /* realloc to 2x */
-        p->free_elem = p->num_elem;
-        start = refcnt_realloc(start, p->num_elem * 2 * sizeof(BD_PG_RLE_ELEM));
+        void *tmp = refcnt_realloc(start, p->num_elem * 2 * sizeof(BD_PG_RLE_ELEM));
+        if (!tmp) {
+            p->error = 1;
+            return -1;
+        }
+        start = tmp;
         p->elem = start + p->num_elem;
+        p->free_elem = p->num_elem;
         p->num_elem *= 2;
     }
+
+    return 0;
 }
 
 /*
- * encoding
+ * crop encoded image
  */
 
-static void _enc_elem(RLE_ENC *p, uint16_t color, uint16_t len)
+static int _enc_elem(RLE_ENC *p, uint16_t color, uint16_t len)
 {
-    _rle_ensure_size(p);
+    if (BD_UNLIKELY(_rle_ensure_size(p) < 0)) {
+        return -1;
+    }
 
     p->elem->color = color;
     p->elem->len = len;
 
     p->free_elem--;
     p->elem++;
+
+    return 0;
 }
 
-static void _enc_eol(RLE_ENC *p)
+static int _enc_eol(RLE_ENC *p)
 {
-    _enc_elem(p, 0, 0);
+    return _enc_elem(p, 0, 0);
 }
 
 BD_PG_RLE_ELEM *rle_crop_object(const BD_PG_RLE_ELEM *orig, int width,
-                                       int crop_x, int crop_y, int crop_w, int crop_h)
+                                int crop_x, int crop_y, int crop_w, int crop_h)
 {
     RLE_ENC  rle;
     int      x0 = crop_x;
     int      x1 = crop_x + crop_w; /* first pixel outside of cropped region */
     int      x, y;
 
-    if (!rle_begin(&rle)) {
+    if (rle_begin(&rle) < 0) {
         return NULL;
     }
 
@@ -108,7 +119,9 @@ BD_PG_RLE_ELEM *rle_crop_object(const BD_PG_RLE_ELEM *orig, int width,
                 bite.len -= x - x1;
             }
 
-            _enc_elem(&rle, bite.color, bite.len);
+            if (BD_UNLIKELY(_enc_elem(&rle, bite.color, bite.len) < 0)) {
+                goto out;
+            }
         }
 
         if (BD_LIKELY(!orig->len)) {
@@ -118,9 +131,12 @@ BD_PG_RLE_ELEM *rle_crop_object(const BD_PG_RLE_ELEM *orig, int width,
             BD_DEBUG(DBG_GC | DBG_CRIT, "rle eol marker missing\n");
         }
 
-        _enc_eol(&rle);
+        if (BD_UNLIKELY(_enc_eol(&rle) < 0)) {
+            goto out;
+        }
     }
 
+ out:
     return rle_get(&rle);
 }
 
@@ -128,44 +144,61 @@ BD_PG_RLE_ELEM *rle_crop_object(const BD_PG_RLE_ELEM *orig, int width,
  * compression
  */
 
-static void _rle_grow(RLE_ENC *p)
+static int _rle_grow(RLE_ENC *p)
 {
     p->free_elem--;
     p->elem++;
 
-    _rle_ensure_size(p);
+    if (BD_UNLIKELY(_rle_ensure_size(p) < 0)) {
+        return -1;
+    }
 
     p->elem->len = 0;
+
+    return 0;
 }
 
-void rle_add_eol(RLE_ENC *p)
+int rle_add_eol(RLE_ENC *p)
 {
     if (BD_LIKELY(p->elem->len)) {
-        _rle_grow(p);
+        if (BD_UNLIKELY(_rle_grow(p) < 0)) {
+            return -1;
+        }
     }
     p->elem->color = 0;
 
-    _rle_grow(p);
+    if (BD_UNLIKELY(_rle_grow(p) < 0)) {
+        return -1;
+    }
     p->elem->color = 0xffff;
+
+    return 0;
 }
 
-void rle_add_bite(RLE_ENC *p, uint8_t color, int len)
+int rle_add_bite(RLE_ENC *p, uint8_t color, int len)
 {
     if (BD_LIKELY(color == p->elem->color)) {
         p->elem->len += len;
     } else {
         if (BD_LIKELY(p->elem->len)) {
-            _rle_grow(p);
+            if (BD_UNLIKELY(!_rle_grow(p))) {
+                return -1;
+            }
         }
         p->elem->color = color;
         p->elem->len = len;
     }
+
+    return 0;
 }
 
-void rle_compress_chunk(RLE_ENC *p, const uint8_t *mem, unsigned width)
+int rle_compress_chunk(RLE_ENC *p, const uint8_t *mem, unsigned width)
 {
     unsigned ii;
     for (ii = 0; ii < width; ii++) {
-        rle_add_bite(p, mem[ii], 1);
+        if (BD_UNLIKELY(rle_add_bite(p, mem[ii], 1) < 0)) {
+              return -1;
+        }
     }
+    return 0;
 }
diff --git a/src/libbluray/decoders/rle.h b/src/libbluray/decoders/rle.h
index 1cd70e0..2dba817 100644
--- a/src/libbluray/decoders/rle.h
+++ b/src/libbluray/decoders/rle.h
@@ -34,6 +34,8 @@ typedef struct {
     BD_PG_RLE_ELEM *elem;     /* current element */
     unsigned int    free_elem;/* unused element count */
     unsigned int    num_elem; /* allocated element count */
+
+    int error;
 } RLE_ENC;
 
 /*
@@ -52,16 +54,26 @@ static inline int rle_begin(RLE_ENC *p)
     p->free_elem = 1024;
     p->elem = refcnt_realloc(NULL, p->num_elem * sizeof(BD_PG_RLE_ELEM));
     if (!p->elem) {
-        return 0;
+        return -1;
     }
     p->elem->len = 0;
     p->elem->color = 0xffff;
-    return 1;
+
+    p->error = 0;
+
+    return 0;
 }
 
 static inline BD_PG_RLE_ELEM *rle_get(RLE_ENC *p)
 {
     BD_PG_RLE_ELEM *start = (p->elem ? p->elem - (p->num_elem - p->free_elem) : NULL);
+    if (p->error) {
+        if (start) {
+            bd_refcnt_dec(start);
+            p->elem = NULL;
+        }
+        return NULL;
+    }
     return start;
 }
 
@@ -78,8 +90,8 @@ static inline void rle_end(RLE_ENC *p)
  * compression
  */
 
-BD_PRIVATE void rle_add_eol(RLE_ENC *p);
-BD_PRIVATE void rle_add_bite(RLE_ENC *p, uint8_t color, int len);
-BD_PRIVATE void rle_compress_chunk(RLE_ENC *p, const uint8_t *mem, unsigned width);
+BD_PRIVATE int rle_add_eol(RLE_ENC *p);
+BD_PRIVATE int rle_add_bite(RLE_ENC *p, uint8_t color, int len);
+BD_PRIVATE int rle_compress_chunk(RLE_ENC *p, const uint8_t *mem, unsigned width);
 
 #endif /* _BD_RLE_H_ */



More information about the libbluray-devel mailing list