[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