[FFmpeg-devel] dvdsub encoder: respect palette when it makes sense

Nicolas George nicolas.george
Sun Mar 1 10:45:38 CET 2009


Hi.

The current version of the dvdsub encoder uses the alpha channel of the
palette to weight the most important colors, and then completely ignores the
palette. In particular, the alpha values it puts in the stream are hardcoded
arbitrary values.

The attached patch fix that to a certain extent: when there is exactly one
rectangle and the palette has exactly 4 colors, the colors are kept in their
original order and the alpha channel of the palette is copied to the stream.

With this patch, it becomes possible to use the dvdsub encoder to produce a
VOBSUB pair of file that mplayer can understand.

Regards,

-- 
  Nicolas George
-------------- next part --------------
diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c
index 4dc58e7..0fcd1b1 100644
--- a/libavcodec/dvdsubenc.c
+++ b/libavcodec/dvdsubenc.c
@@ -93,6 +93,7 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
     int object_id;
     int offset1[20], offset2[20];
     int i, imax, color, alpha, rects = h->num_rects;
+    unsigned keep_palette;
     unsigned long hmax;
     unsigned long hist[256];
     int           cmap[256];
@@ -102,11 +103,16 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
     if (rects > 20)
         rects = 20;
 
+    keep_palette = rects == 1 && h->rects[0]->nb_colors == 4;
     // analyze bitmaps, compress to 4 colors
     for (i=0; i<256; ++i) {
         hist[i] = 0;
         cmap[i] = 0;
     }
+    if (keep_palette) {
+        for (i = 0; i < 4; i++)
+            cmap[i] = 3 - i;
+    } else {
     for (object_id = 0; object_id < rects; object_id++)
         for (i=0; i<h->rects[object_id]->w*h->rects[object_id]->h; ++i) {
             color = h->rects[object_id]->pict.data[0][i];
@@ -131,6 +137,7 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
         cmap[imax] = color;
         hist[imax] = 0;
     }
+    }
 
 
     // encode data block
@@ -164,8 +171,14 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
     *q++ = 0x03; // palette - 4 nibbles
     *q++ = 0x03; *q++ = 0x7f;
     *q++ = 0x04; // alpha - 4 nibbles
+    if (keep_palette) {
+        uint32_t *p = (uint32_t*)h->rects[0]->pict.data[1];
+        *q++ = (((p[0] >> 24) / 17) << 4) + ((p[1] >> 24) / 17);
+        *q++ = (((p[2] >> 24) / 17) << 4) + ((p[3] >> 24) / 17);
+    } else {
     *q++ = 0xf0; *q++ = 0x00;
     //*q++ = 0x0f; *q++ = 0xff;
+    }
 
     // XXX not sure if more than one rect can really be encoded..
     // 12 bytes per rect
-------------- next part --------------
diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c
index 0fcd1b1..a37092b 100644
--- a/libavcodec/dvdsubenc.c
+++ b/libavcodec/dvdsubenc.c
@@ -113,30 +113,30 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
         for (i = 0; i < 4; i++)
             cmap[i] = 3 - i;
     } else {
-    for (object_id = 0; object_id < rects; object_id++)
-        for (i=0; i<h->rects[object_id]->w*h->rects[object_id]->h; ++i) {
-            color = h->rects[object_id]->pict.data[0][i];
-            // only count non-transparent pixels
-            alpha = ((uint32_t*)h->rects[object_id]->pict.data[1])[color] >> 24;
-            hist[color] += alpha;
-        }
-    for (color=3;; --color) {
-        hmax = 0;
-        imax = 0;
-        for (i=0; i<256; ++i)
-            if (hist[i] > hmax) {
-                imax = i;
-                hmax = hist[i];
+        for (object_id = 0; object_id < rects; object_id++)
+            for (i=0; i<h->rects[object_id]->w*h->rects[object_id]->h; ++i) {
+                color = h->rects[object_id]->pict.data[0][i];
+                // only count non-transparent pixels
+                alpha = ((uint32_t*)h->rects[object_id]->pict.data[1])[color] >> 24;
+                hist[color] += alpha;
             }
-        if (hmax == 0)
-            break;
-        if (color == 0)
-            color = 3;
-        av_log(NULL, AV_LOG_DEBUG, "dvd_subtitle hist[%d]=%ld -> col %d\n",
-               imax, hist[imax], color);
-        cmap[imax] = color;
-        hist[imax] = 0;
-    }
+        for (color=3;; --color) {
+            hmax = 0;
+            imax = 0;
+            for (i=0; i<256; ++i)
+                if (hist[i] > hmax) {
+                    imax = i;
+                    hmax = hist[i];
+                }
+            if (hmax == 0)
+                break;
+            if (color == 0)
+                color = 3;
+            av_log(NULL, AV_LOG_DEBUG, "dvd_subtitle hist[%d]=%ld -> col %d\n",
+                   imax, hist[imax], color);
+            cmap[imax] = color;
+            hist[imax] = 0;
+        }
     }
 
 
@@ -176,8 +176,8 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
         *q++ = (((p[0] >> 24) / 17) << 4) + ((p[1] >> 24) / 17);
         *q++ = (((p[2] >> 24) / 17) << 4) + ((p[3] >> 24) / 17);
     } else {
-    *q++ = 0xf0; *q++ = 0x00;
-    //*q++ = 0x0f; *q++ = 0xff;
+        *q++ = 0xf0; *q++ = 0x00;
+        //*q++ = 0x0f; *q++ = 0xff;
     }
 
     // XXX not sure if more than one rect can really be encoded..
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090301/d193c618/attachment.pgp>



More information about the ffmpeg-devel mailing list