Example #1
0
/**
 * gst_tag_freeform_string_to_utf8:
 * @data: string data
 * @size: length of string data, or -1 if the string is NUL-terminated
 * @env_vars: a NULL-terminated string array of environment variable names,
 *            or NULL
 *
 * Convenience function to read a string with unknown character encoding. If
 * the string is already in UTF-8 encoding, it will be returned right away.
 * If not it tries to detect byte-order-mark for UTF-16/32 cases and use that.
 * Otherwise, the environment will be searched for a number of environment
 * variables (whose names are specified in the NULL-terminated string array
 * @env_vars) containing a list of character encodings to try/use. If none
 * are specified, the current locale will be tried. If that also doesn't work,
 * WINDOWS-1252/ISO-8859-1 is assumed (which will almost always succeed).
 *
 * Returns: a newly-allocated string in UTF-8 encoding, or NULL
 */
gchar *
gst_tag_freeform_string_to_utf8 (const gchar * data, gint size,
    const gchar ** env_vars)
{
  const gchar *cur_loc = NULL;

  gsize bytes_read;

  gchar *utf8 = NULL;

  g_return_val_if_fail (data != NULL, NULL);

  if (size < 0)
    size = strlen (data);

  /* chop off trailing string terminators to make sure utf8_validate doesn't
   * get to see them (since that would make the utf8 check fail) */
  while (size > 0 && data[size - 1] == '\0')
    --size;

  /* Should we try the charsets specified
   * via environment variables FIRST ? */
  if (g_utf8_validate (data, size, NULL)) {
    utf8 = g_strndup (data, size);
    GST_LOG ("String '%s' is valid UTF-8 already", utf8);
    goto beach;
  }

  /* check for and use byte-order-mark for UTF-16/32 cases */
  if (size >= 2) {
    const gchar *c = NULL;
    gint prefix, ssize;

    if (size >= 4) {
      prefix = 4;
      ssize = GST_ROUND_DOWN_4 (size - 4);
      switch (GST_READ_UINT32_BE (data)) {
        case 0x0000FEFF:
          c = "UTF-32BE";
          break;
        case 0xFFFE0000:
          c = "UTF-32LE";
          break;
        default:
          break;
      }
    }
    if (!c) {
      prefix = 2;
      ssize = GST_ROUND_DOWN_2 (size - 2);
      switch (GST_READ_UINT16_BE (data)) {
        case 0xFEFF:
          c = "UTF-16BE";
          break;
        case 0xFFFE:
          c = "UTF-16LE";
          break;
        default:
          break;
      }
    }
    if (c) {
      GST_LOG ("Trying to convert freeform string to UTF-8 from '%s'", c);
      if ((utf8 =
              g_convert (data + prefix, ssize, "UTF-8", c, &bytes_read, NULL,
                  NULL))) {
        if (bytes_read == ssize)
          goto beach;
        g_free (utf8);
        utf8 = NULL;
      }
    }
  }

  while (env_vars && *env_vars != NULL) {
    const gchar *env = NULL;

    /* Try charsets specified via the environment */
    env = g_getenv (*env_vars);
    if (env != NULL && *env != '\0') {
      gchar **c, **csets;

      csets = g_strsplit (env, G_SEARCHPATH_SEPARATOR_S, -1);

      for (c = csets; c && *c; ++c) {
        GST_LOG ("Trying to convert freeform string to UTF-8 from '%s'", *c);
        if ((utf8 =
                g_convert (data, size, "UTF-8", *c, &bytes_read, NULL, NULL))) {
          if (bytes_read == size) {
            g_strfreev (csets);
            goto beach;
          }
          g_free (utf8);
          utf8 = NULL;
        }
      }

      g_strfreev (csets);
    }
    ++env_vars;
  }

  /* Try current locale (if not UTF-8) */
  if (!g_get_charset (&cur_loc)) {
    GST_LOG ("Trying to convert freeform string using locale ('%s')", cur_loc);
    if ((utf8 = g_locale_to_utf8 (data, size, &bytes_read, NULL, NULL))) {
      if (bytes_read == size) {
        goto beach;
      }
      g_free (utf8);
      utf8 = NULL;
    }
  }

  /* Try Windows-1252 (which is a superset of ISO 8859-1 that uses a control
   * character range in ISO 8859-1 for more printable characters) */
  {
    GError *err = NULL;

    GST_LOG ("Trying to convert freeform string using Windows-1252/ISO-8859-1 "
        "fallback");
    utf8 = g_convert (data, size, "UTF-8", "WINDOWS-1252", &bytes_read, NULL,
        &err);
    if (err != NULL) {
      /* fallback in case iconv implementation doesn't support windows-1252
       * for some reason */
      if (err->code == G_CONVERT_ERROR_NO_CONVERSION) {
        g_free (utf8);
        utf8 = g_convert (data, size, "UTF-8", "ISO-8859-1", &bytes_read,
            NULL, NULL);
      }
      g_error_free (err);
    }

    if (utf8 != NULL && bytes_read == size)
      goto beach;
  }

  g_free (utf8);
  return NULL;

beach:

  g_strchomp (utf8);
  if (utf8 && utf8[0] != '\0') {
    GST_LOG ("Returning '%s'", utf8);
    return utf8;
  }

  g_free (utf8);
  return NULL;
}
Example #2
0
/**
 * gst_video_tile_get_index:
 * @mode: a #GstVideoTileMode
 * @x: x coordinate
 * @y: y coordinate
 * @x_tiles: number of horizintal tiles
 * @y_tiles: number of vertical tiles
 *
 * Get the tile index of the tile at coordinates @x and @y in the tiled
 * image of @x_tiles by @y_tiles.
 *
 * Use this method when @mode is of type %GST_VIDEO_TILE_TYPE_INDEXED.
 *
 * Returns: the index of the tile at @x and @y in the tiled image of
 *   @x_tiles by @y_tiles.
 *
 * Since: 1.4
 */
