/** * 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; }
/** * 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; }