[FFmpeg-devel] [PATCH 1/2 v2] avutil: add a Tile Grid API

James Almer jamrial at gmail.com
Sun Jan 21 00:04:06 EET 2024


This includes a struct and helpers. It will be used to support container level
cropping and tiled image formats, but should be generic enough for general
usage.

Signed-off-by: James Almer <jamrial at gmail.com>
---
Extended to include fields used for cropping. Should make the struct reusable
even for non tiled images, e.g. setting both rows and tiles to 1, in which case
tile width and height would become analogous to coded_{witdh,height}.

 libavutil/Makefile |   2 +
 libavutil/tile.c   |  81 +++++++++++++++++++
 libavutil/tile.h   | 188 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 271 insertions(+)
 create mode 100644 libavutil/tile.c
 create mode 100644 libavutil/tile.h

diff --git a/libavutil/Makefile b/libavutil/Makefile
index e7709b97d0..380d706cfe 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -82,6 +82,7 @@ HEADERS = adler32.h                                                     \
           spherical.h                                                   \
           stereo3d.h                                                    \
           threadmessage.h                                               \
+          tile.h                                                        \
           time.h                                                        \
           timecode.h                                                    \
           timestamp.h                                                   \
@@ -172,6 +173,7 @@ OBJS = adler32.o                                                        \
        spherical.o                                                      \
        stereo3d.o                                                       \
        threadmessage.o                                                  \
+       tile.o                                                           \
        time.o                                                           \
        timecode.o                                                       \
        tree.o                                                           \
