[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