[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