guint
gst_video_tile_get_index (GstVideoTileMode mode, gint x, gint y,
    gint x_tiles, gint y_tiles)
{
  gsize offset;

  g_return_val_if_fail (GST_VIDEO_TILE_MODE_IS_INDEXED (mode), 0);

  switch (mode) {
    case GST_VIDEO_TILE_MODE_ZFLIPZ_2X2:
      /* Due to the zigzag pattern we know that tiles are numbered like:
       * (see http://linuxtv.org/downloads/v4l-dvb-apis/re31.html)
       *
       *         |             Column (x)
       *         |   0    1    2    3    4    5    6    7
       *  -------|---------------------------------------
       *       0 |   0    1    6    7    8    9   14   15
       *    R  1 |   2    3    4    5   10   11   12   13
       *    o  2 |  16   17   22   23   24   25   30   31
       *    w  3 |  18   19   20   21   26   27   28   29
       *       4 |  32   33   38   39   40   41   46   47
       *   (y) 5 |  34   35   36   37   42   43   44   45
       *       6 |  48   49   50   51   52   53   54   55
       *
       * From this we can see that:
       *
       * For even rows:
       * - The first block in a row is always mapped to memory block 'y * width'.
       * - For all even rows, except for the last one when 'y' is odd, from the first
       *   block number an offset is then added to obtain the block number for
       *   the other blocks in the row. The offset is 'x' plus the corresponding
       *   number in the series [0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, ...], which can be
       *   expressed as 'GST_ROUND_DOWN_4 (x + 2)'.
       *       f(x,y,width,height) = y * width + x + GST_ROUND_DOWN_4 (x + 2)
       *
       * - For the last row when 'y' is odd the offset is simply 'x'.
       *       f(x,y,width,height) = y * width + x
       * - Note that 'y' is even, so 'GST_ROUNDOWN_2 (y) == y' in this case
       *
       *  For odd rows:
       * - The first block in the row is always mapped to memory block
       *   'GST_ROUND_DOWN_2(y) * width + 2'.
       * - From the first block number an offset is then added to obtain the block
       *   number for the other blocks in the row. The offset is 'x' plus the
       *   corresponding number in the series [0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, ...],
       *   which can be  expressed as GST_ROUND_DOWN_4 (x).
       *       f(x,y,width,height) = GST_ROUND_DOWN_2 (y) * width + bx 2 + GST_ROUND_DOWN_4 (x)
       */
      /* Common to all cases */
      offset = GST_ROUND_DOWN_2 (y) * x_tiles + x;

      if (y & 1) {
        /* For odd row */
        offset += 2 + GST_ROUND_DOWN_4 (x);
      } else if ((y_tiles & 1) == 0 || y != (y_tiles - 1)) {
        /* For even row except for the last row when odd height */
        offset += GST_ROUND_DOWN_4 (x + 2);
      }
      break;
    default:
      offset = 0;
      break;
  }
  return offset;
}