changeset 34784:d180a74b1a89

av_sub: support multiple rectangles. The "packet_t" structure is renamed with a prefix, because it is used a public header.
author cigaes
date Sun, 22 Apr 2012 21:52:39 +0000
parents 1d4795fbdb67
children b89534df8e1e
files sub/av_sub.c sub/spudec.c sub/spudec.h
diffstat 3 files changed, 111 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/sub/av_sub.c	Sun Apr 22 12:10:49 2012 +0000
+++ b/sub/av_sub.c	Sun Apr 22 21:52:39 2012 +0000
@@ -32,6 +32,47 @@
     }
 }
 
+static void avsub_to_spudec(AVSubtitleRect **rects, int num_rects,
+                            double pts, double endpts)
+{
+    int i, xmin = INT_MAX, ymin = INT_MAX, xmax = INT_MIN, ymax = INT_MIN;
+    struct spu_packet_t *packet;
+
+    if (num_rects == 1) {
+        spudec_set_paletted(vo_spudec,
+                            rects[0]->pict.data[0],
+                            rects[0]->pict.linesize[0],
+                            rects[0]->pict.data[1],
+                            rects[0]->x,
+                            rects[0]->y,
+                            rects[0]->w,
+                            rects[0]->h,
+                            pts,
+                            endpts);
+        return;
+    }
+    for (i = 0; i < num_rects; i++) {
+        xmin = FFMIN(xmin, rects[i]->x);
+        ymin = FFMIN(ymin, rects[i]->y);
+        xmax = FFMAX(xmax, rects[i]->x + rects[i]->w);
+        ymax = FFMAX(ymax, rects[i]->y + rects[i]->h);
+    }
+    packet = spudec_packet_create(xmin, ymin, xmax - xmin, ymax - ymin);
+    if (!packet)
+        return;
+    spudec_packet_clear(packet);
+    for (i = 0; i < num_rects; i++)
+        spudec_packet_fill(packet,
+                           rects[i]->pict.data[0],
+                           rects[i]->pict.linesize[0],
+                           rects[i]->pict.data[1],
+                           rects[i]->x - xmin,
+                           rects[i]->y - ymin,
+                           rects[i]->w,
+                           rects[i]->h);
+    spudec_packet_send(vo_spudec, packet, pts, endpts);
+}
+
 /**
  * Decode a subtitle packet via libavcodec.
  * \return < 0 on error, > 0 if further processing is needed
@@ -90,16 +131,7 @@
         case SUBTITLE_BITMAP:
             if (!vo_spudec)
                 vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, NULL, 0);
-            spudec_set_paletted(vo_spudec,
-                                sub.rects[0]->pict.data[0],
-                                sub.rects[0]->pict.linesize[0],
-                                sub.rects[0]->pict.data[1],
-                                sub.rects[0]->x,
-                                sub.rects[0]->y,
-                                sub.rects[0]->w,
-                                sub.rects[0]->h,
-                                *pts,
-                                *endpts);
+            avsub_to_spudec(sub.rects, sub.num_rects, *pts, *endpts);
             vo_osd_changed(OSDTYPE_SPU);
             break;
         case SUBTITLE_TEXT:
--- a/sub/spudec.c	Sun Apr 22 12:10:49 2012 +0000
+++ b/sub/spudec.c	Sun Apr 22 21:52:39 2012 +0000
@@ -57,8 +57,8 @@
 int spu_alignment = -1;
 float spu_gaussvar = 1.0;
 
-typedef struct packet_t packet_t;
-struct packet_t {
+typedef struct spu_packet_t packet_t;
+struct spu_packet_t {
   int is_decoded;
   unsigned char *packet;
   int data_len;
@@ -1349,25 +1349,12 @@
 
 #define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly
 
-/**
- * palette must contain at least 256 32-bit entries, otherwise crashes
- * are possible
- */
-void spudec_set_paletted(void *this, const uint8_t *pal_img, int pal_stride,
-                         const void *palette,
-                         int x, int y, int w, int h,
-                         double pts, double endpts)
+packet_t *spudec_packet_create(int x, int y, int w, int h)
 {
-  int i;
-  uint16_t g8a8_pal[256];
   packet_t *packet;
-  const uint32_t *pal = palette;
-  spudec_handle_t *spu = this;
-  uint8_t *img;
-  uint8_t *aimg;
   int stride = (w + 7) & ~7;
   if ((unsigned)w >= 0x8000 || (unsigned)h > 0x4000)
-    return;
+    return NULL;
   packet = calloc(1, sizeof(packet_t));
   packet->is_decoded = 1;
   packet->width = w;
@@ -1377,21 +1364,47 @@
   packet->start_row = y;
   packet->data_len = 2 * stride * h;
   if (packet->data_len) { // size 0 is a special "clear" packet
-      packet->packet = malloc(packet->data_len);
-      img  = packet->packet;
-      aimg = packet->packet + stride * h;
-      for (i = 0; i < 256; i++) {
-          uint32_t pixel = pal[i];
-          int alpha = pixel >> 24;
-          int gray = (((pixel & 0x000000ff) >>  0) +
-                      ((pixel & 0x0000ff00) >>  7) +
-                      ((pixel & 0x00ff0000) >> 16)) >> 2;
-          gray = FFMIN(gray, alpha);
-          g8a8_pal[i] = (-alpha << 8) | gray;
-      }
-      pal2gray_alpha(g8a8_pal, pal_img, pal_stride,
-                     img, aimg, stride, w, h);
+    packet->packet = malloc(packet->data_len);
+    if (!packet->packet) {
+      free(packet);
+      packet = NULL;
+    }
   }
+  return packet;
+}
+
+void spudec_packet_clear(packet_t *packet)
+{
+  /* clear alpha and value, as value is premultiplied */
+  memset(packet->packet, 0, packet->data_len);
+}
+
+void spudec_packet_fill(packet_t *packet,
+                        const uint8_t *pal_img, int pal_stride,
+                        const void *palette,
+                        int x, int y, int w, int h)
+{
+  const uint32_t *pal = palette;
+  uint8_t *img  = packet->packet + x + y * packet->stride;
+  uint8_t *aimg = img + packet->stride * packet->height;
+  int i;
+  uint16_t g8a8_pal[256];
+
+  for (i = 0; i < 256; i++) {
+      uint32_t pixel = pal[i];
+      int alpha = pixel >> 24;
+      int gray = (((pixel & 0x000000ff) >>  0) +
+                  ((pixel & 0x0000ff00) >>  7) +
+                  ((pixel & 0x00ff0000) >> 16)) >> 2;
+      gray = FFMIN(gray, alpha);
+      g8a8_pal[i] = (-alpha << 8) | gray;
+  }
+  pal2gray_alpha(g8a8_pal, pal_img, pal_stride,
+                 img, aimg, packet->stride, w, h);
+}
+
+void spudec_packet_send(void *spu, packet_t *packet, double pts, double endpts)
+{
   packet->start_pts = 0;
   packet->end_pts = 0x7fffffff;
   if (pts != MP_NOPTS_VALUE)
@@ -1400,3 +1413,20 @@
     packet->end_pts = endpts * 90000;
   spudec_queue_packet(spu, packet);
 }
