[FFmpeg-devel] [PATCH 5/6] avcodec/tiff_data: Avoid relocations for TiffGeoTagNameType

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Thu Mar 14 12:46:48 EET 2024


Andreas Rheinhardt:
> Instead store all the strings in one continugous string
> (with internal \0) and use offsets to access the actual
> substrings. This replaces the pointers to the strings
> and therefore avoids relocations (and on x64, it actually
> shrinks TiffGeoTagNameType by reusing padding to store
> the offset field).
> 
> This saves 720B of .data.rel.ro and 1080B of .rela.dyn
> (containing the relocation records) here while increasing
> .rodata by 384B.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
> ---
> I also have patches for the remaining tables, but am not
> satisfied with them yet.
> 
>  libavcodec/tiff.c      |  28 +++++----
>  libavcodec/tiff.h      |   5 --
>  libavcodec/tiff_data.h | 129 ++++++++++++++++++++++++-----------------
>  3 files changed, 92 insertions(+), 70 deletions(-)
> 
> diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
> index 15e5edd93b..004db89c6b 100644
> --- a/libavcodec/tiff.c
> +++ b/libavcodec/tiff.c
> @@ -139,27 +139,31 @@ static void free_geotags(TiffContext *const s)
>      s->geotag_count = 0;
>  }
>  
> -#define RET_GEOKEY(TYPE, array, element)\
> +static const char *get_geokey_name(int key)
> +{
> +#define RET_GEOKEY_STR(TYPE, array)\
>      if (key >= TIFF_##TYPE##_KEY_ID_OFFSET &&\
>          key - TIFF_##TYPE##_KEY_ID_OFFSET < FF_ARRAY_ELEMS(tiff_##array##_name_type_map))\
> -        return tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].element;
> +        return tiff_##array##_name_type_string + tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].offset;
>  
> -static const char *get_geokey_name(int key)
> -{
> -    RET_GEOKEY(VERT, vert, name);
> -    RET_GEOKEY(PROJ, proj, name);
> -    RET_GEOKEY(GEOG, geog, name);
> -    RET_GEOKEY(CONF, conf, name);
> +    RET_GEOKEY_STR(VERT, vert);
> +    RET_GEOKEY_STR(PROJ, proj);
> +    RET_GEOKEY_STR(GEOG, geog);
> +    RET_GEOKEY_STR(CONF, conf);
>  
>      return NULL;
>  }
>  
>  static int get_geokey_type(int key)
>  {
> -    RET_GEOKEY(VERT, vert, type);
> -    RET_GEOKEY(PROJ, proj, type);
> -    RET_GEOKEY(GEOG, geog, type);
> -    RET_GEOKEY(CONF, conf, type);
> +#define RET_GEOKEY_TYPE(TYPE, array)\
> +    if (key >= TIFF_##TYPE##_KEY_ID_OFFSET &&\
> +        key - TIFF_##TYPE##_KEY_ID_OFFSET < FF_ARRAY_ELEMS(tiff_##array##_name_type_map))\
> +        return tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].type;
> +    RET_GEOKEY_TYPE(VERT, vert);
> +    RET_GEOKEY_TYPE(PROJ, proj);
> +    RET_GEOKEY_TYPE(GEOG, geog);
> +    RET_GEOKEY_TYPE(CONF, conf);
>  
>      return AVERROR_INVALIDDATA;
>  }
> diff --git a/libavcodec/tiff.h b/libavcodec/tiff.h
> index 2dd21dea52..12afcfa6e5 100644
> --- a/libavcodec/tiff.h
> +++ b/libavcodec/tiff.h
> @@ -222,9 +222,4 @@ typedef struct TiffGeoTagKeyName {
>      const char *const name;
>  } TiffGeoTagKeyName;
>  
> -typedef struct TiffGeoTagNameType {
> -    const char *const name;
> -    const enum TiffGeoTagType type;
> -} TiffGeoTagNameType;
> -
>  #endif /* AVCODEC_TIFF_H */
> diff --git a/libavcodec/tiff_data.h b/libavcodec/tiff_data.h
> index 9b123ca8df..9ed46d31af 100644
> --- a/libavcodec/tiff_data.h
> +++ b/libavcodec/tiff_data.h
> @@ -32,66 +32,89 @@
>  
>  #include "tiff.h"
>  
> +typedef struct TiffGeoTagNameType {
> +    enum TiffGeoTagType type;
> +    unsigned offset;
> +} TiffGeoTagNameType;
> +
>  #define TIFF_CONF_KEY_ID_OFFSET 1024
> -static const TiffGeoTagNameType tiff_conf_name_type_map[] = {
> -    {"GTModelTypeGeoKey",              GEOTIFF_SHORT },
> -    {"GTRasterTypeGeoKey",             GEOTIFF_SHORT },
> -    {"GTCitationGeoKey",               GEOTIFF_STRING}
> -};
> +#define CONF_NAME_TYPE_MAP(KEY)                 \
> +    KEY(GTModelTypeGeoKey,              SHORT ) \
> +    KEY(GTRasterTypeGeoKey,             SHORT ) \
> +    KEY(GTCitationGeoKey,               STRING) \
>  
>  #define TIFF_GEOG_KEY_ID_OFFSET 2048
> -static const TiffGeoTagNameType tiff_geog_name_type_map[] = {
> -    {"GeographicTypeGeoKey",           GEOTIFF_SHORT },
> -    {"GeogCitationGeoKey",             GEOTIFF_STRING},
> -    {"GeogGeodeticDatumGeoKey",        GEOTIFF_SHORT },
> -    {"GeogPrimeMeridianGeoKey",        GEOTIFF_SHORT },
> -    {"GeogLinearUnitsGeoKey",          GEOTIFF_SHORT },
> -    {"GeogLinearUnitSizeGeoKey",       GEOTIFF_DOUBLE},
> -    {"GeogAngularUnitsGeoKey",         GEOTIFF_SHORT },
> -    {"GeogAngularUnitSizeGeoKey",      GEOTIFF_DOUBLE},
> -    {"GeogEllipsoidGeoKey",            GEOTIFF_SHORT },
> -    {"GeogSemiMajorAxisGeoKey",        GEOTIFF_DOUBLE},
> -    {"GeogSemiMinorAxisGeoKey",        GEOTIFF_DOUBLE},
> -    {"GeogInvFlatteningGeoKey",        GEOTIFF_DOUBLE},
> -    {"GeogAzimuthUnitsGeoKey",         GEOTIFF_SHORT },
> -    {"GeogPrimeMeridianLongGeoKey",    GEOTIFF_DOUBLE}
> -};
> +#define GEOG_NAME_TYPE_MAP(KEY)                 \
> +    KEY(GeographicTypeGeoKey,           SHORT ) \
> +    KEY(GeogCitationGeoKey,             STRING) \
> +    KEY(GeogGeodeticDatumGeoKey,        SHORT ) \
> +    KEY(GeogPrimeMeridianGeoKey,        SHORT ) \
> +    KEY(GeogLinearUnitsGeoKey,          SHORT ) \
> +    KEY(GeogLinearUnitSizeGeoKey,       DOUBLE) \
> +    KEY(GeogAngularUnitsGeoKey,         SHORT ) \
> +    KEY(GeogAngularUnitSizeGeoKey,      DOUBLE) \
> +    KEY(GeogEllipsoidGeoKey,            SHORT ) \
> +    KEY(GeogSemiMajorAxisGeoKey,        DOUBLE) \
> +    KEY(GeogSemiMinorAxisGeoKey,        DOUBLE) \
> +    KEY(GeogInvFlatteningGeoKey,        DOUBLE) \
> +    KEY(GeogAzimuthUnitsGeoKey,         SHORT ) \
> +    KEY(GeogPrimeMeridianLongGeoKey,    DOUBLE) \
>  
>  #define TIFF_PROJ_KEY_ID_OFFSET 3072
> -static const TiffGeoTagNameType tiff_proj_name_type_map[] = {
> -    {"ProjectedCSTypeGeoKey",          GEOTIFF_SHORT },
> -    {"PCSCitationGeoKey",              GEOTIFF_STRING},
> -    {"ProjectionGeoKey",               GEOTIFF_SHORT },
> -    {"ProjCoordTransGeoKey",           GEOTIFF_SHORT },
> -    {"ProjLinearUnitsGeoKey",          GEOTIFF_SHORT },
> -    {"ProjLinearUnitSizeGeoKey",       GEOTIFF_DOUBLE},
> -    {"ProjStdParallel1GeoKey",         GEOTIFF_DOUBLE},
> -    {"ProjStdParallel2GeoKey",         GEOTIFF_DOUBLE},
> -    {"ProjNatOriginLongGeoKey",        GEOTIFF_DOUBLE},
> -    {"ProjNatOriginLatGeoKey",         GEOTIFF_DOUBLE},
> -    {"ProjFalseEastingGeoKey",         GEOTIFF_DOUBLE},
> -    {"ProjFalseNorthingGeoKey",        GEOTIFF_DOUBLE},
> -    {"ProjFalseOriginLongGeoKey",      GEOTIFF_DOUBLE},
> -    {"ProjFalseOriginLatGeoKey",       GEOTIFF_DOUBLE},
> -    {"ProjFalseOriginEastingGeoKey",   GEOTIFF_DOUBLE},
> -    {"ProjFalseOriginNorthingGeoKey",  GEOTIFF_DOUBLE},
> -    {"ProjCenterLongGeoKey",           GEOTIFF_DOUBLE},
> -    {"ProjCenterLatGeoKey",            GEOTIFF_DOUBLE},
> -    {"ProjCenterEastingGeoKey",        GEOTIFF_DOUBLE},
> -    {"ProjCenterNorthingGeoKey",       GEOTIFF_DOUBLE},
> -    {"ProjScaleAtNatOriginGeoKey",     GEOTIFF_DOUBLE},
> -    {"ProjScaleAtCenterGeoKey",        GEOTIFF_DOUBLE},
> -    {"ProjAzimuthAngleGeoKey",         GEOTIFF_DOUBLE},
> -    {"ProjStraightVertPoleLongGeoKey", GEOTIFF_DOUBLE}
> -};
> +#define PROJ_NAME_TYPE_MAP(KEY)                 \
> +    KEY(ProjectedCSTypeGeoKey,          SHORT ) \
> +    KEY(PCSCitationGeoKey,              STRING) \
> +    KEY(ProjectionGeoKey,               SHORT ) \
> +    KEY(ProjCoordTransGeoKey,           SHORT ) \
> +    KEY(ProjLinearUnitsGeoKey,          SHORT ) \
> +    KEY(ProjLinearUnitSizeGeoKey,       DOUBLE) \
> +    KEY(ProjStdParallel1GeoKey,         DOUBLE) \
> +    KEY(ProjStdParallel2GeoKey,         DOUBLE) \
> +    KEY(ProjNatOriginLongGeoKey,        DOUBLE) \
> +    KEY(ProjNatOriginLatGeoKey,         DOUBLE) \
> +    KEY(ProjFalseEastingGeoKey,         DOUBLE) \
> +    KEY(ProjFalseNorthingGeoKey,        DOUBLE) \
> +    KEY(ProjFalseOriginLongGeoKey,      DOUBLE) \
> +    KEY(ProjFalseOriginLatGeoKey,       DOUBLE) \
> +    KEY(ProjFalseOriginEastingGeoKey,   DOUBLE) \
> +    KEY(ProjFalseOriginNorthingGeoKey,  DOUBLE) \
> +    KEY(ProjCenterLongGeoKey,           DOUBLE) \
> +    KEY(ProjCenterLatGeoKey,            DOUBLE) \
> +    KEY(ProjCenterEastingGeoKey,        DOUBLE) \
> +    KEY(ProjCenterNorthingGeoKey,       DOUBLE) \
> +    KEY(ProjScaleAtNatOriginGeoKey,     DOUBLE) \
> +    KEY(ProjScaleAtCenterGeoKey,        DOUBLE) \
> +    KEY(ProjAzimuthAngleGeoKey,         DOUBLE) \
> +    KEY(ProjStraightVertPoleLongGeoKey, DOUBLE) \
>  
>  #define TIFF_VERT_KEY_ID_OFFSET 4096
> -static const TiffGeoTagNameType tiff_vert_name_type_map[] = {
> -    {"VerticalCSTypeGeoKey",           GEOTIFF_SHORT },
> -    {"VerticalCitationGeoKey",         GEOTIFF_STRING},
> -    {"VerticalDatumGeoKey",            GEOTIFF_SHORT },
> -    {"VerticalUnitsGeoKey",            GEOTIFF_SHORT }
> -};
> +#define VERT_NAME_TYPE_MAP(KEY)                 \
> +    KEY(VerticalCSTypeGeoKey,           SHORT ) \
> +    KEY(VerticalCitationGeoKey,         STRING) \
> +    KEY(VerticalDatumGeoKey,            SHORT ) \
> +    KEY(VerticalUnitsGeoKey,            SHORT ) \
> +
> +#define ADD_OFFSET(NAME, TYPE)                          \
> +    NAME ## _OFFSET,                                    \
> +    NAME ## _END = NAME ## _OFFSET + sizeof(#NAME) - 1, \
> +
> +#define STRING(NAME, TYPE) #NAME "\0"
> +
> +#define ENTRY(NAME, TYPE) { .type = GEOTIFF_ ## TYPE, .offset = NAME ## _OFFSET },
> +#define NAME_TYPE_MAP(NAME, name) \
> +    enum { \
> +        NAME ## _NAME_TYPE_MAP(ADD_OFFSET) \
> +    }; \
> +    static const TiffGeoTagNameType tiff_ ## name ## _name_type_map[] = { \
> +        NAME ## _NAME_TYPE_MAP(ENTRY) \
> +    }; \
> +    static const char *const tiff_ ## name ## _name_type_string = \
> +        NAME ## _NAME_TYPE_MAP(STRING)
> +
> +NAME_TYPE_MAP(CONF, conf);
> +NAME_TYPE_MAP(GEOG, geog);
> +NAME_TYPE_MAP(PROJ, proj);
> +NAME_TYPE_MAP(VERT, vert);
>  
>  #define TIFF_GEO_KEY_UNDEFINED    0
>  #define TIFF_GEO_KEY_USER_DEFINED 32767

Will apply the two remaining patches of this patchset tonight unless
there are objections.

- Andreas



More information about the ffmpeg-devel mailing list