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

Nicolas George nicolas.george
Mon Mar 2 14:41:10 CET 2009


Hi.

Here is a new version of the patch. It does two things:

- It prints a warning when a subtitle has more than 4 colors or when one of
  the 4 main colors is beyond 16.

- It copies the palette and alpha information to the encoded data instead of
  hardcoded arbitrary values.

(It also adds an AVCodecContext parameter, just to have a proper context for
the warning.)

Regards,

-- 
  Nicolas George
-------------- next part --------------
diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c
index 4dc58e7..28e9837 100644
--- a/libavcodec/dvdsubenc.c
+++ b/libavcodec/dvdsubenc.c
@@ -86,7 +86,8 @@ static void dvd_encode_rle(uint8_t **pq,
     *pq = q;
 }
 
-static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
+static int encode_dvd_subtitles(AVCodecContext *avctx,
+                                uint8_t *outbuf, int outbuf_size,
                                 const AVSubtitle *h)
 {
     uint8_t *q, *qq;
@@ -96,6 +97,8 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
     unsigned long hmax;
     unsigned long hist[256];
     int           cmap[256];
+    unsigned rev_cmap[4] = { 0, 0, 0, 0 };
+    uint32_t *palette;
 
     if (rects == 0 || h->rects == NULL)
         return -1;
@@ -114,7 +117,7 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
             alpha = ((uint32_t*)h->rects[object_id]->pict.data[1])[color] >> 24;
             hist[color] += alpha;
         }
-    for (color=3;; --color) {
+    for (color = 0; color < 256; color++) {
         hmax = 0;
         imax = 0;
         for (i=0; i<256; ++i)
@@ -124,12 +127,19 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
             }
         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;
+        if (color == 4)
+            av_log(avctx, AV_LOG_WARNING, "DVD subtitles have only 4 colors; "
+                   "extra colors are remapped.\n");
+        cmap[imax] = 3 - color % 4;
         hist[imax] = 0;
+        if (color < 4) {
+            if (imax >= 16)
+                av_log(avctx, AV_LOG_WARNING, "DVD subtitles palette have "
+                       "only 16 entries.\n");
+            rev_cmap[color] = imax & 15;
+        }
     }
 
 
@@ -161,11 +171,15 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
     // send start display command
     bytestream_put_be16(&q, (h->start_display_time*90) >> 10);
     bytestream_put_be16(&q, (q - outbuf) /*- 2 */ + 8 + 12*rects + 2);
+    palette = (uint32_t *)h->rects[0]->pict.data[1];
     *q++ = 0x03; // palette - 4 nibbles
-    *q++ = 0x03; *q++ = 0x7f;
+    *q++ = (rev_cmap[0] << 4) + rev_cmap[1];
+    *q++ = (rev_cmap[2] << 4) + rev_cmap[3];
     *q++ = 0x04; // alpha - 4 nibbles
-    *q++ = 0xf0; *q++ = 0x00;
-    //*q++ = 0x0f; *q++ = 0xff;
+    *q++ = ((palette[rev_cmap[0]] >> 28) << 4) +
+           ((palette[rev_cmap[1]] >> 28) << 0);
+    *q++ = ((palette[rev_cmap[2]] >> 28) << 4) +
+           ((palette[rev_cmap[3]] >> 28) << 0);
 
     // XXX not sure if more than one rect can really be encoded..
     // 12 bytes per rect
@@ -211,7 +225,7 @@ static int dvdsub_encode(AVCodecContext *avctx,
     AVSubtitle *sub = data;
     int ret;
 
-    ret = encode_dvd_subtitles(buf, buf_size, sub);
+    ret = encode_dvd_subtitles(avctx, buf, buf_size, sub);
     return ret;
 }
 
-------------- 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/20090302/48a9e8a8/attachment.pgp>



More information about the ffmpeg-devel mailing list