[Ffmpeg-devel] [PATCH] HD DVD subtitle decoding

Michael Niedermayer michaelni
Sat Jan 27 02:59:53 CET 2007


Hi

On Thu, Jan 25, 2007 at 11:51:04AM +0000, Ian Caulfield wrote:
> Hi,
> 
> The attached patches add support for HD DVD subtitles (both 2-bit and 8-bit)
> to the dvdsub decoder. The patches depend on my earlier bugfix/tidy patches,
> which I've reattached as dvdsub1.patch and dvdsub2.patch.

1 patch per mail is prefered, 2patches (1 functional + 1 cosmetic is ok too)
but reposting all the prerequisites together with 5 new patches really makes
our work hard


> 
> dvdsubdec-rename.patch renames one of the internal functions and some local
> variable in order to avoid confusion between the 2-bit and 8-bit RLE modes.
> 
> dvdsubdec-hd.patch adds the HD DVD subtitle support
> 
> dvdsubdec-retab.patch retabulates the code
> 
> I'm not sure about the yuvtorgb code - I lifted this from dvbsubdec.c, but I
> reckon it should probably live somewhere else, though I couldn't decide
> where.

well choose a filename you like and put it there, copy and paste is not ok
ideally the yuv2rgb code from libswscale/ should be used / or the code should 
be moved into libswscale/ but thats not so important and can be done later


[...]

> @@ -78,6 +117,55 @@
>      return 0;
>  }
>  
> +static int decode_rle_8bit(uint8_t *bitmap, int linesize, int w, int h,
> +                           const uint8_t *buf, int start, int buf_size) 
> +{
> +    GetBitContext gb;
> +    int bit_len;
> +    int x, y, len, color, has_run;
> +    uint8_t *d;
> +
> +    bit_len = (buf_size - start) * 8;
> +    init_get_bits(&gb, buf + start, bit_len);
> +
> +    x = 0;
> +    y = 0;
> +    d = bitmap;
> +    for(;;) {
> +        if (get_bits_count(&gb) > bit_len)
> +            return -1;
> +        has_run = get_bits1(&gb);
> +        if (get_bits1(&gb))
> +            color = get_bits(&gb, 8);
> +        else
> +            color = get_bits(&gb, 2);
> +        if (has_run) {
> +            if (get_bits1(&gb)) {
> +                len = get_bits(&gb, 7);
> +                if (len == 0)
> +                    len = w - x;
> +                else
> +                    len += 9;
> +            } else
> +                len = get_bits(&gb, 3) + 2;
> +        } else
> +            len = 1;
> +
> +        len = FFMIN(len, w - x);
> +        memset(d + x, color, len);
> +        x += len;
> +        if (x >= w) {
> +            y++;
> +            if (y >= h)
> +                break;
> +            d += linesize;
> +            x = 0;
> +            align_get_bits(&gb);

this looks duplicated, maybe this can be factored out into its own function?


> +        }
> +    }
> +    return 0;
> +}
> +
>  static void guess_palette(uint32_t *rgba_palette,
>                            uint8_t *palette,
>                            uint8_t *alpha,
> @@ -125,27 +213,39 @@
>                                  const uint8_t *buf, int buf_size)
>  {
>      int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos;
> +    int big_offsets = 0, is_8bit = 0;
>      uint8_t colormap_2bit[4], alpha_2bit[4];
> +    uint32_t palette_8bit[256];
>      int date;
>      int i;
>      int is_menu = 0;
>  
> -    if (buf_size < 4)
> +    if (buf_size < 10)
>          return -1;
>      sub_header->rects = NULL;
>      sub_header->num_rects = 0;
>      sub_header->start_display_time = 0;
>      sub_header->end_display_time = 0;
>  
> +    if (AV_RB16(buf) == 0)    /* HD subpicture with 4-byte offsets */
> +        big_offsets = 1;
> +
> +    if (big_offsets)
> +        cmd_pos = AV_RB32(buf + 6);
> +    else
>      cmd_pos = AV_RB16(buf + 2);
> -    while ((cmd_pos + 4) < buf_size) {
> +
> +    while ((cmd_pos + (big_offsets ? 6 : 4)) < buf_size) {
>          date = AV_RB16(buf + cmd_pos);
> +        if (big_offsets)
> +            next_cmd_pos = AV_RB32(buf + cmd_pos + 2);
> +        else
>          next_cmd_pos = AV_RB16(buf + cmd_pos + 2);
>  #ifdef DEBUG
>          av_log(NULL, AV_LOG_INFO, "cmd_pos=0x%04x next=0x%04x date=%d\n",
>                 cmd_pos, next_cmd_pos, date);
>  #endif
> -        pos = cmd_pos + 4;
> +        pos = cmd_pos + (big_offsets ? 6 : 4);
>          offset1 = -1;
>          offset2 = -1;
>          x1 = y1 = x2 = y2 = 0;
> @@ -191,6 +291,7 @@
>  #endif
>                  break;
>              case 0x05:
> +            case 0x85:
>                  if ((buf_size - pos) < 6)
>                      goto fail;
>                  x1 = (buf[pos] << 4) | (buf[pos + 1] >> 4);
> @@ -213,6 +314,40 @@
>  #endif
>                  pos += 4;
>                  break;
> +            case 0x86:
> +                if ((buf_size - pos) < 8)
> +                    goto fail;
> +                offset1 = AV_RB32(buf + pos);
> +                offset2 = AV_RB32(buf + pos + 4);
> +#ifdef DEBUG
> +                av_log(NULL, AV_LOG_INFO, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2);
> +#endif
> +                pos += 8;
> +                break;
> +
> +            case 0x83:
> +                /* HD set palette */
> +                if ((buf_size - pos) < 768)
> +                    goto fail;
> +                for (i = 0; i < 256; i++)
> +                    palette_8bit[i] = (palette_8bit[i] & 0xff000000)
> +                                      | yuv_to_rgb32(buf[pos+i*3], 
> +                                                     buf[pos+i*3+1],
> +                                                     buf[pos+i*3+2]);
> +                is_8bit = 1;
> +                pos += 768;
> +                break;
> +            case 0x84:
> +                /* HD set contrast (alpha) */
> +                if ((buf_size - pos) < 256)
> +                    goto fail;
> +                for (i = 0; i < 256; i++)
> +                    palette_8bit[i] = (palette_8bit[i] & 0x00ffffff)
> +                                      | ((0xFF - buf[pos+i]) << 24);
> +                is_8bit = 1;
> +                pos += 256;
> +                break;
> +

something like
if(big_palette){
    nb_colors= 256;
    pal_entry_size= 24;
    alpha_entry_size= 8;
}else{
    nb_colors= 4;
    pal_entry_size= 4;
    alpha_entry_size= 4;
}

case 0x03:
case 0x83:
    /* set palette */
    if ((buf_size - pos) < pal_entry_size*nb_colors/8)
        goto fail;
    for(i=0; i<nb_colors; i++)
        palette[i]= get_bits(pal_entry_size);
    break;
case 0x04:
case 0x04:
    /* set alpha */
    if ((buf_size - pos) < alpha_entry_size*nb_colors/8)
        goto fail;
    for(i=0; i<nb_colors; i++)
        alpha[i]= get_bits(alpha_entry_size);
    break;

the same can be done with case 0x86/6

and guess_palette() could then do the yuv->rgb which is IMHO cleaner then
your code where the 2bit palette is "converted" in guess_palette() while
the 8bit one is handled while it is read

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No snowflake in an avalanche ever feels responsible. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070127/303f8a9b/attachment.pgp>



More information about the ffmpeg-devel mailing list