Merge commit '3c650efb81aaa3b395ba4606ee68a47ee4efb57b'
[ffmpeg.git] / libavcodec / dvdsubenc.c
index 1939cb8..d19d071 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include "avcodec.h"
 #include "bytestream.h"
  */
 #include "avcodec.h"
 #include "bytestream.h"
+#include "internal.h"
 #include "libavutil/avassert.h"
 #include "libavutil/bprint.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/avassert.h"
 #include "libavutil/bprint.h"
 #include "libavutil/imgutils.h"
@@ -93,10 +94,14 @@ static void dvd_encode_rle(uint8_t **pq,
 static int color_distance(uint32_t a, uint32_t b)
 {
     int r = 0, d, i;
 static int color_distance(uint32_t a, uint32_t b)
 {
     int r = 0, d, i;
+    int alpha_a = 8, alpha_b = 8;
 
 
-    for (i = 0; i < 32; i += 8) {
-        d = ((a >> i) & 0xFF) - ((b >> i) & 0xFF);
+    for (i = 24; i >= 0; i -= 8) {
+        d = alpha_a * (int)((a >> i) & 0xFF) -
+            alpha_b * (int)((b >> i) & 0xFF);
         r += d * d;
         r += d * d;
+        alpha_a = a >> 28;
+        alpha_b = b >> 28;
     }
     return r;
 }
     }
     return r;
 }
@@ -129,7 +134,8 @@ static void count_colors(AVCodecContext *avctx, unsigned hits[33],
         if (match) {
             best_d = INT_MAX;
             for (j = 0; j < 16; j++) {
         if (match) {
             best_d = INT_MAX;
             for (j = 0; j < 16; j++) {
-                d = color_distance(color & 0xFFFFFF, dvdc->global_palette[j]);
+                d = color_distance(0xFF000000 | color,
+                                   0xFF000000 | dvdc->global_palette[j]);
                 if (d < best_d) {
                     best_d = d;
                     best_j = j;
                 if (d < best_d) {
                     best_d = d;
                     best_j = j;
@@ -201,7 +207,7 @@ static void select_palette(AVCodecContext *avctx, int out_palette[4],
 
 static void build_color_map(AVCodecContext *avctx, int cmap[],
                             const uint32_t palette[],
 
 static void build_color_map(AVCodecContext *avctx, int cmap[],
                             const uint32_t palette[],
-                            const int out_palette[], int const out_alpha[])
+                            const int out_palette[], unsigned int const out_alpha[])
 {
     DVDSubtitleContext *dvdc = avctx->priv_data;
     int i, j, d, best_d;
 {
     DVDSubtitleContext *dvdc = avctx->priv_data;
     int i, j, d, best_d;
@@ -253,9 +259,21 @@ static int encode_dvd_subtitles(AVCodecContext *avctx,
     AVSubtitleRect vrect;
     uint8_t *vrect_data = NULL;
     int x2, y2;
     AVSubtitleRect vrect;
     uint8_t *vrect_data = NULL;
     int x2, y2;
+    int forced = 0;
 
     if (rects == 0 || h->rects == NULL)
         return AVERROR(EINVAL);
 
     if (rects == 0 || h->rects == NULL)
         return AVERROR(EINVAL);
+    for (i = 0; i < rects; i++)
+        if (h->rects[i]->type != SUBTITLE_BITMAP) {
+            av_log(avctx, AV_LOG_ERROR, "Bitmap subtitle required\n");
+            return AVERROR(EINVAL);
+        }
+    /* Mark this subtitle forced if any of the rectangles is forced. */
+    for (i = 0; i < rects; i++)
+        if ((h->rects[i]->flags & AV_SUBTITLE_FLAG_FORCED) != 0) {
+            forced = 1;
+            break;
+        }
     vrect = *h->rects[0];
 
     if (rects > 1) {
     vrect = *h->rects[0];
 
     if (rects > 1) {
@@ -314,19 +332,18 @@ static int encode_dvd_subtitles(AVCodecContext *avctx,
 
     // encode data block
     q = outbuf + 4;
 
     // encode data block
     q = outbuf + 4;
-    /* TODO reindent */
-        offset1 = q - outbuf;
-        // worst case memory requirement: 1 nibble per pixel..
-        if ((q - outbuf) + vrect.w * vrect.h / 2 + 17 + 21 > outbuf_size) {
-            av_log(NULL, AV_LOG_ERROR, "dvd_subtitle too big\n");
-            ret = AVERROR_BUFFER_TOO_SMALL;
-            goto fail;
-        }
-        dvd_encode_rle(&q, vrect.pict.data[0], vrect.w * 2,
-                       vrect.w, (vrect.h + 1) >> 1, cmap);
-        offset2 = q - outbuf;
-        dvd_encode_rle(&q, vrect.pict.data[0] + vrect.w, vrect.w * 2,
-                       vrect.w, vrect.h >> 1, cmap);
+    offset1 = q - outbuf;
+    // worst case memory requirement: 1 nibble per pixel..
+    if ((q - outbuf) + vrect.w * vrect.h / 2 + 17 + 21 > outbuf_size) {
+        av_log(NULL, AV_LOG_ERROR, "dvd_subtitle too big\n");
+        ret = AVERROR_BUFFER_TOO_SMALL;
+        goto fail;
+    }
+    dvd_encode_rle(&q, vrect.pict.data[0], vrect.w * 2,
+                   vrect.w, (vrect.h + 1) >> 1, cmap);
+    offset2 = q - outbuf;
+    dvd_encode_rle(&q, vrect.pict.data[0] + vrect.w, vrect.w * 2,
+                   vrect.w, vrect.h >> 1, cmap);
 
     // set data packet size
     qq = outbuf + 2;
 
     // set data packet size
     qq = outbuf + 2;
@@ -343,26 +360,25 @@ static int encode_dvd_subtitles(AVCodecContext *avctx,
     *q++ = (out_alpha[1] & 0xF0) | (out_alpha[0] >> 4);
 
     // 12 bytes per rect
     *q++ = (out_alpha[1] & 0xF0) | (out_alpha[0] >> 4);
 
     // 12 bytes per rect
-    /* TODO reindent */
-        x2 = vrect.x + vrect.w - 1;
-        y2 = vrect.y + vrect.h - 1;
-
-        *q++ = 0x05;
-        // x1 x2 -> 6 nibbles
-        *q++ = vrect.x >> 4;
-        *q++ = (vrect.x << 4) | ((x2 >> 8) & 0xf);
-        *q++ = x2;
-        // y1 y2 -> 6 nibbles
-        *q++ = vrect.y >> 4;
-        *q++ = (vrect.y << 4) | ((y2 >> 8) & 0xf);
-        *q++ = y2;
-
-        *q++ = 0x06;
-        // offset1, offset2
-        bytestream_put_be16(&q, offset1);
-        bytestream_put_be16(&q, offset2);
-
-    *q++ = 0x01; // start command
+    x2 = vrect.x + vrect.w - 1;
+    y2 = vrect.y + vrect.h - 1;
+
+    *q++ = 0x05;
+    // x1 x2 -> 6 nibbles
+    *q++ = vrect.x >> 4;
+    *q++ = (vrect.x << 4) | ((x2 >> 8) & 0xf);
+    *q++ = x2;
+    // y1 y2 -> 6 nibbles
+    *q++ = vrect.y >> 4;
+    *q++ = (vrect.y << 4) | ((y2 >> 8) & 0xf);
+    *q++ = y2;
+
+    *q++ = 0x06;
+    // offset1, offset2
+    bytestream_put_be16(&q, offset1);
+    bytestream_put_be16(&q, offset2);
+
+    *q++ = forced ? 0x00 : 0x01; // start command
     *q++ = 0xff; // terminating command
 
     // send stop display command last
     *q++ = 0xff; // terminating command
 
     // send stop display command last
@@ -374,7 +390,7 @@ static int encode_dvd_subtitles(AVCodecContext *avctx,
     qq = outbuf;
     bytestream_put_be16(&qq, q - outbuf);
 
     qq = outbuf;
     bytestream_put_be16(&qq, q - outbuf);
 
-    av_log(NULL, AV_LOG_DEBUG, "subtitle_packet size=%td\n", q - outbuf);
+    av_log(NULL, AV_LOG_DEBUG, "subtitle_packet size=%"PTRDIFF_SPECIFIER"\n", q - outbuf);
     ret = q - outbuf;
 
 fail:
     ret = q - outbuf;
 
 fail:
@@ -398,23 +414,25 @@ static int dvdsub_init(AVCodecContext *avctx)
     memcpy(dvdc->global_palette, default_palette, sizeof(dvdc->global_palette));
 
     av_bprint_init(&extradata, 0, 1);
     memcpy(dvdc->global_palette, default_palette, sizeof(dvdc->global_palette));
 
     av_bprint_init(&extradata, 0, 1);
+    if (avctx->width && avctx->height)
+        av_bprintf(&extradata, "size: %dx%d\n", avctx->width, avctx->height);
     av_bprintf(&extradata, "palette:");
     for (i = 0; i < 16; i++)
         av_bprintf(&extradata, " %06"PRIx32"%c",
                    dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n');
 
     av_bprintf(&extradata, "palette:");
     for (i = 0; i < 16; i++)
         av_bprintf(&extradata, " %06"PRIx32"%c",
                    dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n');
 
-    if ((ret = av_bprint_finalize(&extradata, (char **)&avctx->extradata)) < 0)
+    ret = avpriv_bprint_to_extradata(avctx, &extradata);
+    if (ret < 0)
         return ret;
         return ret;
-    avctx->extradata_size = extradata.len;
 
     return 0;
 }
 
 static int dvdsub_encode(AVCodecContext *avctx,
 
     return 0;
 }
 
 static int dvdsub_encode(AVCodecContext *avctx,
-                         unsigned char *buf, int buf_size, void *data)
+                         unsigned char *buf, int buf_size,
+                         const AVSubtitle *sub)
 {
     //DVDSubtitleContext *s = avctx->priv_data;
 {
     //DVDSubtitleContext *s = avctx->priv_data;
-    AVSubtitle *sub = data;
     int ret;
 
     ret = encode_dvd_subtitles(avctx, buf, buf_size, sub);
     int ret;
 
     ret = encode_dvd_subtitles(avctx, buf, buf_size, sub);
@@ -423,10 +441,10 @@ static int dvdsub_encode(AVCodecContext *avctx,
 
 AVCodec ff_dvdsub_encoder = {
     .name           = "dvdsub",
 
 AVCodec ff_dvdsub_encoder = {
     .name           = "dvdsub",
+    .long_name      = NULL_IF_CONFIG_SMALL("DVD subtitles"),
     .type           = AVMEDIA_TYPE_SUBTITLE,
     .id             = AV_CODEC_ID_DVD_SUBTITLE,
     .init           = dvdsub_init,
     .type           = AVMEDIA_TYPE_SUBTITLE,
     .id             = AV_CODEC_ID_DVD_SUBTITLE,
     .init           = dvdsub_init,
-    .encode         = dvdsub_encode,
-    .long_name      = NULL_IF_CONFIG_SMALL("DVD subtitles"),
+    .encode_sub     = dvdsub_encode,
     .priv_data_size = sizeof(DVDSubtitleContext),
 };
     .priv_data_size = sizeof(DVDSubtitleContext),
 };