diff options
| author | phintuka <phintuka> | 2011-01-21 14:38:55 +0000 |
|---|---|---|
| committer | phintuka <phintuka> | 2011-01-21 14:38:55 +0000 |
| commit | afda0d4e8f830ec110c68dc9ee58341b82352af3 (patch) | |
| tree | 56e53ef09e2a466cbb1d0ad9150062e8e5b924c5 /tools | |
| parent | 17167143bbfce792f5837aa8ab1bb785ffecd85e (diff) | |
| download | xineliboutput-afda0d4e8f830ec110c68dc9ee58341b82352af3.tar.gz xineliboutput-afda0d4e8f830ec110c68dc9ee58341b82352af3.tar.bz2 | |
Added HDMV PG compatible RLE functions
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/rle.c | 167 | ||||
| -rw-r--r-- | tools/rle.h | 12 |
2 files changed, 177 insertions, 2 deletions
diff --git a/tools/rle.c b/tools/rle.c index 89a21879..51a4bc2b 100644 --- a/tools/rle.c +++ b/tools/rle.c @@ -4,7 +4,7 @@ * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * - * $Id: rle.c,v 1.5 2010-07-19 13:20:22 phintuka Exp $ + * $Id: rle.c,v 1.6 2011-01-21 14:38:55 phintuka Exp $ * */ @@ -172,3 +172,168 @@ xine_rle_elem_t *rle_scale_nearest(const xine_rle_elem_t *old_rle, int *rle_elem *rle_elems = num_rle; return new_rle_start; } + +/* + * encode single HDMV PG rle element + */ +static uint8_t *write_rle_hdmv(uint8_t *rle_data, uint color, uint len) +{ + /* short non-transparent sequences are uncompressed */ + if (color && len < 4) { + uint i; + for (i = 0; i < len; i++) { + *rle_data++ = color; + } + return rle_data; + } + + /* rle code marker */ + *rle_data++ = 0; + + if (!color) { + /* transparent */ + if (len < 64) { + *rle_data++ = len; + } else { + *rle_data++ = 0x40 | ((len >> 8) & 0x3f); + *rle_data++ = len & 0xff; + } + } else { + if (len < 64) { + *rle_data++ = 0x80 | len; + } else { + *rle_data++ = 0x80 | 0x40 | ((len >> 8) & 0x3f); + *rle_data++ = len & 0xff; + } + *rle_data++ = color; + } + + return rle_data; +} + +/* + * compress LUT8 image using HDMV PG compression algorithm + */ +size_t rle_compress_hdmv(uint8_t **rle_data, const uint8_t *data, uint w, uint h, int *num_rle) +{ + uint y; + size_t rle_size = 0; + uint8_t *rle = NULL; + + *rle_data = NULL; + *num_rle = 0; + + for (y = 0; y < h; y++) { + + /* grow buffer ? */ + if ((ssize_t)(rle_size - (rle - *rle_data)) < w * 4) { + size_t used = rle - *rle_data; + rle_size = rle_size < 1 ? w*h/16 : rle_size*2; + *rle_data = realloc(*rle_data, rle_size); + rle = *rle_data + used; + } + + /* compress line */ + uint color = *data; + uint len = 1; + uint x = 1; + + for (x = 1; x < w; x++) { + if (data[x] == color) { + len++; + } else { + rle = write_rle_hdmv(rle, color, len); + (*num_rle)++; + color = data[x]; + len = 1; + } + } + + if (len) { + rle = write_rle_hdmv(rle, color, len); + (*num_rle)++; + } + + /* end of line marker */ + rle = write_rle_hdmv(rle, 0, 0); + (*num_rle)++; + data += w; + } + + return rle - *rle_data; +} + + +int rle_uncompress_hdmv(xine_rle_elem_t **data, + uint w, uint h, + const uint8_t *rle_data, uint num_rle, size_t rle_size) +{ + uint rle_count = 0, x = 0, y = 0; + xine_rle_elem_t *rlep = calloc(2*num_rle, sizeof(xine_rle_elem_t)); + const uint8_t *end = rle_data + rle_size; + + *data = rlep; + + /* convert to xine-lib rle format */ + while (y < h) { + + if (rle_data >= end || rle_count >= 2*num_rle) { + free(*data); + *data = NULL; + return -1 - (rle_data >= end); + } + + /* decode RLE element */ + uint byte = *rle_data++; + if (byte) { + rlep->color = byte; + rlep->len = 1; + } else { + byte = *rle_data++; + if (!(byte & 0x80)) { + rlep->color = 0; + if (!(byte & 0x40)) + rlep->len = byte & 0x3f; + else + rlep->len = ((byte & 0x3f) << 8) | *rle_data++; + } else { + if (!(byte & 0x40)) + rlep->len = byte & 0x3f; + else + rlep->len = ((byte & 0x3f) << 8) | *rle_data++; + rlep->color = *rle_data++; + } + } + + /* move to next element */ + if (rlep->len > 0) { + + if (rlep->len == 1 && x && rlep[-1].color == rlep->color) { + rlep[-1].len++; + x++; + } else { + x += rlep->len; + rlep++; + rle_count++; + } + + if (x > w) { + return -9999; + } + + } else { + /* end of line marker (00 00) */ + if (x < w-1) { + //return -1-rlep->color - (w-x); + rlep->len = w - x; + rlep->color = 0xff; + rlep++; + rle_count++; + } + x = 0; + y++; + } + } + + return rle_count; +} diff --git a/tools/rle.h b/tools/rle.h index b4fed0dd..41a579d2 100644 --- a/tools/rle.h +++ b/tools/rle.h @@ -4,7 +4,7 @@ * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * - * $Id: rle.h,v 1.3 2010-05-21 11:55:15 phintuka Exp $ + * $Id: rle.h,v 1.4 2011-01-21 14:38:55 phintuka Exp $ * */ @@ -45,6 +45,16 @@ struct xine_rle_elem_s *rle_scale_nearest(const struct xine_rle_elem_s *old_rle, uint w, uint h, uint new_w, uint new_h); +/* + * HDMV (BluRay) presentation graphics format + */ + +size_t rle_compress_hdmv(uint8_t **rle_data, const uint8_t *data, uint w, uint h, int *num_rle); +int rle_uncompress_hdmv(struct xine_rle_elem_s **data, + uint w, uint h, + const uint8_t *rle_data, uint num_rle, size_t rle_size); + + #if defined __cplusplus } #endif |