diff --git a/libavutil/tile.c b/libavutil/tile.c
new file mode 100644
index 0000000000..de59ba4bab
--- /dev/null
+++ b/libavutil/tile.c
@@ -0,0 +1,81 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <limits.h>
+
+#include "log.h"
+#include "mem.h"
+#include "opt.h"
+#include "tile.h"
+
+#define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
+#define OFFSET(x) offsetof(AVTileGrid, x)
+static const AVOption tile_grid_options[] = {
+    { "type", NULL, OFFSET(type), AV_OPT_TYPE_INT,
+            { .i64 = AV_TILE_DIMENSION_TYPE_UNIFORM },
+            AV_TILE_DIMENSION_TYPE_UNIFORM, AV_TILE_DIMENSION_TYPE_VARIABLE, FLAGS, "type" },
+        { "uniform",  NULL, 0, AV_OPT_TYPE_CONST,
+                   { .i64 = AV_TILE_DIMENSION_TYPE_UNIFORM },  .unit = "type" },
+        { "variable", NULL, 0, AV_OPT_TYPE_CONST,
+                   { .i64 = AV_TILE_DIMENSION_TYPE_VARIABLE }, .unit = "type" },
+    { "tile_rows", NULL, OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS },
+    { "tile_cols", NULL, OFFSET(tile_cols), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS },
+    { "horizontal_offset", NULL, OFFSET(horizontal_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
+    { "vertical_offset", NULL, OFFSET(vertical_offset),     AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
+    { "output_size", "size of the output image", OFFSET(output_width), AV_OPT_TYPE_IMAGE_SIZE,
+        { .str = NULL }, 0, INT_MAX, FLAGS },
+    { NULL },
+};
+
+static const AVClass tile_grid_class = {
+    .class_name          = "AVTileGrid",
+    .version             = LIBAVUTIL_VERSION_INT,
+    .option              = tile_grid_options,
+};
+
+const AVClass *av_tile_grid_get_class(void)
+{
+    return &tile_grid_class;
+}
+
+AVTileGrid *av_tile_grid_alloc(void)
+{
+    AVTileGrid *tile_grid = av_mallocz(sizeof(AVTileGrid));
+
+    if (tile_grid) {
+        tile_grid->av_class = &tile_grid_class;
+        av_opt_set_defaults(tile_grid);
+    }
+
+    return tile_grid;
+}
+
+void av_tile_grid_free(AVTileGrid **ptile_grid)
+{
+    AVTileGrid *tile_grid = *ptile_grid;
+
+    if (!tile_grid)
+        return;
+
+    if (tile_grid->type == AV_TILE_DIMENSION_TYPE_VARIABLE) {
+        av_freep(&tile_grid->w.tile_widths);
+        av_freep(&tile_grid->h.tile_heights);
+    }
+    av_freep(ptile_grid);
+}
diff --git a/libavutil/tile.h b/libavutil/tile.h
new file mode 100644
index 0000000000..7e68dc7bd5
--- /dev/null
+++ b/libavutil/tile.h
@@ -0,0 +1,188 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_TILE_H
+#define AVUTIL_TILE_H
+
+#include <stdint.h>
+
+#include "log.h"
+
+/**
+ * @defgroup lavu_tile_grid Tile grid paremeters
+ * @{
+ */
+
+enum AVTileGridType {
+    AV_TILE_DIMENSION_TYPE_UNIFORM,  ///< All tiles have the same size
+    AV_TILE_DIMENSION_TYPE_VARIABLE, ///< Tiles may have variable size
+};
+
+/**
+ * AVTileGrid holds information on how to combine several independent images in a
+ * single grid for presentation.
+ *
+ * It must be allocated by av_tile_grid_alloc(), and its size is not a part of the
+ * ABI. No new fields may be added to this struct without a major version bump,
+ * except for new elements of the unions w and h fitting in sizeof(intptr_t).
+ */
+typedef struct AVTileGrid {
+    const AVClass *av_class;
+
+    /**
+     * Amount of rows in the grid.
+     *
+     * Must be > 0.
+     */
+    int tile_rows;
+    /**
+     * Amount of columns in the grid.
+     *
+     * Must be > 0.
+     */
+    int tile_cols;
+
+    enum AVTileGridType type;
+
+    /**
+     * Tile witdh paremeters
+     */
+    union {
+        /**
+         * Width of every tile.
+         * This member must be used when the @ref type is AV_TILE_DIMENSION_TYPE_UNIFORM.
+         */
+        intptr_t tile_width;
+        /**
+         * A @ref tile_rows * @ref tile_cols sized array of width values for each
+         * tile in the grid, in row major order.
+         * This member must be used when the @ref type is AV_TILE_DIMENSION_TYPE_VARIABLE.
+         *
+         * Must be allocated with the av_malloc() family of functions, and will be
+         * freed by av_tile_grid_free().
+         */
+        int *tile_widths;
+    } w;
+
+    /**
+     * Tile height paremeters
+     */
+    union {
+        /**
+         * Height of every tile.
+         *
+         * This member must be used when the @ref type is AV_TILE_DIMENSION_TYPE_UNIFORM.
+         */
+        intptr_t tile_height;
+        /**
+         * A @ref tile_rows * @ref tile_cols sized array of height values for each
+         * tile in the grid, in row major order.
+         *
+         * This member must be used when the @ref type is AV_TILE_DIMENSION_TYPE_VARIABLE.
+         * Must be allocated with the av_malloc() family of functions, and will be
+         * freed by av_tile_grid_free().
+         */
+        int *tile_heights;
+    } h;
+
+    /**
+     * Offset in pixels from the left edge of the grid where the actual image
+     * meant for presentation starts.
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_UNIFORM, this field must be >= 0
+     * and <= ((@ref tile_width * @ref tile_cols) - @ref output_width).
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_VARIABLE, this field must be >= 0
+     * and <= the sum of all values in the tile_widths array minus
+     * @ref output_width.
+     */
+    int horizontal_offset;
+    /**
+     * Offset in pixels from the top edge of the grid where the actual image meant
+     * for presentation starts.
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_UNIFORM, this field must be >= 0
+     * and <= ((@ref tile_height * @ref tile_rows) - @ref output_height).
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_VARIABLE, this field must be >= 0
+     * and <= the sum of all values in the tile_heights array minus
+     * @ref output_height.
+     */
+    int vertical_offset;
+
+    /**
+     * Width of the final image for presentation.
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_UNIFORM, this field must be > 0
+     * and <= (@ref tile_width * @ref tile_cols) - @ref horizontal_offset.
+     * When it's not equal to tile_width * tile_cols, the result of
+     * (@ref tile_width * @ref tile_cols) - output_width - @ref horizontal_offset
+     * is the amount of pixels to be cropped from the right edge of the final
+     * image before presentation.
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_VARIABLE, this field must be > 0
+     * and <= the sum of all values in the tile_widths array minus
+     * @ref horizontal_offset.
+     * When it's not equal to the sum of all values in the tile_widths array,
+     * the result of said sum minus output_width minus @ref horizontal_offset is
+     * the amount of pixels to be cropped from the right edge of the final image
+     * before presentation.
+     */
+    int output_width;
+    /**
+     * Height of the final image for presentation.
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_UNIFORM, this field must be > 0
+     * and <= (@ref tile_height * @ref tile_rows) - @ref vertical_offset.
+     * When it's not equal to tile_height * tile_rows, the result of
+     * (@ref tile_height * @ref tile_rows) - output_height - @ref vertical_offset
+     * is the amount of pixels to be cropped from the bottom edge of the final
+     * image before presentation.
+     *
+     * When @ref type is AV_TILE_DIMENSION_TYPE_VARIABLE, this field must be > 0
+     * and <= the sum of all values in the tile_heights array minus
+     * @ref vertical_offset.
+     * When it's not equal to the sum of all values in the tile_heights array,
+     * the result of said sum minus output_height minus @ref vertical_offset is
+     * the amount of pixels to be cropped from the bottom edge of the final image
+     * before presentation.
+     */
+    int output_height;
+} AVTileGrid;
+
+const AVClass *av_tile_grid_get_class(void);
+
+/**
+ * Allocates a AVTileGrid, and initializes its fields with default values.
+ * Must be freed with av_tile_grid_free().
+ */
+AVTileGrid *av_tile_grid_alloc(void);
+
+/**
+ * Free an AVTileGrid and all its contents.
+ *
+ * @param tile_grid pointer to pointer to an allocated AVTileGrid.
+ *                  upon return, *tile_grid will be set to NULL.
+ */
+void av_tile_grid_free(AVTileGrid **tile_grid);
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_TILE_H */
-- 
2.43.0



More information about the ffmpeg-devel mailing list