libbluray | branch: master | hpi1 <h...@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_ */ _______________________________________________ libbluray-devel mailing list libbluray-devel@videolan.org https://mailman.videolan.org/listinfo/libbluray-devel