+
+/**
+ * palette must contain at least 256 32-bit entries, otherwise crashes
+ * are possible
+ */
+void spudec_set_paletted(void *spu, const uint8_t *pal_img, int pal_stride,
+                         const void *palette,
+                         int x, int y, int w, int h,
+                         double pts, double endpts)
+{
+  packet_t *packet = spudec_packet_create(x, y, w, h);
+  if (!packet)
+      return;
+  if (packet->data_len) // size 0 is a special "clear" packet
+    spudec_packet_fill(packet, pal_img, pal_stride, palette, 0, 0, w, h);
+  spudec_packet_send(spu, packet, pts, endpts);
+}
--- a/sub/spudec.h	Sun Apr 22 12:10:49 2012 +0000
+++ b/sub/spudec.h	Sun Apr 22 21:52:39 2012 +0000
@@ -41,5 +41,13 @@
                          const void *palette,
                          int x, int y, int w, int h,
                          double pts, double endpts);
+struct spu_packet_t *spudec_packet_create(int x, int y, int w, int h);
+void spudec_packet_fill(struct spu_packet_t *packet,
+                        const uint8_t *pal_img, int pal_stride,
+                        const void *palette,
+                        int x, int y, int w, int h);
+void spudec_packet_send(void *spu, struct spu_packet_t *packet,
+                        double pts, double endpts);
+void spudec_packet_clear(struct spu_packet_t *packet);
 
 #endif /* MPLAYER_SPUDEC_H */