androidmedia: add support for a new qualcomm colorspace
authorJorge Luis Zapata <jzapata@fluendo.com>
Mon, 12 Aug 2013 10:16:16 +0000 (10:16 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Tue, 3 Sep 2013 09:06:00 +0000 (11:06 +0200)
sys/androidmedia/gstamc-constants.h
sys/androidmedia/gstamc.c
sys/androidmedia/gstamcvideodec.c

index ea6288c..f263cdd 100644 (file)
@@ -95,6 +95,7 @@ enum
   COLOR_FormatAndroidOpaque = 0x7F000789,
   COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100,
   COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00,
+  COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7fa30c03,
   /* From hardware/ti/omap4xxx/domx/omx_core/inc/OMX_TI_IVCommon.h */
   COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced = 0x7f000001
 };
index e4fdfbf..6c185b4 100644 (file)
@@ -2125,7 +2125,8 @@ static const struct
   COLOR_FormatYUV420SemiPlanar, GST_VIDEO_FORMAT_NV12}, {
   COLOR_TI_FormatYUV420PackedSemiPlanar, GST_VIDEO_FORMAT_NV12}, {
   COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced, GST_VIDEO_FORMAT_NV12}, {
-  COLOR_QCOM_FormatYUV420SemiPlanar, GST_VIDEO_FORMAT_NV12}
+  COLOR_QCOM_FormatYUV420SemiPlanar, GST_VIDEO_FORMAT_NV12}, {
+  COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, GST_VIDEO_FORMAT_NV12}
 };
 
 static gboolean
index 735ac33..71a1be3 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) 2012, Collabora Ltd.
  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
+ * Copyright (C) 2012, Rafaël Carré <funman@videolanorg>
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation
@@ -766,6 +768,30 @@ gst_amc_video_dec_set_src_caps (GstAmcVideoDec * self, GstAmcFormat * format)
   return TRUE;
 }
 
+/*
+ * The format is called QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka.
+ * Which is actually NV12 (interleaved U&V).
+ */
+#define TILE_WIDTH 64
+#define TILE_HEIGHT 32
+#define TILE_SIZE (TILE_WIDTH * TILE_HEIGHT)
+#define TILE_GROUP_SIZE (4 * TILE_SIZE)
+
+/* get frame tile coordinate. XXX: nothing to be understood here, don't try. */
+static size_t
+tile_pos (size_t x, size_t y, size_t w, size_t h)
+{
+  size_t flim = x + (y & ~1) * w;
+
+  if (y & 1) {
+    flim += (x & ~3) + 2;
+  } else if ((h & 1) == 0 || y != (h - 1)) {
+    flim += (x + 2) & ~3;
+  }
+
+  return flim;
+}
+
 /* The weird handling of cropping, alignment and everything is taken from
  * platform/frameworks/media/libstagefright/colorconversion/ColorConversion.cpp
  */
@@ -976,6 +1002,87 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
       ret = TRUE;
       break;
     }
+    case COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka:{
+      gint width = self->width;
+      gint height = self->height;
+      gint src_stride = self->stride;
+      gint dest_luma_stride = GST_VIDEO_INFO_COMP_STRIDE (info, 0);
+      gint dest_chroma_stride = GST_VIDEO_INFO_COMP_STRIDE (info, 1);
+      guint8 *src = buf->data + buffer_info->offset;
+      guint8 *dest_luma =
+          GST_BUFFER_DATA (outbuf) + GST_VIDEO_INFO_COMP_OFFSET (info, 0);
+      guint8 *dest_chroma =
+          GST_BUFFER_DATA (outbuf) + GST_VIDEO_INFO_COMP_OFFSET (info, 1);
+      gint y;
+
+      const size_t tile_w = (width - 1) / TILE_WIDTH + 1;
+      const size_t tile_w_align = (tile_w + 1) & ~1;
+
+      const size_t tile_h_luma = (height - 1) / TILE_HEIGHT + 1;
+      const size_t tile_h_chroma = (height / 2 - 1) / TILE_HEIGHT + 1;
+
+      size_t luma_size = tile_w_align * tile_h_luma * TILE_SIZE;
+
+      if ((luma_size % TILE_GROUP_SIZE) != 0)
+        luma_size = (((luma_size - 1) / TILE_GROUP_SIZE) + 1) * TILE_GROUP_SIZE;
+
+      for (y = 0; y < tile_h_luma; y++) {
+        size_t row_width = width;
+        gint x;
+
+        for (x = 0; x < tile_w; x++) {
+          size_t tile_width = row_width;
+          size_t tile_height = height;
+          gint luma_idx;
+          gint chroma_idx;
+          /* luma source pointer for this tile */
+          const uint8_t *src_luma = src
+              + tile_pos (x, y, tile_w_align, tile_h_luma) * TILE_SIZE;
+
+          /* chroma source pointer for this tile */
+          const uint8_t *src_chroma = src + luma_size
+              + tile_pos (x, y / 2, tile_w_align, tile_h_chroma) * TILE_SIZE;
+          if (y & 1)
+            src_chroma += TILE_SIZE / 2;
+
+          /* account for right columns */
+          if (tile_width > TILE_WIDTH)
+            tile_width = TILE_WIDTH;
+
+          /* account for bottom rows */
+          if (tile_height > TILE_HEIGHT)
+            tile_height = TILE_HEIGHT;
+
+          /* dest luma memory index for this tile */
+          luma_idx = y * TILE_HEIGHT * dest_luma_stride + x * TILE_WIDTH;
+
+          /* dest chroma memory index for this tile */
+          /* XXX: remove divisions */
+          chroma_idx =
+              y * TILE_HEIGHT / 2 * dest_chroma_stride + x * TILE_WIDTH;
+
+          tile_height /= 2;     // we copy 2 luma lines at once
+          while (tile_height--) {
+            memcpy (dest_luma + luma_idx, src_luma, tile_width);
+            src_luma += TILE_WIDTH;
+            luma_idx += dest_luma_stride;
+
+            memcpy (dest_luma + luma_idx, src_luma, tile_width);
+            src_luma += TILE_WIDTH;
+            luma_idx += dest_luma_stride;
+
+            memcpy (dest_chroma + chroma_idx, src_chroma, tile_width);
+            src_chroma += TILE_WIDTH;
+            chroma_idx += dest_chroma_stride;
+          }
+          row_width -= TILE_WIDTH;
+        }
+        height -= TILE_HEIGHT;
+      }
+      ret = TRUE;
+      break;
+
+    }
     default:
       GST_ERROR_OBJECT (self, "Unsupported color format %d",
           self->color_format);