diff options
Diffstat (limited to '')
62 files changed, 2725 insertions, 2841 deletions
diff --git a/media/ffvpx/libavutil/aarch64/cpu.c b/media/ffvpx/libavutil/aarch64/cpu.c index f27fef3992..7a05391343 100644 --- a/media/ffvpx/libavutil/aarch64/cpu.c +++ b/media/ffvpx/libavutil/aarch64/cpu.c @@ -24,34 +24,20 @@ #include <stdint.h> #include <sys/auxv.h> -#define get_cpu_feature_reg(reg, val) \ - __asm__("mrs %0, " #reg : "=r" (val)) +#define HWCAP_AARCH64_ASIMDDP (1 << 20) +#define HWCAP2_AARCH64_I8MM (1 << 13) static int detect_flags(void) { int flags = 0; -#if defined(HWCAP_CPUID) && HAVE_INLINE_ASM unsigned long hwcap = getauxval(AT_HWCAP); - // We can check for DOTPROD and I8MM using HWCAP_ASIMDDP and - // HWCAP2_I8MM too, avoiding to read the CPUID registers (which triggers - // a trap, handled by the kernel). However the HWCAP_* defines for these - // extensions are added much later than HWCAP_CPUID, so the userland - // headers might lack support for them even if the binary later is run - // on hardware that does support it (and where the kernel might support - // HWCAP_CPUID). - // See https://www.kernel.org/doc/html/latest/arm64/cpu-feature-registers.html - if (hwcap & HWCAP_CPUID) { - uint64_t tmp; - - get_cpu_feature_reg(ID_AA64ISAR0_EL1, tmp); - if (((tmp >> 44) & 0xf) == 0x1) - flags |= AV_CPU_FLAG_DOTPROD; - get_cpu_feature_reg(ID_AA64ISAR1_EL1, tmp); - if (((tmp >> 52) & 0xf) == 0x1) - flags |= AV_CPU_FLAG_I8MM; - } -#endif + unsigned long hwcap2 = getauxval(AT_HWCAP2); + + if (hwcap & HWCAP_AARCH64_ASIMDDP) + flags |= AV_CPU_FLAG_DOTPROD; + if (hwcap2 & HWCAP2_AARCH64_I8MM) + flags |= AV_CPU_FLAG_I8MM; return flags; } diff --git a/media/ffvpx/libavutil/arm/float_dsp_init_vfp.c b/media/ffvpx/libavutil/arm/float_dsp_init_vfp.c index 05873e7e37..6d6237aae8 100644 --- a/media/ffvpx/libavutil/arm/float_dsp_init_vfp.c +++ b/media/ffvpx/libavutil/arm/float_dsp_init_vfp.c @@ -32,7 +32,7 @@ void ff_vector_fmul_window_vfp(float *dst, const float *src0, void ff_vector_fmul_reverse_vfp(float *dst, const float *src0, const float *src1, int len); -void ff_butterflies_float_vfp(float *av_restrict v1, float *av_restrict v2, int len); +void ff_butterflies_float_vfp(float *restrict v1, float *restrict v2, int len); av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags) { diff --git a/media/ffvpx/libavutil/avstring.c b/media/ffvpx/libavutil/avstring.c index 8751ce5576..2071dd36a5 100644 --- a/media/ffvpx/libavutil/avstring.c +++ b/media/ffvpx/libavutil/avstring.c @@ -345,7 +345,7 @@ int av_escape(char **dst, const char *src, const char *special_chars, int av_match_name(const char *name, const char *names) { const char *p; - int len, namelen; + size_t len, namelen; if (!name || !names) return 0; diff --git a/media/ffvpx/libavutil/avutil.h b/media/ffvpx/libavutil/avutil.h index a362c8baa8..d2900dcb48 100644 --- a/media/ffvpx/libavutil/avutil.h +++ b/media/ffvpx/libavutil/avutil.h @@ -335,19 +335,6 @@ unsigned av_int_list_length_for_size(unsigned elsize, #define av_int_list_length(list, term) \ av_int_list_length_for_size(sizeof(*(list)), list, term) -#if FF_API_AV_FOPEN_UTF8 -/** - * Open a file using a UTF-8 filename. - * The API of this function matches POSIX fopen(), errors are returned through - * errno. - * @deprecated Avoid using it, as on Windows, the FILE* allocated by this - * function may be allocated with a different CRT than the caller - * who uses the FILE*. No replacement provided in public API. - */ -attribute_deprecated -FILE *av_fopen_utf8(const char *path, const char *mode); -#endif - /** * Return the fractional representation of the internal time base. */ diff --git a/media/ffvpx/libavutil/avutil.symbols b/media/ffvpx/libavutil/avutil.symbols index 5ee7afb855..75f5625d98 100644 --- a/media/ffvpx/libavutil/avutil.symbols +++ b/media/ffvpx/libavutil/avutil.symbols @@ -8,7 +8,6 @@ av_base64_decode av_base64_encode #endif av_bprint_append_data -av_bprint_channel_layout av_bprint_chars av_bprint_clear av_bprint_escape @@ -39,7 +38,6 @@ av_channel_layout_compare av_channel_layout_copy av_channel_layout_default av_channel_layout_describe -av_channel_layout_extract_channel av_channel_layout_from_mask av_channel_layout_from_mask av_channel_layout_uninit @@ -52,9 +50,7 @@ av_color_space_name av_color_transfer_name av_compare_mod av_compare_ts -#ifndef MOZ_FFVPX_AUDIOONLY av_content_light_metadata_create_side_data -#endif av_cpu_count av_crc av_crc_get_table @@ -88,26 +84,13 @@ av_expr_parse_and_eval av_fast_malloc av_fast_mallocz av_fast_realloc -av_fifo_alloc av_fifo_alloc2 -av_fifo_alloc_array av_fifo_can_read av_fifo_can_write -av_fifo_drain av_fifo_drain2 -av_fifo_free -av_fifo_freep av_fifo_freep2 -av_fifo_generic_peek -av_fifo_generic_read -av_fifo_generic_write -av_fifo_grow av_fifo_peek -av_fifo_realloc2 av_fifo_read -av_fifo_reset -av_fifo_size -av_fifo_space av_fifo_write av_find_best_pix_fmt_of_2 av_find_info_tag @@ -122,6 +105,8 @@ av_frame_apply_cropping av_frame_clone av_frame_copy av_frame_copy_props +av_frame_side_data_free +av_frame_side_data_get_c av_frame_free av_frame_get_buffer av_frame_get_plane_buffer @@ -142,14 +127,7 @@ av_gcd av_get_alt_sample_fmt av_get_bits_per_pixel av_get_bytes_per_sample -av_get_channel_description -av_get_channel_layout -av_get_channel_layout_channel_index -av_get_channel_layout_nb_channels -av_get_channel_layout_string -av_get_channel_name av_get_cpu_flags -av_get_default_channel_layout av_get_known_color_name av_get_media_type_string av_get_packed_sample_fmt @@ -162,7 +140,6 @@ av_get_pix_fmt_string av_get_planar_sample_fmt av_get_sample_fmt av_get_sample_fmt_string -av_get_standard_channel_layout av_get_time_base_q av_get_token av_gettime @@ -201,9 +178,7 @@ av_log_set_flags av_log_set_level av_mallocz av_malloc -#ifndef MOZ_FFVPX_AUDIOONLY av_mastering_display_metadata_create_side_data -#endif av_match_list av_match_name av_max_alloc @@ -225,7 +200,6 @@ av_opt_flag_is_set av_opt_free av_opt_freep_ranges av_opt_get -av_opt_get_channel_layout av_opt_get_dict_val av_opt_get_double av_opt_get_image_size @@ -244,7 +218,6 @@ av_opt_query_ranges_default av_opt_serialize av_opt_set av_opt_set_bin -av_opt_set_channel_layout av_opt_set_defaults av_opt_set_defaults2 av_opt_set_dict diff --git a/media/ffvpx/libavutil/bprint.h b/media/ffvpx/libavutil/bprint.h index 8559745478..4ac8570561 100644 --- a/media/ffvpx/libavutil/bprint.h +++ b/media/ffvpx/libavutil/bprint.h @@ -172,9 +172,9 @@ void av_bprint_chars(AVBPrint *buf, char c, unsigned n); /** * Append data to a print buffer. * - * param buf bprint buffer to use - * param data pointer to data - * param size size of data + * @param buf bprint buffer to use + * @param data pointer to data + * @param size size of data */ void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size); @@ -182,9 +182,9 @@ struct tm; /** * Append a formatted date and time to a print buffer. * - * param buf bprint buffer to use - * param fmt date and time format string, see strftime() - * param tm broken-down time structure to translate + * @param buf bprint buffer to use + * @param fmt date and time format string, see strftime() + * @param tm broken-down time structure to translate * * @note due to poor design of the standard strftime function, it may * produce poor results if the format string expands to a very long text and diff --git a/media/ffvpx/libavutil/channel_layout.c b/media/ffvpx/libavutil/channel_layout.c index b59d798f29..fd6718e0e7 100644 --- a/media/ffvpx/libavutil/channel_layout.c +++ b/media/ffvpx/libavutil/channel_layout.c @@ -33,6 +33,7 @@ #include "common.h" #include "error.h" #include "macros.h" +#include "mem.h" #include "opt.h" #define CHAN_IS_AMBI(x) ((x) >= AV_CHAN_AMBISONIC_BASE &&\ @@ -76,14 +77,6 @@ static const struct channel_name channel_names[] = { [AV_CHAN_BOTTOM_FRONT_RIGHT ] = { "BFR", "bottom front right" }, }; -static const char *get_channel_name(enum AVChannel channel_id) -{ - if ((unsigned) channel_id >= FF_ARRAY_ELEMS(channel_names) || - !channel_names[channel_id].name) - return NULL; - return channel_names[channel_id].name; -} - void av_channel_name_bprint(AVBPrint *bp, enum AVChannel channel_id) { if (channel_id >= AV_CHAN_AMBISONIC_BASE && @@ -94,6 +87,10 @@ void av_channel_name_bprint(AVBPrint *bp, enum AVChannel channel_id) av_bprintf(bp, "%s", channel_names[channel_id].name); else if (channel_id == AV_CHAN_NONE) av_bprintf(bp, "NONE"); + else if (channel_id == AV_CHAN_UNKNOWN) + av_bprintf(bp, "UNK"); + else if (channel_id == AV_CHAN_UNUSED) + av_bprintf(bp, "UNSD"); else av_bprintf(bp, "USR%d", channel_id); } @@ -123,6 +120,10 @@ void av_channel_description_bprint(AVBPrint *bp, enum AVChannel channel_id) av_bprintf(bp, "%s", channel_names[channel_id].description); else if (channel_id == AV_CHAN_NONE) av_bprintf(bp, "none"); + else if (channel_id == AV_CHAN_UNKNOWN) + av_bprintf(bp, "unknown"); + else if (channel_id == AV_CHAN_UNUSED) + av_bprintf(bp, "unused"); else av_bprintf(bp, "user %d", channel_id); } @@ -159,6 +160,11 @@ enum AVChannel av_channel_from_string(const char *str) if (channel_names[i].name && !strcmp(str, channel_names[i].name)) return i; } + if (!strcmp(str, "UNK")) + return AV_CHAN_UNKNOWN; + if (!strcmp(str, "UNSD")) + return AV_CHAN_UNUSED; + if (!strncmp(str, "USR", 3)) { const char *p = str + 3; id = strtol(p, &endptr, 0); @@ -214,199 +220,82 @@ static const struct channel_layout_name channel_layout_map[] = { { "22.2", AV_CHANNEL_LAYOUT_22POINT2, }, }; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS -static uint64_t get_channel_layout_single(const char *name, int name_len) +int av_channel_layout_custom_init(AVChannelLayout *channel_layout, int nb_channels) { - int i; - char *end; - int64_t layout; - - for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) { - if (strlen(channel_layout_map[i].name) == name_len && - !memcmp(channel_layout_map[i].name, name, name_len)) - return channel_layout_map[i].layout.u.mask; - } - for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) - if (channel_names[i].name && - strlen(channel_names[i].name) == name_len && - !memcmp(channel_names[i].name, name, name_len)) - return (int64_t)1 << i; - - errno = 0; - i = strtol(name, &end, 10); - - if (!errno && (end + 1 - name == name_len && *end == 'c')) - return av_get_default_channel_layout(i); - - errno = 0; - layout = strtoll(name, &end, 0); - if (!errno && end - name == name_len) - return FFMAX(layout, 0); - return 0; -} - -uint64_t av_get_channel_layout(const char *name) -{ - const char *n, *e; - const char *name_end = name + strlen(name); - int64_t layout = 0, layout_single; - - for (n = name; n < name_end; n = e + 1) { - for (e = n; e < name_end && *e != '+' && *e != '|'; e++); - layout_single = get_channel_layout_single(n, e - n); - if (!layout_single) - return 0; - layout |= layout_single; - } - return layout; -} - -int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels) -{ - int nb = 0; - char *end; - uint64_t layout = av_get_channel_layout(name); - - if (layout) { - *channel_layout = layout; - *nb_channels = av_get_channel_layout_nb_channels(layout); - return 0; - } - - nb = strtol(name, &end, 10); - if (!errno && *end == 'C' && *(end + 1) == '\0' && nb > 0 && nb < 64) { - *channel_layout = 0; - *nb_channels = nb; - return 0; - } - - return AVERROR(EINVAL); -} - -void av_bprint_channel_layout(struct AVBPrint *bp, - int nb_channels, uint64_t channel_layout) -{ - int i; + AVChannelCustom *map; if (nb_channels <= 0) - nb_channels = av_get_channel_layout_nb_channels(channel_layout); - - for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) - if (nb_channels == channel_layout_map[i].layout.nb_channels && - channel_layout == channel_layout_map[i].layout.u.mask) { - av_bprintf(bp, "%s", channel_layout_map[i].name); - return; - } - - av_bprintf(bp, "%d channels", nb_channels); - if (channel_layout) { - int i, ch; - av_bprintf(bp, " ("); - for (i = 0, ch = 0; i < 64; i++) { - if ((channel_layout & (UINT64_C(1) << i))) { - const char *name = get_channel_name(i); - if (name) { - if (ch > 0) - av_bprintf(bp, "+"); - av_bprintf(bp, "%s", name); - } - ch++; - } - } - av_bprintf(bp, ")"); - } -} - -void av_get_channel_layout_string(char *buf, int buf_size, - int nb_channels, uint64_t channel_layout) -{ - AVBPrint bp; + return AVERROR(EINVAL); - av_bprint_init_for_buffer(&bp, buf, buf_size); - av_bprint_channel_layout(&bp, nb_channels, channel_layout); -} + map = av_calloc(nb_channels, sizeof(*channel_layout->u.map)); + if (!map) + return AVERROR(ENOMEM); + for (int i = 0; i < nb_channels; i++) + map[i].id = AV_CHAN_UNKNOWN; -int av_get_channel_layout_nb_channels(uint64_t channel_layout) -{ - return av_popcount64(channel_layout); -} + channel_layout->order = AV_CHANNEL_ORDER_CUSTOM; + channel_layout->nb_channels = nb_channels; + channel_layout->u.map = map; -int64_t av_get_default_channel_layout(int nb_channels) { - int i; - for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) - if (nb_channels == channel_layout_map[i].layout.nb_channels) - return channel_layout_map[i].layout.u.mask; return 0; } -int av_get_channel_layout_channel_index(uint64_t channel_layout, - uint64_t channel) +int av_channel_layout_from_mask(AVChannelLayout *channel_layout, + uint64_t mask) { - if (!(channel_layout & channel) || - av_get_channel_layout_nb_channels(channel) != 1) + if (!mask) return AVERROR(EINVAL); - channel_layout &= channel - 1; - return av_get_channel_layout_nb_channels(channel_layout); -} -const char *av_get_channel_name(uint64_t channel) -{ - int i; - if (av_get_channel_layout_nb_channels(channel) != 1) - return NULL; - for (i = 0; i < 64; i++) - if ((1ULL<<i) & channel) - return get_channel_name(i); - return NULL; -} + channel_layout->order = AV_CHANNEL_ORDER_NATIVE; + channel_layout->nb_channels = av_popcount64(mask); + channel_layout->u.mask = mask; -const char *av_get_channel_description(uint64_t channel) -{ - int i; - if (av_get_channel_layout_nb_channels(channel) != 1) - return NULL; - for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) - if ((1ULL<<i) & channel) - return channel_names[i].description; - return NULL; + return 0; } -uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index) +static int parse_channel_list(AVChannelLayout *ch_layout, const char *str) { - int i; + int ret; + int nb_channels = 0; + AVChannelCustom *map = NULL; + AVChannelCustom custom = {0}; - if (av_get_channel_layout_nb_channels(channel_layout) <= index) - return 0; + while (*str) { + char *channel, *chname; + int ret = av_opt_get_key_value(&str, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); + if (ret < 0) { + av_freep(&map); + return ret; + } + if (*str) + str++; // skip separator + if (!channel) { + channel = chname; + chname = NULL; + } + av_strlcpy(custom.name, chname ? chname : "", sizeof(custom.name)); + custom.id = av_channel_from_string(channel); + av_free(channel); + av_free(chname); + if (custom.id == AV_CHAN_NONE) { + av_freep(&map); + return AVERROR(EINVAL); + } - for (i = 0; i < 64; i++) { - if ((1ULL << i) & channel_layout && !index--) - return 1ULL << i; + av_dynarray2_add((void **)&map, &nb_channels, sizeof(custom), (void *)&custom); + if (!map) + return AVERROR(ENOMEM); } - return 0; -} - -int av_get_standard_channel_layout(unsigned index, uint64_t *layout, - const char **name) -{ - if (index >= FF_ARRAY_ELEMS(channel_layout_map)) - return AVERROR_EOF; - if (layout) *layout = channel_layout_map[index].layout.u.mask; - if (name) *name = channel_layout_map[index].name; - return 0; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif -int av_channel_layout_from_mask(AVChannelLayout *channel_layout, - uint64_t mask) -{ - if (!mask) + if (!nb_channels) return AVERROR(EINVAL); - channel_layout->order = AV_CHANNEL_ORDER_NATIVE; - channel_layout->nb_channels = av_popcount64(mask); - channel_layout->u.mask = mask; + ch_layout->order = AV_CHANNEL_ORDER_CUSTOM; + ch_layout->u.map = map; + ch_layout->nb_channels = nb_channels; + + ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL); + av_assert0(ret == 0); return 0; } @@ -414,10 +303,8 @@ int av_channel_layout_from_mask(AVChannelLayout *channel_layout, int av_channel_layout_from_string(AVChannelLayout *channel_layout, const char *str) { - int i; - int channels = 0, nb_channels = 0, native = 1; - enum AVChannel highest_channel = AV_CHAN_NONE; - const char *dup; + int i, matches, ret; + int channels = 0, nb_channels = 0; char *chlist, *end; uint64_t mask = 0; @@ -429,6 +316,10 @@ int av_channel_layout_from_string(AVChannelLayout *channel_layout, } } + /* This function is a channel layout initializer, so we have to + * zero-initialize before we start setting fields individually. */ + memset(channel_layout, 0, sizeof(*channel_layout)); + /* ambisonic */ if (!strncmp(str, "ambisonic ", 10)) { const char *p = str + 10; @@ -470,6 +361,7 @@ int av_channel_layout_from_string(AVChannelLayout *channel_layout, for (i = 0; i < extra.nb_channels; i++) { enum AVChannel ch = av_channel_layout_channel_from_index(&extra, i); if (CHAN_IS_AMBI(ch)) { + av_channel_layout_uninit(channel_layout); av_channel_layout_uninit(&extra); return AVERROR(EINVAL); } @@ -493,121 +385,20 @@ int av_channel_layout_from_string(AVChannelLayout *channel_layout, return AVERROR(ENOMEM); /* channel names */ - av_sscanf(str, "%d channels (%[^)]", &nb_channels, chlist); - end = strchr(str, ')'); - - dup = chlist; - while (*dup) { - char *channel, *chname; - int ret = av_opt_get_key_value(&dup, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); - if (ret < 0) { - av_free(chlist); - return ret; - } - if (*dup) - dup++; // skip separator - if (channel && !*channel) - av_freep(&channel); - for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) { - if (channel_names[i].name && !strcmp(channel ? channel : chname, channel_names[i].name)) { - if (channel || i < highest_channel || mask & (1ULL << i)) - native = 0; // Not a native layout, use a custom one - highest_channel = i; - mask |= 1ULL << i; - break; - } - } - - if (!channel && i >= FF_ARRAY_ELEMS(channel_names)) { - char *endptr = chname; - enum AVChannel id = AV_CHAN_NONE; - - if (!strncmp(chname, "USR", 3)) { - const char *p = chname + 3; - id = strtol(p, &endptr, 0); - } - if (id < 0 || *endptr) { - native = 0; // Unknown channel name - channels = 0; - mask = 0; - av_free(chname); - break; - } - if (id > 63) - native = 0; // Not a native layout, use a custom one - else { - if (id < highest_channel || mask & (1ULL << id)) - native = 0; // Not a native layout, use a custom one - highest_channel = id; - mask |= 1ULL << id; - } - } - channels++; - av_free(channel); - av_free(chname); - } - - if (mask && native) { - av_free(chlist); - if (nb_channels && ((nb_channels != channels) || (!end || *++end))) - return AVERROR(EINVAL); - av_channel_layout_from_mask(channel_layout, mask); - return 0; - } - - /* custom layout of channel names */ - if (channels && !native) { - int idx = 0; + matches = av_sscanf(str, "%d channels (%[^)]", &nb_channels, chlist); + ret = parse_channel_list(channel_layout, chlist); + av_freep(&chlist); + if (ret < 0 && ret != AVERROR(EINVAL)) + return ret; - if (nb_channels && ((nb_channels != channels) || (!end || *++end))) { - av_free(chlist); + if (ret >= 0) { + end = strchr(str, ')'); + if (matches == 2 && (nb_channels != channel_layout->nb_channels || !end || *++end)) { + av_channel_layout_uninit(channel_layout); return AVERROR(EINVAL); } - - channel_layout->u.map = av_calloc(channels, sizeof(*channel_layout->u.map)); - if (!channel_layout->u.map) { - av_free(chlist); - return AVERROR(ENOMEM); - } - - channel_layout->order = AV_CHANNEL_ORDER_CUSTOM; - channel_layout->nb_channels = channels; - - dup = chlist; - while (*dup) { - char *channel, *chname; - int ret = av_opt_get_key_value(&dup, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); - if (ret < 0) { - av_freep(&channel_layout->u.map); - av_free(chlist); - return ret; - } - if (*dup) - dup++; // skip separator - for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) { - if (channel_names[i].name && !strcmp(channel ? channel : chname, channel_names[i].name)) { - channel_layout->u.map[idx].id = i; - if (channel) - av_strlcpy(channel_layout->u.map[idx].name, chname, sizeof(channel_layout->u.map[idx].name)); - idx++; - break; - } - } - if (i >= FF_ARRAY_ELEMS(channel_names)) { - const char *p = (channel ? channel : chname) + 3; - channel_layout->u.map[idx].id = strtol(p, NULL, 0); - if (channel) - av_strlcpy(channel_layout->u.map[idx].name, chname, sizeof(channel_layout->u.map[idx].name)); - idx++; - } - av_free(channel); - av_free(chname); - } - av_free(chlist); - return 0; } - av_freep(&chlist); errno = 0; mask = strtoull(str, &end, 0); @@ -659,6 +450,29 @@ int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src) return 0; } +static int64_t masked_description(const AVChannelLayout *channel_layout, int start_channel) +{ + uint64_t mask = 0; + for (int i = start_channel; i < channel_layout->nb_channels; i++) { + enum AVChannel ch = channel_layout->u.map[i].id; + if (ch >= 0 && ch < 63 && mask < (1ULL << ch)) + mask |= (1ULL << ch); + else + return AVERROR(EINVAL); + } + return mask; +} + +static int has_channel_names(const AVChannelLayout *channel_layout) +{ + if (channel_layout->order != AV_CHANNEL_ORDER_CUSTOM) + return 0; + for (int i = 0; i < channel_layout->nb_channels; i++) + if (channel_layout->u.map[i].name[0]) + return 1; + return 0; +} + /** * If the layout is n-th order standard-order ambisonic, with optional * extra non-diegetic channels at the end, return the order. @@ -702,6 +516,33 @@ static int ambisonic_order(const AVChannelLayout *channel_layout) return order; } +static enum AVChannelOrder canonical_order(AVChannelLayout *channel_layout) +{ + int has_known_channel = 0; + int order; + + if (channel_layout->order != AV_CHANNEL_ORDER_CUSTOM) + return channel_layout->order; + + if (has_channel_names(channel_layout)) + return AV_CHANNEL_ORDER_CUSTOM; + + for (int i = 0; i < channel_layout->nb_channels && !has_known_channel; i++) + if (channel_layout->u.map[i].id != AV_CHAN_UNKNOWN) + has_known_channel = 1; + if (!has_known_channel) + return AV_CHANNEL_ORDER_UNSPEC; + + if (masked_description(channel_layout, 0) > 0) + return AV_CHANNEL_ORDER_NATIVE; + + order = ambisonic_order(channel_layout); + if (order >= 0 && masked_description(channel_layout, (order + 1) * (order + 1)) >= 0) + return AV_CHANNEL_ORDER_AMBISONIC; + + return AV_CHANNEL_ORDER_CUSTOM; +} + /** * If the custom layout is n-th order standard-order ambisonic, with optional * extra non-diegetic channels at the end, write its string description in bp. @@ -726,9 +567,17 @@ static int try_describe_ambisonic(AVBPrint *bp, const AVChannelLayout *channel_l extra.nb_channels = av_popcount64(channel_layout->u.mask); extra.u.mask = channel_layout->u.mask; } else { - extra.order = AV_CHANNEL_ORDER_CUSTOM; - extra.nb_channels = channel_layout->nb_channels - nb_ambi_channels; - extra.u.map = channel_layout->u.map + nb_ambi_channels; + int64_t mask; + if (!has_channel_names(channel_layout) && + (mask = masked_description(channel_layout, nb_ambi_channels)) > 0) { + extra.order = AV_CHANNEL_ORDER_NATIVE; + extra.nb_channels = av_popcount64(mask); + extra.u.mask = mask; + } else { + extra.order = AV_CHANNEL_ORDER_CUSTOM; + extra.nb_channels = channel_layout->nb_channels - nb_ambi_channels; + extra.u.map = channel_layout->u.map + nb_ambi_channels; + } } av_bprint_chars(bp, '+', 1); @@ -754,9 +603,17 @@ int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, // fall-through case AV_CHANNEL_ORDER_CUSTOM: if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) { + int64_t mask; int res = try_describe_ambisonic(bp, channel_layout); if (res >= 0) return 0; + if (!has_channel_names(channel_layout) && + (mask = masked_description(channel_layout, 0)) > 0) { + AVChannelLayout native = { .order = AV_CHANNEL_ORDER_NATIVE, + .nb_channels = av_popcount64(mask), + .u.mask = mask }; + return av_channel_layout_describe_bprint(&native, bp); + } } if (channel_layout->nb_channels) av_bprintf(bp, "%d channels (", channel_layout->nb_channels); @@ -1016,3 +873,97 @@ uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, return ret; } + +int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags) +{ + int allow_lossy = !(flags & AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS); + int lossy; + + if (!av_channel_layout_check(channel_layout)) + return AVERROR(EINVAL); + + if (flags & AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL) + order = canonical_order(channel_layout); + + if (channel_layout->order == order) + return 0; + + switch (order) { + case AV_CHANNEL_ORDER_UNSPEC: { + int nb_channels = channel_layout->nb_channels; + if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) { + lossy = 0; + for (int i = 0; i < nb_channels; i++) { + if (channel_layout->u.map[i].id != AV_CHAN_UNKNOWN || channel_layout->u.map[i].name[0]) { + lossy = 1; + break; + } + } + } else { + lossy = 1; + } + if (!lossy || allow_lossy) { + void *opaque = channel_layout->opaque; + av_channel_layout_uninit(channel_layout); + channel_layout->order = AV_CHANNEL_ORDER_UNSPEC; + channel_layout->nb_channels = nb_channels; + channel_layout->opaque = opaque; + return lossy; + } + return AVERROR(ENOSYS); + } + case AV_CHANNEL_ORDER_NATIVE: + if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) { + int64_t mask = masked_description(channel_layout, 0); + if (mask < 0) + return AVERROR(ENOSYS); + lossy = has_channel_names(channel_layout); + if (!lossy || allow_lossy) { + void *opaque = channel_layout->opaque; + av_channel_layout_uninit(channel_layout); + av_channel_layout_from_mask(channel_layout, mask); + channel_layout->opaque = opaque; + return lossy; + } + } + return AVERROR(ENOSYS); + case AV_CHANNEL_ORDER_CUSTOM: { + AVChannelLayout custom = { 0 }; + int ret = av_channel_layout_custom_init(&custom, channel_layout->nb_channels); + void *opaque = channel_layout->opaque; + if (ret < 0) + return ret; + if (channel_layout->order != AV_CHANNEL_ORDER_UNSPEC) + for (int i = 0; i < channel_layout->nb_channels; i++) + custom.u.map[i].id = av_channel_layout_channel_from_index(channel_layout, i); + av_channel_layout_uninit(channel_layout); + *channel_layout = custom; + channel_layout->opaque = opaque; + return 0; + } + case AV_CHANNEL_ORDER_AMBISONIC: + if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) { + int64_t mask; + int nb_channels = channel_layout->nb_channels; + int order = ambisonic_order(channel_layout); + if (order < 0) + return AVERROR(ENOSYS); + mask = masked_description(channel_layout, (order + 1) * (order + 1)); + if (mask < 0) + return AVERROR(ENOSYS); + lossy = has_channel_names(channel_layout); + if (!lossy || allow_lossy) { + void *opaque = channel_layout->opaque; + av_channel_layout_uninit(channel_layout); + channel_layout->order = AV_CHANNEL_ORDER_AMBISONIC; + channel_layout->nb_channels = nb_channels; + channel_layout->u.mask = mask; + channel_layout->opaque = opaque; + return lossy; + } + } + return AVERROR(ENOSYS); + default: + return AVERROR(EINVAL); + } +} diff --git a/media/ffvpx/libavutil/channel_layout.h b/media/ffvpx/libavutil/channel_layout.h index 8dc1a91401..8a078d1601 100644 --- a/media/ffvpx/libavutil/channel_layout.h +++ b/media/ffvpx/libavutil/channel_layout.h @@ -119,7 +119,7 @@ enum AVChannelOrder { /** * The channel order does not correspond to any other predefined order and * is stored as an explicit map. For example, this could be used to support - * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_SILENCE) + * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_UNUSED) * channels at arbitrary positions. */ AV_CHANNEL_ORDER_CUSTOM, @@ -146,6 +146,10 @@ enum AVChannelOrder { * as defined in AmbiX format $ 2.1. */ AV_CHANNEL_ORDER_AMBISONIC, + /** + * Number of channel orders, not part of ABI/API + */ + FF_CHANNEL_ORDER_NB }; @@ -192,16 +196,6 @@ enum AVChannelOrder { #define AV_CH_BOTTOM_FRONT_LEFT (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT ) #define AV_CH_BOTTOM_FRONT_RIGHT (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT ) -#if FF_API_OLD_CHANNEL_LAYOUT -/** Channel mask value used for AVCodecContext.request_channel_layout - to indicate that the user requests the channel order of the decoder output - to be the native codec channel order. - @deprecated channel order is now indicated in a special field in - AVChannelLayout - */ -#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL -#endif - /** * @} * @defgroup channel_mask_c Audio channel layouts @@ -430,146 +424,6 @@ typedef struct AVChannelLayout { struct AVBPrint; -#if FF_API_OLD_CHANNEL_LAYOUT -/** - * @name Deprecated Functions - * @{ - */ - -/** - * Return a channel layout id that matches name, or 0 if no match is found. - * - * name can be one or several of the following notations, - * separated by '+' or '|': - * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, - * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); - * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, - * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); - * - a number of channels, in decimal, followed by 'c', yielding - * the default channel layout for that number of channels (@see - * av_get_default_channel_layout); - * - a channel layout mask, in hexadecimal starting with "0x" (see the - * AV_CH_* macros). - * - * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" - * - * @deprecated use av_channel_layout_from_string() - */ -attribute_deprecated -uint64_t av_get_channel_layout(const char *name); - -/** - * Return a channel layout and the number of channels based on the specified name. - * - * This function is similar to (@see av_get_channel_layout), but can also parse - * unknown channel layout specifications. - * - * @param[in] name channel layout specification string - * @param[out] channel_layout parsed channel layout (0 if unknown) - * @param[out] nb_channels number of channels - * - * @return 0 on success, AVERROR(EINVAL) if the parsing fails. - * @deprecated use av_channel_layout_from_string() - */ -attribute_deprecated -int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels); - -/** - * Return a description of a channel layout. - * If nb_channels is <= 0, it is guessed from the channel_layout. - * - * @param buf put here the string containing the channel layout - * @param buf_size size in bytes of the buffer - * @param nb_channels number of channels - * @param channel_layout channel layout bitset - * @deprecated use av_channel_layout_describe() - */ -attribute_deprecated -void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); - -/** - * Append a description of a channel layout to a bprint buffer. - * @deprecated use av_channel_layout_describe() - */ -attribute_deprecated -void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout); - -/** - * Return the number of channels in the channel layout. - * @deprecated use AVChannelLayout.nb_channels - */ -attribute_deprecated -int av_get_channel_layout_nb_channels(uint64_t channel_layout); - -/** - * Return default channel layout for a given number of channels. - * - * @deprecated use av_channel_layout_default() - */ -attribute_deprecated -int64_t av_get_default_channel_layout(int nb_channels); - -/** - * Get the index of a channel in channel_layout. - * - * @param channel_layout channel layout bitset - * @param channel a channel layout describing exactly one channel which must be - * present in channel_layout. - * - * @return index of channel in channel_layout on success, a negative AVERROR - * on error. - * - * @deprecated use av_channel_layout_index_from_channel() - */ -attribute_deprecated -int av_get_channel_layout_channel_index(uint64_t channel_layout, - uint64_t channel); - -/** - * Get the channel with the given index in channel_layout. - * @deprecated use av_channel_layout_channel_from_index() - */ -attribute_deprecated -uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); - -/** - * Get the name of a given channel. - * - * @return channel name on success, NULL on error. - * - * @deprecated use av_channel_name() - */ -attribute_deprecated -const char *av_get_channel_name(uint64_t channel); - -/** - * Get the description of a given channel. - * - * @param channel a channel layout with a single channel - * @return channel description on success, NULL on error - * @deprecated use av_channel_description() - */ -attribute_deprecated -const char *av_get_channel_description(uint64_t channel); - -/** - * Get the value and name of a standard channel layout. - * - * @param[in] index index in an internal list, starting at 0 - * @param[out] layout channel layout mask - * @param[out] name name of the layout - * @return 0 if the layout exists, - * <0 if index is beyond the limits - * @deprecated use av_channel_layout_standard() - */ -attribute_deprecated -int av_get_standard_channel_layout(unsigned index, uint64_t *layout, - const char **name); -/** - * @} - */ -#endif - /** * Get a human readable string in an abbreviated form describing a given channel. * This is the inverse function of @ref av_channel_from_string(). @@ -618,6 +472,23 @@ void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_i enum AVChannel av_channel_from_string(const char *name); /** + * Initialize a custom channel layout with the specified number of channels. + * The channel map will be allocated and the designation of all channels will + * be set to AV_CHAN_UNKNOWN. + * + * This is only a convenience helper function, a custom channel layout can also + * be constructed without using this. + * + * @param channel_layout the layout structure to be initialized + * @param nb_channels the number of channels + * + * @return 0 on success + * AVERROR(EINVAL) if the number of channels <= 0 + * AVERROR(ENOMEM) if the channel map could not be allocated + */ +int av_channel_layout_custom_init(AVChannelLayout *channel_layout, int nb_channels); + +/** * Initialize a native channel layout from a bitmask indicating which channels * are present. * @@ -641,10 +512,14 @@ int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask); * - the number of unordered channels (eg. "4C" or "4 channels") * - the ambisonic order followed by optional non-diegetic channels (eg. * "ambisonic 2+stereo") + * On error, the channel layout will remain uninitialized, but not necessarily + * untouched. * - * @param channel_layout input channel layout + * @param channel_layout uninitialized channel layout for the result * @param str string describing the channel layout - * @return 0 channel layout was detected, AVERROR_INVALIDATATA otherwise + * @return 0 on success parsing the channel layout + * AVERROR(EINVAL) if an invalid channel layout string was provided + * AVERROR(ENOMEM) if there was not enough memory */ int av_channel_layout_from_string(AVChannelLayout *channel_layout, const char *str); @@ -805,6 +680,53 @@ int av_channel_layout_check(const AVChannelLayout *channel_layout); int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1); /** + * The conversion must be lossless. + */ +#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS (1 << 0) + +/** + * The specified retype target order is ignored and the simplest possible + * (canonical) order is used for which the input layout can be losslessy + * represented. + */ +#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL (1 << 1) + +/** + * Change the AVChannelOrder of a channel layout. + * + * Change of AVChannelOrder can be either lossless or lossy. In case of a + * lossless conversion all the channel designations and the associated channel + * names (if any) are kept. On a lossy conversion the channel names and channel + * designations might be lost depending on the capabilities of the desired + * AVChannelOrder. Note that some conversions are simply not possible in which + * case this function returns AVERROR(ENOSYS). + * + * The following conversions are supported: + * + * Any -> Custom : Always possible, always lossless. + * Any -> Unspecified: Always possible, lossless if channel designations + * are all unknown and channel names are not used, lossy otherwise. + * Custom -> Ambisonic : Possible if it contains ambisonic channels with + * optional non-diegetic channels in the end. Lossy if the channels have + * custom names, lossless otherwise. + * Custom -> Native : Possible if it contains native channels in native + * order. Lossy if the channels have custom names, lossless otherwise. + * + * On error this function keeps the original channel layout untouched. + * + * @param channel_layout channel layout which will be changed + * @param order the desired channel layout order + * @param flags a combination of AV_CHANNEL_LAYOUT_RETYPE_FLAG_* constants + * @return 0 if the conversion was successful and lossless or if the channel + * layout was already in the desired order + * >0 if the conversion was successful but lossy + * AVERROR(ENOSYS) if the conversion was not possible (or would be + * lossy and AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS was specified) + * AVERROR(EINVAL), AVERROR(ENOMEM) on error + */ +int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags); + +/** * @} */ diff --git a/media/ffvpx/libavutil/color_utils.c b/media/ffvpx/libavutil/color_utils.c deleted file mode 100644 index 5e221fb798..0000000000 --- a/media/ffvpx/libavutil/color_utils.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> - * - * 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 <stddef.h> -#include <math.h> - -#include "libavutil/color_utils.h" -#include "libavutil/pixfmt.h" - -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc) -{ - double gamma; - switch (trc) { - case AVCOL_TRC_BT709: - case AVCOL_TRC_SMPTE170M: - case AVCOL_TRC_SMPTE240M: - case AVCOL_TRC_BT1361_ECG: - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - /* these share a segmented TRC, but gamma 1.961 is a close - approximation, and also more correct for decoding content */ - gamma = 1.961; - break; - case AVCOL_TRC_GAMMA22: - case AVCOL_TRC_IEC61966_2_1: - gamma = 2.2; - break; - case AVCOL_TRC_GAMMA28: - gamma = 2.8; - break; - case AVCOL_TRC_LINEAR: - gamma = 1.0; - break; - default: - gamma = 0.0; // Unknown value representation - } - return gamma; -} - -#define BT709_alpha 1.099296826809442 -#define BT709_beta 0.018053968510807 - -static double avpriv_trc_bt709(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 4.500 * Lc - : a * pow(Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_gamma22(double Lc) -{ - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); -} - -static double avpriv_trc_gamma28(double Lc) -{ - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); -} - -static double avpriv_trc_smpte240M(double Lc) -{ - const double a = 1.1115; - const double b = 0.0228; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 4.000 * Lc - : a * pow(Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_linear(double Lc) -{ - return Lc; -} - -static double avpriv_trc_log(double Lc) -{ - return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; -} - -static double avpriv_trc_log_sqrt(double Lc) -{ - // sqrt(10) / 1000 - return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; -} - -static double avpriv_trc_iec61966_2_4(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) - : ( b > Lc) ? 4.500 * Lc - : a * pow( Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_bt1361(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 - : ( b > Lc) ? 4.500 * Lc - : a * pow( Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_iec61966_2_1(double Lc) -{ - const double a = 1.055; - const double b = 0.0031308; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 12.92 * Lc - : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); -} - -static double avpriv_trc_smpte_st2084(double Lc) -{ - const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 - const double c2 = 32.0 * 2413.0 / 4096.0; - const double c3 = 32.0 * 2392.0 / 4096.0; - const double m = 128.0 * 2523.0 / 4096.0; - const double n = 0.25 * 2610.0 / 4096.0; - const double L = Lc / 10000.0; - const double Ln = pow(L, n); - - return (0.0 > Lc) ? 0.0 - : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); - -} - -static double avpriv_trc_smpte_st428_1(double Lc) -{ - return (0.0 > Lc) ? 0.0 - : pow(48.0 * Lc / 52.37, 1.0 / 2.6); -} - - -static double avpriv_trc_arib_std_b67(double Lc) { - // The function uses the definition from HEVC, which assumes that the peak - // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and - // using the definition from the ARIB STD-B67 spec) - const double a = 0.17883277; - const double b = 0.28466892; - const double c = 0.55991073; - return (0.0 > Lc) ? 0.0 : - (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); -} - -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc) -{ - avpriv_trc_function func = NULL; - switch (trc) { - case AVCOL_TRC_BT709: - case AVCOL_TRC_SMPTE170M: - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - func = avpriv_trc_bt709; - break; - - case AVCOL_TRC_GAMMA22: - func = avpriv_trc_gamma22; - break; - case AVCOL_TRC_GAMMA28: - func = avpriv_trc_gamma28; - break; - - case AVCOL_TRC_SMPTE240M: - func = avpriv_trc_smpte240M; - break; - - case AVCOL_TRC_LINEAR: - func = avpriv_trc_linear; - break; - - case AVCOL_TRC_LOG: - func = avpriv_trc_log; - break; - - case AVCOL_TRC_LOG_SQRT: - func = avpriv_trc_log_sqrt; - break; - - case AVCOL_TRC_IEC61966_2_4: - func = avpriv_trc_iec61966_2_4; - break; - - case AVCOL_TRC_BT1361_ECG: - func = avpriv_trc_bt1361; - break; - - case AVCOL_TRC_IEC61966_2_1: - func = avpriv_trc_iec61966_2_1; - break; - - case AVCOL_TRC_SMPTEST2084: - func = avpriv_trc_smpte_st2084; - break; - - case AVCOL_TRC_SMPTEST428_1: - func = avpriv_trc_smpte_st428_1; - break; - - case AVCOL_TRC_ARIB_STD_B67: - func = avpriv_trc_arib_std_b67; - break; - - case AVCOL_TRC_RESERVED0: - case AVCOL_TRC_UNSPECIFIED: - case AVCOL_TRC_RESERVED: - default: - break; - } - return func; -} diff --git a/media/ffvpx/libavutil/color_utils.h b/media/ffvpx/libavutil/color_utils.h deleted file mode 100644 index 9529006452..0000000000 --- a/media/ffvpx/libavutil/color_utils.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> - * - * 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_COLOR_UTILS_H -#define AVUTIL_COLOR_UTILS_H - - -#include "libavutil/pixfmt.h" - -/** - * Determine a suitable 'gamma' value to match the supplied - * AVColorTransferCharacteristic. - * - * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) - * - * @return Will return an approximation to the simple gamma function matching - * the supplied Transfer Characteristic, Will return 0.0 for any - * we cannot reasonably match against. - */ -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc); - - -typedef double (*avpriv_trc_function)(double); - -/** - * Determine the function needed to apply the given - * AVColorTransferCharacteristic to linear input. - * - * The function returned should expect a nominal domain and range of [0.0-1.0] - * values outside of this range maybe valid depending on the chosen - * characteristic function. - * - * @return Will return pointer to the function matching the - * supplied Transfer Characteristic. If unspecified will - * return NULL: - */ -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc); - -#endif diff --git a/media/ffvpx/libavutil/common.h b/media/ffvpx/libavutil/common.h index de2140a678..3e4c339893 100644 --- a/media/ffvpx/libavutil/common.h +++ b/media/ffvpx/libavutil/common.h @@ -43,6 +43,14 @@ #include "error.h" #include "macros.h" +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +# include "internal.h" +#else +# include "mem.h" +#endif /* HAVE_AV_CONFIG_H */ + //rounded division & shift #define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) /* assume b>0 */ @@ -84,11 +92,6 @@ /* misc math functions */ -#ifdef HAVE_AV_CONFIG_H -# include "config.h" -# include "intmath.h" -#endif - #ifndef av_ceil_log2 # define av_ceil_log2 av_ceil_log2_c #endif @@ -568,12 +571,4 @@ static av_always_inline av_const int av_parity_c(uint32_t v) }\ }\ - - -#include "mem.h" - -#ifdef HAVE_AV_CONFIG_H -# include "internal.h" -#endif /* HAVE_AV_CONFIG_H */ - #endif /* AVUTIL_COMMON_H */ diff --git a/media/ffvpx/libavutil/cpu.c b/media/ffvpx/libavutil/cpu.c index 48d195168c..d4f947360a 100644 --- a/media/ffvpx/libavutil/cpu.c +++ b/media/ffvpx/libavutil/cpu.c @@ -49,8 +49,8 @@ #include <unistd.h> #endif -static atomic_int cpu_flags = ATOMIC_VAR_INIT(-1); -static atomic_int cpu_count = ATOMIC_VAR_INIT(-1); +static atomic_int cpu_flags = -1; +static atomic_int cpu_count = -1; static int get_cpu_flags(void) { @@ -208,7 +208,7 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) int av_cpu_count(void) { - static atomic_int printed = ATOMIC_VAR_INIT(0); + static atomic_int printed = 0; int nb_cpus = 1; int count = 0; diff --git a/media/ffvpx/libavutil/csp.h b/media/ffvpx/libavutil/csp.h new file mode 100644 index 0000000000..73bce52bc0 --- /dev/null +++ b/media/ffvpx/libavutil/csp.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> + * + * 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_CSP_H +#define AVUTIL_CSP_H + +#include "pixfmt.h" +#include "rational.h" + +/** + * @file + * Colorspace value utility functions for libavutil. + * @ingroup lavu_math_csp + * @author Ronald S. Bultje <rsbultje@gmail.com> + * @author Leo Izen <leo.izen@gmail.com> + * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> + */ + +/** + * @defgroup lavu_math_csp Colorspace Utility + * @ingroup lavu_math + * @{ + */ + +/** + * Struct containing luma coefficients to be used for RGB to YUV/YCoCg, or similar + * calculations. + */ +typedef struct AVLumaCoefficients { + AVRational cr, cg, cb; +} AVLumaCoefficients; + +/** + * Struct containing chromaticity x and y values for the standard CIE 1931 + * chromaticity definition. + */ +typedef struct AVCIExy { + AVRational x, y; +} AVCIExy; + +/** + * Struct defining the red, green, and blue primary locations in terms of CIE + * 1931 chromaticity x and y. + */ +typedef struct AVPrimaryCoefficients { + AVCIExy r, g, b; +} AVPrimaryCoefficients; + +/** + * Struct defining white point location in terms of CIE 1931 chromaticity x + * and y. + */ +typedef AVCIExy AVWhitepointCoefficients; + +/** + * Struct that contains both white point location and primaries location, providing + * the complete description of a color gamut. + */ +typedef struct AVColorPrimariesDesc { + AVWhitepointCoefficients wp; + AVPrimaryCoefficients prim; +} AVColorPrimariesDesc; + +/** + * Function pointer representing a double -> double transfer function that performs + * an EOTF transfer inversion. This function outputs linear light. + */ +typedef double (*av_csp_trc_function)(double); + +/** + * Retrieves the Luma coefficients necessary to construct a conversion matrix + * from an enum constant describing the colorspace. + * @param csp An enum constant indicating YUV or similar colorspace. + * @return The Luma coefficients associated with that colorspace, or NULL + * if the constant is unknown to libavutil. + */ +const AVLumaCoefficients *av_csp_luma_coeffs_from_avcsp(enum AVColorSpace csp); + +/** + * Retrieves a complete gamut description from an enum constant describing the + * color primaries. + * @param prm An enum constant indicating primaries + * @return A description of the colorspace gamut associated with that enum + * constant, or NULL if the constant is unknown to libavutil. + */ +const AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries prm); + +/** + * Detects which enum AVColorPrimaries constant corresponds to the given complete + * gamut description. + * @see enum AVColorPrimaries + * @param prm A description of the colorspace gamut + * @return The enum constant associated with this gamut, or + * AVCOL_PRI_UNSPECIFIED if no clear match can be idenitified. + */ +enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm); + +/** + * Determine a suitable 'gamma' value to match the supplied + * AVColorTransferCharacteristic. + * + * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) + * + * This function returns the gamma exponent for the OETF. For example, sRGB is approximated + * by gamma 2.2, not by gamma 0.45455. + * + * @return Will return an approximation to the simple gamma function matching + * the supplied Transfer Characteristic, Will return 0.0 for any + * we cannot reasonably match against. + */ +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc); + +/** + * Determine the function needed to apply the given + * AVColorTransferCharacteristic to linear input. + * + * The function returned should expect a nominal domain and range of [0.0-1.0] + * values outside of this range maybe valid depending on the chosen + * characteristic function. + * + * @return Will return pointer to the function matching the + * supplied Transfer Characteristic. If unspecified will + * return NULL: + */ +av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc); + +/** + * @} + */ + +#endif /* AVUTIL_CSP_H */ diff --git a/media/ffvpx/libavutil/dict.c b/media/ffvpx/libavutil/dict.c index 7f23d5336a..6fb09399ba 100644 --- a/media/ffvpx/libavutil/dict.c +++ b/media/ffvpx/libavutil/dict.c @@ -145,11 +145,8 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, m->elems[m->count].value = copy_value; m->count++; } else { - if (!m->count) { - av_freep(&m->elems); - av_freep(pm); - } - av_freep(©_key); + err = 0; + goto end; } return 0; @@ -157,12 +154,13 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, enomem: err = AVERROR(ENOMEM); err_out: + av_free(copy_value); +end: if (m && !m->count) { av_freep(&m->elems); av_freep(pm); } av_free(copy_key); - av_free(copy_value); return err; } diff --git a/media/ffvpx/libavutil/eval.c b/media/ffvpx/libavutil/eval.c index 95adb51609..84ff929130 100644 --- a/media/ffvpx/libavutil/eval.c +++ b/media/ffvpx/libavutil/eval.c @@ -32,13 +32,12 @@ #include "common.h" #include "eval.h" #include "ffmath.h" -#include "internal.h" #include "log.h" #include "mathematics.h" +#include "mem.h" #include "sfc64.h" #include "fftime.h" #include "avstring.h" -#include "timer.h" #include "reverse.h" typedef struct Parser { diff --git a/media/ffvpx/libavutil/fftime.h b/media/ffvpx/libavutil/fftime.h index 8f3b320e38..dc169b064a 100644 --- a/media/ffvpx/libavutil/fftime.h +++ b/media/ffvpx/libavutil/fftime.h @@ -22,7 +22,6 @@ #define AVUTIL_TIME_H #include <stdint.h> -#include <time.h> /** * Get the current time in microseconds. diff --git a/media/ffvpx/libavutil/ffversion.h b/media/ffvpx/libavutil/ffversion.h index 392808d726..1aa567741f 100644 --- a/media/ffvpx/libavutil/ffversion.h +++ b/media/ffvpx/libavutil/ffversion.h @@ -1,5 +1,5 @@ /* Automatically generated by version.sh, do not manually edit! */ #ifndef AVUTIL_FFVERSION_H #define AVUTIL_FFVERSION_H -#define FFMPEG_VERSION "N-111736-gd9d5695390" +#define FFMPEG_VERSION "N-114439-gf0ee4bbc6b" #endif /* AVUTIL_FFVERSION_H */ diff --git a/media/ffvpx/libavutil/fifo.c b/media/ffvpx/libavutil/fifo.c index b0807abbf7..8806c668d7 100644 --- a/media/ffvpx/libavutil/fifo.c +++ b/media/ffvpx/libavutil/fifo.c @@ -290,222 +290,3 @@ void av_fifo_freep2(AVFifo **f) av_freep(f); } } - - -#if FF_API_FIFO_OLD_API -#include "internal.h" -FF_DISABLE_DEPRECATION_WARNINGS -#define OLD_FIFO_SIZE_MAX (size_t)FFMIN3(INT_MAX, UINT32_MAX, SIZE_MAX) - -AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) -{ - AVFifoBuffer *f; - void *buffer; - - if (nmemb > OLD_FIFO_SIZE_MAX / size) - return NULL; - - buffer = av_realloc_array(NULL, nmemb, size); - if (!buffer) - return NULL; - f = av_mallocz(sizeof(AVFifoBuffer)); - if (!f) { - av_free(buffer); - return NULL; - } - f->buffer = buffer; - f->end = f->buffer + nmemb * size; - av_fifo_reset(f); - return f; -} - -AVFifoBuffer *av_fifo_alloc(unsigned int size) -{ - return av_fifo_alloc_array(size, 1); -} - -void av_fifo_free(AVFifoBuffer *f) -{ - if (f) { - av_freep(&f->buffer); - av_free(f); - } -} - -void av_fifo_freep(AVFifoBuffer **f) -{ - if (f) { - av_fifo_free(*f); - *f = NULL; - } -} - -void av_fifo_reset(AVFifoBuffer *f) -{ - f->wptr = f->rptr = f->buffer; - f->wndx = f->rndx = 0; -} - -int av_fifo_size(const AVFifoBuffer *f) -{ - return (uint32_t)(f->wndx - f->rndx); -} - -int av_fifo_space(const AVFifoBuffer *f) -{ - return f->end - f->buffer - av_fifo_size(f); -} - -int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) -{ - unsigned int old_size = f->end - f->buffer; - - if (new_size > OLD_FIFO_SIZE_MAX) - return AVERROR(EINVAL); - - if (old_size < new_size) { - size_t offset_r = f->rptr - f->buffer; - size_t offset_w = f->wptr - f->buffer; - uint8_t *tmp; - - tmp = av_realloc(f->buffer, new_size); - if (!tmp) - return AVERROR(ENOMEM); - - // move the data from the beginning of the ring buffer - // to the newly allocated space - // the second condition distinguishes full vs empty fifo - if (offset_w <= offset_r && av_fifo_size(f)) { - const size_t copy = FFMIN(new_size - old_size, offset_w); - memcpy(tmp + old_size, tmp, copy); - if (copy < offset_w) { - memmove(tmp, tmp + copy , offset_w - copy); - offset_w -= copy; - } else - offset_w = old_size + copy; - } - - f->buffer = tmp; - f->end = f->buffer + new_size; - f->rptr = f->buffer + offset_r; - f->wptr = f->buffer + offset_w; - } - return 0; -} - -int av_fifo_grow(AVFifoBuffer *f, unsigned int size) -{ - unsigned int old_size = f->end - f->buffer; - if(size + (unsigned)av_fifo_size(f) < size) - return AVERROR(EINVAL); - - size += av_fifo_size(f); - - if (old_size < size) - return av_fifo_realloc2(f, FFMAX(size, 2*old_size)); - return 0; -} - -/* src must NOT be const as it can be a context for func that may need - * updating (like a pointer or byte counter) */ -int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, - int (*func)(void *, void *, int)) -{ - int total = size; - uint32_t wndx= f->wndx; - uint8_t *wptr= f->wptr; - - if (size > av_fifo_space(f)) - return AVERROR(ENOSPC); - - do { - int len = FFMIN(f->end - wptr, size); - if (func) { - len = func(src, wptr, len); - if (len <= 0) - break; - } else { - memcpy(wptr, src, len); - src = (uint8_t *)src + len; - } - wptr += len; - if (wptr >= f->end) - wptr = f->buffer; - wndx += len; - size -= len; - } while (size > 0); - f->wndx= wndx; - f->wptr= wptr; - return total - size; -} - -int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)) -{ - uint8_t *rptr = f->rptr; - - if (offset < 0 || buf_size > av_fifo_size(f) - offset) - return AVERROR(EINVAL); - - if (offset >= f->end - rptr) - rptr += offset - (f->end - f->buffer); - else - rptr += offset; - - while (buf_size > 0) { - int len; - - if (rptr >= f->end) - rptr -= f->end - f->buffer; - - len = FFMIN(f->end - rptr, buf_size); - if (func) - func(dest, rptr, len); - else { - memcpy(dest, rptr, len); - dest = (uint8_t *)dest + len; - } - - buf_size -= len; - rptr += len; - } - - return 0; -} - -int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, - void (*func)(void *, void *, int)) -{ - return av_fifo_generic_peek_at(f, dest, 0, buf_size, func); -} - -int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, - void (*func)(void *, void *, int)) -{ - if (buf_size > av_fifo_size(f)) - return AVERROR(EINVAL); - - do { - int len = FFMIN(f->end - f->rptr, buf_size); - if (func) - func(dest, f->rptr, len); - else { - memcpy(dest, f->rptr, len); - dest = (uint8_t *)dest + len; - } - av_fifo_drain(f, len); - buf_size -= len; - } while (buf_size > 0); - return 0; -} - -/** Discard data from the FIFO. */ -void av_fifo_drain(AVFifoBuffer *f, int size) -{ - av_assert2(av_fifo_size(f) >= size); - f->rptr += size; - if (f->rptr >= f->end) - f->rptr -= f->end - f->buffer; - f->rndx += size; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif diff --git a/media/ffvpx/libavutil/fifo.h b/media/ffvpx/libavutil/fifo.h index ce3a2aed7c..f2206c35f5 100644 --- a/media/ffvpx/libavutil/fifo.h +++ b/media/ffvpx/libavutil/fifo.h @@ -26,10 +26,6 @@ #define AVUTIL_FIFO_H #include <stddef.h> -#include <stdint.h> - -#include "attributes.h" -#include "version.h" /** * @defgroup lavu_fifo AVFifo @@ -239,208 +235,6 @@ void av_fifo_reset2(AVFifo *f); */ void av_fifo_freep2(AVFifo **f); - -#if FF_API_FIFO_OLD_API -typedef struct AVFifoBuffer { - uint8_t *buffer; - uint8_t *rptr, *wptr, *end; - uint32_t rndx, wndx; -} AVFifoBuffer; - -/** - * Initialize an AVFifoBuffer. - * @param size of FIFO - * @return AVFifoBuffer or NULL in case of memory allocation failure - * @deprecated use av_fifo_alloc2() - */ -attribute_deprecated -AVFifoBuffer *av_fifo_alloc(unsigned int size); - -/** - * Initialize an AVFifoBuffer. - * @param nmemb number of elements - * @param size size of the single element - * @return AVFifoBuffer or NULL in case of memory allocation failure - * @deprecated use av_fifo_alloc2() - */ -attribute_deprecated -AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size); - -/** - * Free an AVFifoBuffer. - * @param f AVFifoBuffer to free - * @deprecated use the AVFifo API with av_fifo_freep2() - */ -attribute_deprecated -void av_fifo_free(AVFifoBuffer *f); - -/** - * Free an AVFifoBuffer and reset pointer to NULL. - * @param f AVFifoBuffer to free - * @deprecated use the AVFifo API with av_fifo_freep2() - */ -attribute_deprecated -void av_fifo_freep(AVFifoBuffer **f); - -/** - * Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied. - * @param f AVFifoBuffer to reset - * @deprecated use av_fifo_reset2() with the new AVFifo-API - */ -attribute_deprecated -void av_fifo_reset(AVFifoBuffer *f); - -/** - * Return the amount of data in bytes in the AVFifoBuffer, that is the - * amount of data you can read from it. - * @param f AVFifoBuffer to read from - * @return size - * @deprecated use av_fifo_can_read() with the new AVFifo-API - */ -attribute_deprecated -int av_fifo_size(const AVFifoBuffer *f); - -/** - * Return the amount of space in bytes in the AVFifoBuffer, that is the - * amount of data you can write into it. - * @param f AVFifoBuffer to write into - * @return size - * @deprecated use av_fifo_can_write() with the new AVFifo-API - */ -attribute_deprecated -int av_fifo_space(const AVFifoBuffer *f); - -/** - * Feed data at specific position from an AVFifoBuffer to a user-supplied callback. - * Similar as av_fifo_gereric_read but without discarding data. - * @param f AVFifoBuffer to read from - * @param offset offset from current read position - * @param buf_size number of bytes to read - * @param func generic read function - * @param dest data destination - * - * @return a non-negative number on success, a negative error code on failure - * - * @deprecated use the new AVFifo-API with av_fifo_peek() when func == NULL, - * av_fifo_peek_to_cb() otherwise - */ -attribute_deprecated -int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)); - -/** - * Feed data from an AVFifoBuffer to a user-supplied callback. - * Similar as av_fifo_gereric_read but without discarding data. - * @param f AVFifoBuffer to read from - * @param buf_size number of bytes to read - * @param func generic read function - * @param dest data destination - * - * @return a non-negative number on success, a negative error code on failure - * - * @deprecated use the new AVFifo-API with av_fifo_peek() when func == NULL, - * av_fifo_peek_to_cb() otherwise - */ -attribute_deprecated -int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); - -/** - * Feed data from an AVFifoBuffer to a user-supplied callback. - * @param f AVFifoBuffer to read from - * @param buf_size number of bytes to read - * @param func generic read function - * @param dest data destination - * - * @return a non-negative number on success, a negative error code on failure - * - * @deprecated use the new AVFifo-API with av_fifo_read() when func == NULL, - * av_fifo_read_to_cb() otherwise - */ -attribute_deprecated -int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); - -/** - * Feed data from a user-supplied callback to an AVFifoBuffer. - * @param f AVFifoBuffer to write to - * @param src data source; non-const since it may be used as a - * modifiable context by the function defined in func - * @param size number of bytes to write - * @param func generic write function; the first parameter is src, - * the second is dest_buf, the third is dest_buf_size. - * func must return the number of bytes written to dest_buf, or <= 0 to - * indicate no more data available to write. - * If func is NULL, src is interpreted as a simple byte array for source data. - * @return the number of bytes written to the FIFO or a negative error code on failure - * - * @deprecated use the new AVFifo-API with av_fifo_write() when func == NULL, - * av_fifo_write_from_cb() otherwise - */ -attribute_deprecated -int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)); - -/** - * Resize an AVFifoBuffer. - * In case of reallocation failure, the old FIFO is kept unchanged. - * - * @param f AVFifoBuffer to resize - * @param size new AVFifoBuffer size in bytes - * @return <0 for failure, >=0 otherwise - * - * @deprecated use the new AVFifo-API with av_fifo_grow2() to increase FIFO size, - * decreasing FIFO size is not supported - */ -attribute_deprecated -int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size); - -/** - * Enlarge an AVFifoBuffer. - * In case of reallocation failure, the old FIFO is kept unchanged. - * The new fifo size may be larger than the requested size. - * - * @param f AVFifoBuffer to resize - * @param additional_space the amount of space in bytes to allocate in addition to av_fifo_size() - * @return <0 for failure, >=0 otherwise - * - * @deprecated use the new AVFifo-API with av_fifo_grow2(); note that unlike - * this function it adds to the allocated size, rather than to the used size - */ -attribute_deprecated -int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space); - -/** - * Read and discard the specified amount of data from an AVFifoBuffer. - * @param f AVFifoBuffer to read from - * @param size amount of data to read in bytes - * - * @deprecated use the new AVFifo-API with av_fifo_drain2() - */ -attribute_deprecated -void av_fifo_drain(AVFifoBuffer *f, int size); - -#if FF_API_FIFO_PEEK2 -/** - * Return a pointer to the data stored in a FIFO buffer at a certain offset. - * The FIFO buffer is not modified. - * - * @param f AVFifoBuffer to peek at, f must be non-NULL - * @param offs an offset in bytes, its absolute value must be less - * than the used buffer size or the returned pointer will - * point outside to the buffer data. - * The used buffer size can be checked with av_fifo_size(). - * @deprecated use the new AVFifo-API with av_fifo_peek() or av_fifo_peek_to_cb() - */ -attribute_deprecated -static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) -{ - uint8_t *ptr = f->rptr + offs; - if (ptr >= f->end) - ptr = f->buffer + (ptr - f->end); - else if (ptr < f->buffer) - ptr = f->end - (f->buffer - ptr); - return ptr; -} -#endif -#endif - /** * @} */ diff --git a/media/ffvpx/libavutil/film_grain_params.c b/media/ffvpx/libavutil/film_grain_params.c index 930d23c7fe..0a6004b6b3 100644 --- a/media/ffvpx/libavutil/film_grain_params.c +++ b/media/ffvpx/libavutil/film_grain_params.c @@ -17,6 +17,8 @@ */ #include "film_grain_params.h" +#include "mem.h" +#include "pixdesc.h" AVFilmGrainParams *av_film_grain_params_alloc(size_t *size) { @@ -30,13 +32,75 @@ AVFilmGrainParams *av_film_grain_params_alloc(size_t *size) AVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame) { + AVFilmGrainParams *fgp; AVFrameSideData *side_data = av_frame_new_side_data(frame, AV_FRAME_DATA_FILM_GRAIN_PARAMS, sizeof(AVFilmGrainParams)); if (!side_data) return NULL; - memset(side_data->data, 0, sizeof(AVFilmGrainParams)); + fgp = (AVFilmGrainParams *) side_data->data; + *fgp = (AVFilmGrainParams) { + .color_range = AVCOL_RANGE_UNSPECIFIED, + .color_primaries = AVCOL_PRI_UNSPECIFIED, + .color_trc = AVCOL_TRC_UNSPECIFIED, + .color_space = AVCOL_SPC_UNSPECIFIED, + }; - return (AVFilmGrainParams *)side_data->data; + return fgp; +} + +const AVFilmGrainParams *av_film_grain_params_select(const AVFrame *frame) +{ + const AVFilmGrainParams *fgp, *best = NULL; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + int bit_depth_luma, bit_depth_chroma; + if (!desc) + return NULL; + + /* There are no YUV formats with different bit depth per component, + * so just check both against the first component for simplicity */ + bit_depth_luma = bit_depth_chroma = desc->comp[0].depth; + + for (int i = 0; i < frame->nb_side_data; i++) { + if (frame->side_data[i]->type != AV_FRAME_DATA_FILM_GRAIN_PARAMS) + continue; + fgp = (const AVFilmGrainParams*)frame->side_data[i]->data; + if (fgp->width && fgp->width > frame->width || + fgp->height && fgp->height > frame->height) + continue; + +#define CHECK(a, b, unspec) \ + if ((a) != (unspec) && (b) != (unspec) && (a) != (b)) \ + continue + + CHECK(fgp->bit_depth_luma, bit_depth_luma, 0); + CHECK(fgp->bit_depth_chroma, bit_depth_chroma, 0); + CHECK(fgp->color_range, frame->color_range, AVCOL_RANGE_UNSPECIFIED); + CHECK(fgp->color_primaries, frame->color_primaries, AVCOL_PRI_UNSPECIFIED); + CHECK(fgp->color_trc, frame->color_trc, AVCOL_TRC_UNSPECIFIED); + CHECK(fgp->color_space, frame->colorspace, AVCOL_SPC_UNSPECIFIED); + + switch (fgp->type) { + case AV_FILM_GRAIN_PARAMS_NONE: + continue; + case AV_FILM_GRAIN_PARAMS_AV1: + /* AOM FGS needs an exact match for the chroma resolution */ + if (fgp->subsampling_x != desc->log2_chroma_w || + fgp->subsampling_y != desc->log2_chroma_h) + continue; + break; + case AV_FILM_GRAIN_PARAMS_H274: + /* H.274 FGS can be adapted to any lower chroma resolution */ + if (fgp->subsampling_x > desc->log2_chroma_w || + fgp->subsampling_y > desc->log2_chroma_h) + continue; + break; + } + + if (!best || best->width < fgp->width || best->height < fgp->height) + best = fgp; + } + + return best; } diff --git a/media/ffvpx/libavutil/film_grain_params.h b/media/ffvpx/libavutil/film_grain_params.h index f3bd0a4a6a..ccacab88fe 100644 --- a/media/ffvpx/libavutil/film_grain_params.h +++ b/media/ffvpx/libavutil/film_grain_params.h @@ -136,20 +136,42 @@ typedef struct AVFilmGrainH274Params { */ int model_id; - /** - * Specifies the bit depth used for the luma component. - */ +#if FF_API_H274_FILM_GRAIN_VCS + /** + * TODO: On this ABI bump, please also re-order the fields in + * AVFilmGrainParams (see below) + */ + + /** + * Specifies the bit depth used for the luma component. + * + * @deprecated use AVFilmGrainParams.bit_depth_luma. + */ + attribute_deprecated int bit_depth_luma; /** * Specifies the bit depth used for the chroma components. + * + * @deprecated use AVFilmGrainParams.bit_depth_chroma. */ + attribute_deprecated int bit_depth_chroma; + /** + * Specifies the video signal characteristics. + * + * @deprecated use AVFilmGrainParams.color_{range,primaries,trc,space}. + */ + attribute_deprecated enum AVColorRange color_range; + attribute_deprecated enum AVColorPrimaries color_primaries; + attribute_deprecated enum AVColorTransferCharacteristic color_trc; + attribute_deprecated enum AVColorSpace color_space; +#endif /** * Specifies the blending mode used to blend the simulated film grain @@ -231,11 +253,40 @@ typedef struct AVFilmGrainParams { * Additional fields may be added both here and in any structure included. * If a codec's film grain structure differs slightly over another * codec's, fields within may change meaning depending on the type. + * + * TODO: Move this to the end of the structure, at the next ABI bump. */ union { AVFilmGrainAOMParams aom; AVFilmGrainH274Params h274; } codec; + + /** + * Intended display resolution. May be 0 if the codec does not specify + * any restrictions. + */ + + int width, height; + + /** + * Intended subsampling ratio, or 0 for luma-only streams. + */ + int subsampling_x, subsampling_y; + + /** + * Intended video signal characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + + /** + * Intended bit depth, or 0 for unknown/unspecified. + */ + int bit_depth_luma; + int bit_depth_chroma; + } AVFilmGrainParams; /** @@ -257,4 +308,15 @@ AVFilmGrainParams *av_film_grain_params_alloc(size_t *size); */ AVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame); +/** + * Select the most appropriate film grain parameters set for the frame, + * taking into account the frame's format, resolution and video signal + * characteristics. + * + * @note, for H.274, this may select a film grain parameter set with + * greater chroma resolution than the frame. Users should take care to + * correctly adjust the chroma grain frequency to the frame. + */ +const AVFilmGrainParams *av_film_grain_params_select(const AVFrame *frame); + #endif /* AVUTIL_FILM_GRAIN_PARAMS_H */ diff --git a/media/ffvpx/libavutil/fixed_dsp.c b/media/ffvpx/libavutil/fixed_dsp.c index 5ab47d55d0..95f0eb2595 100644 --- a/media/ffvpx/libavutil/fixed_dsp.c +++ b/media/ffvpx/libavutil/fixed_dsp.c @@ -47,6 +47,7 @@ #include "common.h" #include "fixed_dsp.h" +#include "mem.h" static void vector_fmul_add_c(int *dst, const int *src0, const int *src1, const int *src2, int len){ int i; @@ -135,7 +136,7 @@ static int scalarproduct_fixed_c(const int *v1, const int *v2, int len) return (int)(p >> 31); } -static void butterflies_fixed_c(int *av_restrict v1s, int *av_restrict v2, int len) +static void butterflies_fixed_c(int *restrict v1s, int *restrict v2, int len) { int i; unsigned int *v1 = v1s; diff --git a/media/ffvpx/libavutil/fixed_dsp.h b/media/ffvpx/libavutil/fixed_dsp.h index 1217d3a53b..9b566af675 100644 --- a/media/ffvpx/libavutil/fixed_dsp.h +++ b/media/ffvpx/libavutil/fixed_dsp.h @@ -49,7 +49,6 @@ #define AVUTIL_FIXED_DSP_H #include <stdint.h> -#include "config.h" #include "attributes.h" #include "libavcodec/mathops.h" @@ -150,7 +149,7 @@ typedef struct AVFixedDSPContext { * @param v2 second input vector, difference output, 16-byte aligned * @param len length of vectors, multiple of 4 */ - void (*butterflies_fixed)(int *av_restrict v1, int *av_restrict v2, int len); + void (*butterflies_fixed)(int *restrict v1, int *restrict v2, int len); } AVFixedDSPContext; /** diff --git a/media/ffvpx/libavutil/float_dsp.c b/media/ffvpx/libavutil/float_dsp.c index 742dd679d2..e9fb023466 100644 --- a/media/ffvpx/libavutil/float_dsp.c +++ b/media/ffvpx/libavutil/float_dsp.c @@ -109,7 +109,7 @@ static void vector_fmul_reverse_c(float *dst, const float *src0, dst[i] = src0[i] * src1[-i]; } -static void butterflies_float_c(float *av_restrict v1, float *av_restrict v2, +static void butterflies_float_c(float *restrict v1, float *restrict v2, int len) { int i; diff --git a/media/ffvpx/libavutil/float_dsp.h b/media/ffvpx/libavutil/float_dsp.h index 7cad9fc622..342a8715c5 100644 --- a/media/ffvpx/libavutil/float_dsp.h +++ b/media/ffvpx/libavutil/float_dsp.h @@ -19,8 +19,6 @@ #ifndef AVUTIL_FLOAT_DSP_H #define AVUTIL_FLOAT_DSP_H -#include "config.h" - typedef struct AVFloatDSPContext { /** * Calculate the entry wise product of two vectors of floats and store the result in @@ -161,7 +159,7 @@ typedef struct AVFloatDSPContext { * @param v2 second input vector, difference output, 16-byte aligned * @param len length of vectors, multiple of 4 */ - void (*butterflies_float)(float *av_restrict v1, float *av_restrict v2, int len); + void (*butterflies_float)(float *restrict v1, float *restrict v2, int len); /** * Calculate the scalar product of two vectors of floats. diff --git a/media/ffvpx/libavutil/frame.c b/media/ffvpx/libavutil/frame.c index a3f07ca089..930f01dc19 100644 --- a/media/ffvpx/libavutil/frame.c +++ b/media/ffvpx/libavutil/frame.c @@ -28,12 +28,35 @@ #include "samplefmt.h" #include "hwcontext.h" -#if FF_API_OLD_CHANNEL_LAYOUT -#define CHECK_CHANNELS_CONSISTENCY(frame) \ - av_assert2(!(frame)->channel_layout || \ - (frame)->channels == \ - av_get_channel_layout_nb_channels((frame)->channel_layout)) -#endif +static const AVSideDataDescriptor sd_props[] = { + [AV_FRAME_DATA_PANSCAN] = { "AVPanScan" }, + [AV_FRAME_DATA_A53_CC] = { "ATSC A53 Part 4 Closed Captions" }, + [AV_FRAME_DATA_MATRIXENCODING] = { "AVMatrixEncoding" }, + [AV_FRAME_DATA_DOWNMIX_INFO] = { "Metadata relevant to a downmix procedure" }, + [AV_FRAME_DATA_AFD] = { "Active format description" }, + [AV_FRAME_DATA_MOTION_VECTORS] = { "Motion vectors" }, + [AV_FRAME_DATA_SKIP_SAMPLES] = { "Skip samples" }, + [AV_FRAME_DATA_GOP_TIMECODE] = { "GOP timecode" }, + [AV_FRAME_DATA_S12M_TIMECODE] = { "SMPTE 12-1 timecode" }, + [AV_FRAME_DATA_DYNAMIC_HDR_PLUS] = { "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)" }, + [AV_FRAME_DATA_DYNAMIC_HDR_VIVID] = { "HDR Dynamic Metadata CUVA 005.1 2021 (Vivid)" }, + [AV_FRAME_DATA_REGIONS_OF_INTEREST] = { "Regions Of Interest" }, + [AV_FRAME_DATA_VIDEO_ENC_PARAMS] = { "Video encoding parameters" }, + [AV_FRAME_DATA_FILM_GRAIN_PARAMS] = { "Film grain parameters" }, + [AV_FRAME_DATA_DETECTION_BBOXES] = { "Bounding boxes for object detection and classification" }, + [AV_FRAME_DATA_DOVI_RPU_BUFFER] = { "Dolby Vision RPU Data" }, + [AV_FRAME_DATA_DOVI_METADATA] = { "Dolby Vision Metadata" }, + [AV_FRAME_DATA_STEREO3D] = { "Stereo 3D", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_REPLAYGAIN] = { "AVReplayGain", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_DISPLAYMATRIX] = { "3x3 displaymatrix", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_AUDIO_SERVICE_TYPE] = { "Audio service type", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_MASTERING_DISPLAY_METADATA] = { "Mastering display metadata", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_CONTENT_LIGHT_LEVEL] = { "Content light level metadata", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT] = { "Ambient viewing environment", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_SPHERICAL] = { "Spherical Mapping", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_ICC_PROFILE] = { "ICC profile", AV_SIDE_DATA_PROP_GLOBAL }, + [AV_FRAME_DATA_SEI_UNREGISTERED] = { "H.26[45] User Data Unregistered SEI message", AV_SIDE_DATA_PROP_MULTI }, +}; static void get_frame_defaults(AVFrame *frame) { @@ -43,11 +66,6 @@ static void get_frame_defaults(AVFrame *frame) frame->pkt_dts = AV_NOPTS_VALUE; frame->best_effort_timestamp = AV_NOPTS_VALUE; frame->duration = 0; -#if FF_API_PKT_DURATION -FF_DISABLE_DEPRECATION_WARNINGS - frame->pkt_duration = 0; -FF_ENABLE_DEPRECATION_WARNINGS -#endif #if FF_API_FRAME_PKT FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_pos = -1; @@ -75,14 +93,56 @@ static void free_side_data(AVFrameSideData **ptr_sd) av_freep(ptr_sd); } -static void wipe_side_data(AVFrame *frame) +static void wipe_side_data(AVFrameSideData ***sd, int *nb_side_data) { - for (int i = 0; i < frame->nb_side_data; i++) { - free_side_data(&frame->side_data[i]); + for (int i = 0; i < *nb_side_data; i++) { + free_side_data(&((*sd)[i])); } - frame->nb_side_data = 0; + *nb_side_data = 0; + + av_freep(sd); +} - av_freep(&frame->side_data); +static void frame_side_data_wipe(AVFrame *frame) +{ + wipe_side_data(&frame->side_data, &frame->nb_side_data); +} + +void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd) +{ + wipe_side_data(sd, nb_sd); +} + +static void remove_side_data(AVFrameSideData ***sd, int *nb_side_data, + const enum AVFrameSideDataType type) +{ + for (int i = *nb_side_data - 1; i >= 0; i--) { + AVFrameSideData *entry = ((*sd)[i]); + if (entry->type != type) + continue; + + free_side_data(&entry); + + ((*sd)[i]) = ((*sd)[*nb_side_data - 1]); + (*nb_side_data)--; + } +} + +static void remove_side_data_by_entry(AVFrameSideData ***sd, int *nb_sd, + const AVFrameSideData *target) +{ + for (int i = *nb_sd - 1; i >= 0; i--) { + AVFrameSideData *entry = ((*sd)[i]); + if (entry != target) + continue; + + free_side_data(&entry); + + ((*sd)[i]) = ((*sd)[*nb_sd - 1]); + (*nb_sd)--; + + return; + } } AVFrame *av_frame_alloc(void) @@ -181,21 +241,6 @@ static int get_audio_buffer(AVFrame *frame, int align) int channels, planes; int ret; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - if (!frame->ch_layout.nb_channels) { - if (frame->channel_layout) { - av_channel_layout_from_mask(&frame->ch_layout, frame->channel_layout); - } else { - frame->ch_layout.nb_channels = frame->channels; - frame->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; - } - } - frame->channels = frame->ch_layout.nb_channels; - frame->channel_layout = frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? - frame->ch_layout.u.mask : 0; -FF_ENABLE_DEPRECATION_WARNINGS -#endif channels = frame->ch_layout.nb_channels; planes = planar ? channels : 1; if (!frame->linesize[0]) { @@ -245,17 +290,11 @@ int av_frame_get_buffer(AVFrame *frame, int align) if (frame->format < 0) return AVERROR(EINVAL); -FF_DISABLE_DEPRECATION_WARNINGS if (frame->width > 0 && frame->height > 0) return get_video_buffer(frame, align); else if (frame->nb_samples > 0 && - (av_channel_layout_check(&frame->ch_layout) -#if FF_API_OLD_CHANNEL_LAYOUT - || frame->channel_layout || frame->channels > 0 -#endif - )) + (av_channel_layout_check(&frame->ch_layout))) return get_audio_buffer(frame, align); -FF_ENABLE_DEPRECATION_WARNINGS return AVERROR(EINVAL); } @@ -298,25 +337,9 @@ FF_DISABLE_DEPRECATION_WARNINGS dst->pkt_size = src->pkt_size; FF_ENABLE_DEPRECATION_WARNINGS #endif -#if FF_API_PKT_DURATION -FF_DISABLE_DEPRECATION_WARNINGS - dst->pkt_duration = src->pkt_duration; -FF_ENABLE_DEPRECATION_WARNINGS -#endif dst->time_base = src->time_base; -#if FF_API_REORDERED_OPAQUE -FF_DISABLE_DEPRECATION_WARNINGS - dst->reordered_opaque = src->reordered_opaque; -FF_ENABLE_DEPRECATION_WARNINGS -#endif dst->quality = src->quality; dst->best_effort_timestamp = src->best_effort_timestamp; -#if FF_API_FRAME_PICTURE_NUMBER -FF_DISABLE_DEPRECATION_WARNINGS - dst->coded_picture_number = src->coded_picture_number; - dst->display_picture_number = src->display_picture_number; -FF_ENABLE_DEPRECATION_WARNINGS -#endif dst->flags = src->flags; dst->decode_error_flags = src->decode_error_flags; dst->color_primaries = src->color_primaries; @@ -337,7 +360,7 @@ FF_ENABLE_DEPRECATION_WARNINGS sd_dst = av_frame_new_side_data(dst, sd_src->type, sd_src->size); if (!sd_dst) { - wipe_side_data(dst); + frame_side_data_wipe(dst); return AVERROR(ENOMEM); } memcpy(sd_dst->data, sd_src->data, sd_src->size); @@ -346,7 +369,7 @@ FF_ENABLE_DEPRECATION_WARNINGS sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref); if (!sd_dst) { av_buffer_unref(&ref); - wipe_side_data(dst); + frame_side_data_wipe(dst); return AVERROR(ENOMEM); } } @@ -363,11 +386,6 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) int ret = 0; av_assert1(dst->width == 0 && dst->height == 0); -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - av_assert1(dst->channels == 0); -FF_ENABLE_DEPRECATION_WARNINGS -#endif av_assert1(dst->ch_layout.nb_channels == 0 && dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC); @@ -375,31 +393,14 @@ FF_ENABLE_DEPRECATION_WARNINGS dst->width = src->width; dst->height = src->height; dst->nb_samples = src->nb_samples; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - dst->channels = src->channels; - dst->channel_layout = src->channel_layout; - if (!av_channel_layout_check(&src->ch_layout)) { - if (src->channel_layout) - av_channel_layout_from_mask(&dst->ch_layout, src->channel_layout); - else { - dst->ch_layout.nb_channels = src->channels; - dst->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; - } - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif ret = frame_copy_props(dst, src, 0); if (ret < 0) goto fail; - // this check is needed only until FF_API_OLD_CHANNEL_LAYOUT is out - if (av_channel_layout_check(&src->ch_layout)) { - ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); - if (ret < 0) - goto fail; - } + ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); + if (ret < 0) + goto fail; /* duplicate the frame data if it's not refcounted */ if (!src->buf[0]) { @@ -503,29 +504,12 @@ int av_frame_replace(AVFrame *dst, const AVFrame *src) dst->width = src->width; dst->height = src->height; dst->nb_samples = src->nb_samples; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - dst->channels = src->channels; - dst->channel_layout = src->channel_layout; - if (!av_channel_layout_check(&src->ch_layout)) { - av_channel_layout_uninit(&dst->ch_layout); - if (src->channel_layout) - av_channel_layout_from_mask(&dst->ch_layout, src->channel_layout); - else { - dst->ch_layout.nb_channels = src->channels; - dst->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; - } - } else { -#endif + ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); if (ret < 0) goto fail; -#if FF_API_OLD_CHANNEL_LAYOUT - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - wipe_side_data(dst); + frame_side_data_wipe(dst); av_dict_free(&dst->metadata); ret = frame_copy_props(dst, src, 0); if (ret < 0) @@ -624,7 +608,7 @@ void av_frame_unref(AVFrame *frame) if (!frame) return; - wipe_side_data(frame); + frame_side_data_wipe(frame); for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) av_buffer_unref(&frame->buf[i]); @@ -649,11 +633,6 @@ void av_frame_unref(AVFrame *frame) void av_frame_move_ref(AVFrame *dst, AVFrame *src) { av_assert1(dst->width == 0 && dst->height == 0); -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - av_assert1(dst->channels == 0); -FF_ENABLE_DEPRECATION_WARNINGS -#endif av_assert1(dst->ch_layout.nb_channels == 0 && dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC); @@ -692,12 +671,6 @@ int av_frame_make_writable(AVFrame *frame) tmp.format = frame->format; tmp.width = frame->width; tmp.height = frame->height; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - tmp.channels = frame->channels; - tmp.channel_layout = frame->channel_layout; -FF_ENABLE_DEPRECATION_WARNINGS -#endif tmp.nb_samples = frame->nb_samples; ret = av_channel_layout_copy(&tmp.ch_layout, &frame->ch_layout); if (ret < 0) { @@ -745,15 +718,6 @@ AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane) if (frame->nb_samples) { int channels = frame->ch_layout.nb_channels; - -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - if (!channels) { - channels = frame->channels; - CHECK_CHANNELS_CONSISTENCY(frame); - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (!channels) return NULL; planes = av_sample_fmt_is_planar(frame->format) ? channels : 1; @@ -777,38 +741,57 @@ FF_ENABLE_DEPRECATION_WARNINGS return NULL; } -AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, - enum AVFrameSideDataType type, - AVBufferRef *buf) +static AVFrameSideData *add_side_data_from_buf_ext(AVFrameSideData ***sd, + int *nb_sd, + enum AVFrameSideDataType type, + AVBufferRef *buf, uint8_t *data, + size_t size) { AVFrameSideData *ret, **tmp; - if (!buf) - return NULL; - - if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1) + // *nb_sd + 1 needs to fit into an int and a size_t. + if ((unsigned)*nb_sd >= FFMIN(INT_MAX, SIZE_MAX)) return NULL; - tmp = av_realloc(frame->side_data, - (frame->nb_side_data + 1) * sizeof(*frame->side_data)); + tmp = av_realloc_array(*sd, sizeof(**sd), *nb_sd + 1); if (!tmp) return NULL; - frame->side_data = tmp; + *sd = tmp; ret = av_mallocz(sizeof(*ret)); if (!ret) return NULL; ret->buf = buf; - ret->data = ret->buf->data; - ret->size = buf->size; + ret->data = data; + ret->size = size; ret->type = type; - frame->side_data[frame->nb_side_data++] = ret; + (*sd)[(*nb_sd)++] = ret; return ret; } +static AVFrameSideData *add_side_data_from_buf(AVFrameSideData ***sd, + int *nb_sd, + enum AVFrameSideDataType type, + AVBufferRef *buf) +{ + if (!buf) + return NULL; + + return add_side_data_from_buf_ext(sd, nb_sd, type, buf, buf->data, buf->size); +} + +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf) +{ + return + add_side_data_from_buf( + &frame->side_data, &frame->nb_side_data, type, buf); +} + AVFrameSideData *av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, size_t size) @@ -821,16 +804,76 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame, return ret; } -AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, - enum AVFrameSideDataType type) +AVFrameSideData *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd, + enum AVFrameSideDataType type, + size_t size, unsigned int flags) +{ + AVBufferRef *buf = av_buffer_alloc(size); + AVFrameSideData *ret = NULL; + + if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE) + remove_side_data(sd, nb_sd, type); + + ret = add_side_data_from_buf(sd, nb_sd, type, buf); + if (!ret) + av_buffer_unref(&buf); + + return ret; +} + +int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd, + const AVFrameSideData *src, unsigned int flags) +{ + AVBufferRef *buf = NULL; + AVFrameSideData *sd_dst = NULL; + int ret = AVERROR_BUG; + + if (!sd || !src || !nb_sd || (*nb_sd && !*sd)) + return AVERROR(EINVAL); + + buf = av_buffer_ref(src->buf); + if (!buf) + return AVERROR(ENOMEM); + + if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE) + remove_side_data(sd, nb_sd, src->type); + + sd_dst = add_side_data_from_buf_ext(sd, nb_sd, src->type, buf, + src->data, src->size); + if (!sd_dst) { + av_buffer_unref(&buf); + return AVERROR(ENOMEM); + } + + ret = av_dict_copy(&sd_dst->metadata, src->metadata, 0); + if (ret < 0) { + remove_side_data_by_entry(sd, nb_sd, sd_dst); + return ret; + } + + return 0; +} + +const AVFrameSideData *av_frame_side_data_get_c(const AVFrameSideData * const *sd, + const int nb_sd, + enum AVFrameSideDataType type) { - for (int i = 0; i < frame->nb_side_data; i++) { - if (frame->side_data[i]->type == type) - return frame->side_data[i]; + for (int i = 0; i < nb_sd; i++) { + if (sd[i]->type == type) + return sd[i]; } return NULL; } +AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, + enum AVFrameSideDataType type) +{ + return (AVFrameSideData *)av_frame_side_data_get( + frame->side_data, frame->nb_side_data, + type + ); +} + static int frame_copy_video(AVFrame *dst, const AVFrame *src) { int planes; @@ -860,30 +903,8 @@ static int frame_copy_audio(AVFrame *dst, const AVFrame *src) int channels = dst->ch_layout.nb_channels; int planes = planar ? channels : 1; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - if (!channels || !src->ch_layout.nb_channels) { - if (dst->channels != src->channels || - dst->channel_layout != src->channel_layout) - return AVERROR(EINVAL); - CHECK_CHANNELS_CONSISTENCY(src); - } - if (!channels) { - channels = dst->channels; - planes = planar ? channels : 1; - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (dst->nb_samples != src->nb_samples || -#if FF_API_OLD_CHANNEL_LAYOUT - (av_channel_layout_check(&dst->ch_layout) && - av_channel_layout_check(&src->ch_layout) && -#endif av_channel_layout_compare(&dst->ch_layout, &src->ch_layout)) -#if FF_API_OLD_CHANNEL_LAYOUT - ) -#endif return AVERROR(EINVAL); for (int i = 0; i < planes; i++) @@ -901,67 +922,34 @@ int av_frame_copy(AVFrame *dst, const AVFrame *src) if (dst->format != src->format || dst->format < 0) return AVERROR(EINVAL); -FF_DISABLE_DEPRECATION_WARNINGS if (dst->width > 0 && dst->height > 0) return frame_copy_video(dst, src); else if (dst->nb_samples > 0 && - (av_channel_layout_check(&dst->ch_layout) -#if FF_API_OLD_CHANNEL_LAYOUT - || dst->channels > 0 -#endif - )) + (av_channel_layout_check(&dst->ch_layout))) return frame_copy_audio(dst, src); -FF_ENABLE_DEPRECATION_WARNINGS return AVERROR(EINVAL); } void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) { - for (int i = frame->nb_side_data - 1; i >= 0; i--) { - AVFrameSideData *sd = frame->side_data[i]; - if (sd->type == type) { - free_side_data(&frame->side_data[i]); - frame->side_data[i] = frame->side_data[frame->nb_side_data - 1]; - frame->nb_side_data--; - } - } + remove_side_data(&frame->side_data, &frame->nb_side_data, type); } -const char *av_frame_side_data_name(enum AVFrameSideDataType type) +const AVSideDataDescriptor *av_frame_side_data_desc(enum AVFrameSideDataType type) { - switch(type) { - case AV_FRAME_DATA_PANSCAN: return "AVPanScan"; - case AV_FRAME_DATA_A53_CC: return "ATSC A53 Part 4 Closed Captions"; - case AV_FRAME_DATA_STEREO3D: return "Stereo 3D"; - case AV_FRAME_DATA_MATRIXENCODING: return "AVMatrixEncoding"; - case AV_FRAME_DATA_DOWNMIX_INFO: return "Metadata relevant to a downmix procedure"; - case AV_FRAME_DATA_REPLAYGAIN: return "AVReplayGain"; - case AV_FRAME_DATA_DISPLAYMATRIX: return "3x3 displaymatrix"; - case AV_FRAME_DATA_AFD: return "Active format description"; - case AV_FRAME_DATA_MOTION_VECTORS: return "Motion vectors"; - case AV_FRAME_DATA_SKIP_SAMPLES: return "Skip samples"; - case AV_FRAME_DATA_AUDIO_SERVICE_TYPE: return "Audio service type"; - case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata"; - case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: return "Content light level metadata"; - case AV_FRAME_DATA_GOP_TIMECODE: return "GOP timecode"; - case AV_FRAME_DATA_S12M_TIMECODE: return "SMPTE 12-1 timecode"; - case AV_FRAME_DATA_SPHERICAL: return "Spherical Mapping"; - case AV_FRAME_DATA_ICC_PROFILE: return "ICC profile"; - case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)"; - case AV_FRAME_DATA_DYNAMIC_HDR_VIVID: return "HDR Dynamic Metadata CUVA 005.1 2021 (Vivid)"; - case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest"; - case AV_FRAME_DATA_VIDEO_ENC_PARAMS: return "Video encoding parameters"; - case AV_FRAME_DATA_SEI_UNREGISTERED: return "H.26[45] User Data Unregistered SEI message"; - case AV_FRAME_DATA_FILM_GRAIN_PARAMS: return "Film grain parameters"; - case AV_FRAME_DATA_DETECTION_BBOXES: return "Bounding boxes for object detection and classification"; - case AV_FRAME_DATA_DOVI_RPU_BUFFER: return "Dolby Vision RPU Data"; - case AV_FRAME_DATA_DOVI_METADATA: return "Dolby Vision Metadata"; - case AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT: return "Ambient viewing environment"; - } + unsigned t = type; + if (t < FF_ARRAY_ELEMS(sd_props) && sd_props[t].name) + return &sd_props[t]; return NULL; } +const char *av_frame_side_data_name(enum AVFrameSideDataType type) +{ + const AVSideDataDescriptor *desc = av_frame_side_data_desc(type); + return desc ? desc->name : NULL; +} + static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, const AVPixFmtDescriptor *desc) { diff --git a/media/ffvpx/libavutil/frame.h b/media/ffvpx/libavutil/frame.h index c0c1b23db7..3b6d746a16 100644 --- a/media/ffvpx/libavutil/frame.h +++ b/media/ffvpx/libavutil/frame.h @@ -180,6 +180,10 @@ enum AVFrameSideDataType { /** * Film grain parameters for a frame, described by AVFilmGrainParams. * Must be present for every frame which should have film grain applied. + * + * May be present multiple times, for example when there are multiple + * alternative parameter sets for different video signal characteristics. + * The user should select the most appropriate set for the application. */ AV_FRAME_DATA_FILM_GRAIN_PARAMS, @@ -251,6 +255,37 @@ typedef struct AVFrameSideData { AVBufferRef *buf; } AVFrameSideData; +enum AVSideDataProps { + /** + * The side data type can be used in stream-global structures. + * Side data types without this property are only meaningful on per-frame + * basis. + */ + AV_SIDE_DATA_PROP_GLOBAL = (1 << 0), + + /** + * Multiple instances of this side data type can be meaningfully present in + * a single side data array. + */ + AV_SIDE_DATA_PROP_MULTI = (1 << 1), +}; + +/** + * This struct describes the properties of a side data type. Its instance + * corresponding to a given type can be obtained from av_frame_side_data_desc(). + */ +typedef struct AVSideDataDescriptor { + /** + * Human-readable side data description. + */ + const char *name; + + /** + * Side data property flags, a combination of AVSideDataProps values. + */ + unsigned props; +} AVSideDataDescriptor; + /** * Structure describing a single Region Of Interest. * @@ -466,19 +501,6 @@ typedef struct AVFrame { */ AVRational time_base; -#if FF_API_FRAME_PICTURE_NUMBER - /** - * picture number in bitstream order - */ - attribute_deprecated - int coded_picture_number; - /** - * picture number in display order - */ - attribute_deprecated - int display_picture_number; -#endif - /** * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) */ @@ -546,35 +568,11 @@ typedef struct AVFrame { int palette_has_changed; #endif -#if FF_API_REORDERED_OPAQUE - /** - * reordered opaque 64 bits (generally an integer or a double precision float - * PTS but can be anything). - * The user sets AVCodecContext.reordered_opaque to represent the input at - * that time, - * the decoder reorders values as needed and sets AVFrame.reordered_opaque - * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque - * - * @deprecated Use AV_CODEC_FLAG_COPY_OPAQUE instead - */ - attribute_deprecated - int64_t reordered_opaque; -#endif - /** * Sample rate of the audio data. */ int sample_rate; -#if FF_API_OLD_CHANNEL_LAYOUT - /** - * Channel layout of the audio data. - * @deprecated use ch_layout instead - */ - attribute_deprecated - uint64_t channel_layout; -#endif - /** * AVBuffer references backing the data for this frame. All the pointers in * data and extended_data must point inside one of the buffers in buf or @@ -687,19 +685,6 @@ typedef struct AVFrame { int64_t pkt_pos; #endif -#if FF_API_PKT_DURATION - /** - * duration of the corresponding packet, expressed in - * AVStream->time_base units, 0 if unknown. - * - encoding: unused - * - decoding: Read by user. - * - * @deprecated use duration instead - */ - attribute_deprecated - int64_t pkt_duration; -#endif - /** * metadata. * - encoding: Set by user. @@ -720,17 +705,6 @@ typedef struct AVFrame { #define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 #define FF_DECODE_ERROR_DECODE_SLICES 8 -#if FF_API_OLD_CHANNEL_LAYOUT - /** - * number of audio channels, only used for audio. - * - encoding: unused - * - decoding: Read by user. - * @deprecated use ch_layout instead - */ - attribute_deprecated - int channels; -#endif - #if FF_API_FRAME_PKT /** * size of the corresponding packet containing the compressed @@ -1050,6 +1024,94 @@ int av_frame_apply_cropping(AVFrame *frame, int flags); const char *av_frame_side_data_name(enum AVFrameSideDataType type); /** + * @return side data descriptor corresponding to a given side data type, NULL + * when not available. + */ +const AVSideDataDescriptor *av_frame_side_data_desc(enum AVFrameSideDataType type); + +/** + * Free all side data entries and their contents, then zeroes out the + * values which the pointers are pointing to. + * + * @param sd pointer to array of side data to free. Will be set to NULL + * upon return. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be set to 0 upon return. + */ +void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd); + +#define AV_FRAME_SIDE_DATA_FLAG_UNIQUE (1 << 0) + +/** + * Add new side data entry to an array. + * + * @param sd pointer to array of side data to which to add another entry, + * or to NULL in order to start a new array. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. + * @param type type of the added side data + * @param size size of the side data + * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0. + * + * @return newly added side data on success, NULL on error. In case of + * AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of matching + * AVFrameSideDataType will be removed before the addition is + * attempted. + */ +AVFrameSideData *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd, + enum AVFrameSideDataType type, + size_t size, unsigned int flags); + +/** + * Add a new side data entry to an array based on existing side data, taking + * a reference towards the contained AVBufferRef. + * + * @param sd pointer to array of side data to which to add another entry, + * or to NULL in order to start a new array. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. + * @param src side data to be cloned, with a new reference utilized + * for the buffer. + * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0. + * + * @return negative error code on failure, >=0 on success. In case of + * AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of matching + * AVFrameSideDataType will be removed before the addition is + * attempted. + */ +int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd, + const AVFrameSideData *src, unsigned int flags); + +/** + * Get a side data entry of a specific type from an array. + * + * @param sd array of side data. + * @param nb_sd integer containing the number of entries in the array. + * @param type type of side data to be queried + * + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this set. + */ +const AVFrameSideData *av_frame_side_data_get_c(const AVFrameSideData * const *sd, + const int nb_sd, + enum AVFrameSideDataType type); + +/** + * Wrapper around av_frame_side_data_get_c() to workaround the limitation + * that for any type T the conversion from T * const * to const T * const * + * is not performed automatically in C. + * @see av_frame_side_data_get_c() + */ +static inline +const AVFrameSideData *av_frame_side_data_get(AVFrameSideData * const *sd, + const int nb_sd, + enum AVFrameSideDataType type) +{ + return av_frame_side_data_get_c((const AVFrameSideData * const *)sd, + nb_sd, type); +} + +/** * @} */ diff --git a/media/ffvpx/libavutil/hdr_dynamic_metadata.h b/media/ffvpx/libavutil/hdr_dynamic_metadata.h index 09e9d8bbcc..5100ed6f41 100644 --- a/media/ffvpx/libavutil/hdr_dynamic_metadata.h +++ b/media/ffvpx/libavutil/hdr_dynamic_metadata.h @@ -359,13 +359,13 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data, * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer, * excluding the first 48 bytes of the header, and beginning with the application mode. * @param s A pointer containing the decoded AVDynamicHDRPlus structure. - * @param data[in,out] A pointer to pointer to a byte buffer to be filled with the + * @param[in,out] data A pointer to pointer to a byte buffer to be filled with the * serialized metadata. * If *data is NULL, a buffer be will be allocated and a pointer to * it stored in its place. The caller assumes ownership of the buffer. * May be NULL, in which case the function will only store the * required buffer size in *size. - * @param size[in,out] A pointer to a size to be set to the returned buffer's size. + * @param[in,out] size A pointer to a size to be set to the returned buffer's size. * If *data is not NULL, *size must contain the size of the input * buffer. May be NULL only if *data is NULL. * diff --git a/media/ffvpx/libavutil/hwcontext.c b/media/ffvpx/libavutil/hwcontext.c index e23bad230f..fa99a0d8a4 100644 --- a/media/ffvpx/libavutil/hwcontext.c +++ b/media/ffvpx/libavutil/hwcontext.c @@ -84,6 +84,21 @@ static const char *const hw_type_names[] = { [AV_HWDEVICE_TYPE_VULKAN] = "vulkan", }; +typedef struct FFHWDeviceContext { + /** + * The public AVHWDeviceContext. See hwcontext.h for it. + */ + AVHWDeviceContext p; + + const HWContextType *hw_type; + + /** + * For a derived device, a reference to the original device + * context it was derived from. + */ + AVBufferRef *source_device; +} FFHWDeviceContext; + enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name) { int type; @@ -126,26 +141,26 @@ static const AVClass hwdevice_ctx_class = { static void hwdevice_ctx_free(void *opaque, uint8_t *data) { - AVHWDeviceContext *ctx = (AVHWDeviceContext*)data; + FFHWDeviceContext *ctxi = (FFHWDeviceContext*)data; + AVHWDeviceContext *ctx = &ctxi->p; /* uninit might still want access the hw context and the user * free() callback might destroy it, so uninit has to be called first */ - if (ctx->internal->hw_type->device_uninit) - ctx->internal->hw_type->device_uninit(ctx); + if (ctxi->hw_type->device_uninit) + ctxi->hw_type->device_uninit(ctx); if (ctx->free) ctx->free(ctx); - av_buffer_unref(&ctx->internal->source_device); + av_buffer_unref(&ctxi->source_device); av_freep(&ctx->hwctx); - av_freep(&ctx->internal->priv); - av_freep(&ctx->internal); av_freep(&ctx); } AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type) { + FFHWDeviceContext *ctxi; AVHWDeviceContext *ctx; AVBufferRef *buf; const HWContextType *hw_type = NULL; @@ -160,19 +175,10 @@ AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type) if (!hw_type) return NULL; - ctx = av_mallocz(sizeof(*ctx)); - if (!ctx) + ctxi = av_mallocz(sizeof(*ctxi)); + if (!ctxi) return NULL; - - ctx->internal = av_mallocz(sizeof(*ctx->internal)); - if (!ctx->internal) - goto fail; - - if (hw_type->device_priv_size) { - ctx->internal->priv = av_mallocz(hw_type->device_priv_size); - if (!ctx->internal->priv) - goto fail; - } + ctx = &ctxi->p; if (hw_type->device_hwctx_size) { ctx->hwctx = av_mallocz(hw_type->device_hwctx_size); @@ -189,14 +195,11 @@ AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type) ctx->type = type; ctx->av_class = &hwdevice_ctx_class; - ctx->internal->hw_type = hw_type; + ctxi->hw_type = hw_type; return buf; fail: - if (ctx->internal) - av_freep(&ctx->internal->priv); - av_freep(&ctx->internal); av_freep(&ctx->hwctx); av_freep(&ctx); return NULL; @@ -204,19 +207,13 @@ fail: int av_hwdevice_ctx_init(AVBufferRef *ref) { - AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data; - int ret; + FFHWDeviceContext *ctxi = (FFHWDeviceContext*)ref->data; + AVHWDeviceContext *ctx = &ctxi->p; + int ret = 0; - if (ctx->internal->hw_type->device_init) { - ret = ctx->internal->hw_type->device_init(ctx); - if (ret < 0) - goto fail; - } + if (ctxi->hw_type->device_init) + ret = ctxi->hw_type->device_init(ctx); - return 0; -fail: - if (ctx->internal->hw_type->device_uninit) - ctx->internal->hw_type->device_uninit(ctx); return ret; } @@ -228,47 +225,38 @@ static const AVClass hwframe_ctx_class = { static void hwframe_ctx_free(void *opaque, uint8_t *data) { - AVHWFramesContext *ctx = (AVHWFramesContext*)data; + FFHWFramesContext *ctxi = (FFHWFramesContext*)data; + AVHWFramesContext *ctx = &ctxi->p; - if (ctx->internal->pool_internal) - av_buffer_pool_uninit(&ctx->internal->pool_internal); + if (ctxi->pool_internal) + av_buffer_pool_uninit(&ctxi->pool_internal); - if (ctx->internal->hw_type->frames_uninit) - ctx->internal->hw_type->frames_uninit(ctx); + if (ctxi->hw_type->frames_uninit) + ctxi->hw_type->frames_uninit(ctx); if (ctx->free) ctx->free(ctx); - av_buffer_unref(&ctx->internal->source_frames); + av_buffer_unref(&ctxi->source_frames); av_buffer_unref(&ctx->device_ref); av_freep(&ctx->hwctx); - av_freep(&ctx->internal->priv); - av_freep(&ctx->internal); av_freep(&ctx); } AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in) { - AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data; - const HWContextType *hw_type = device_ctx->internal->hw_type; + FFHWDeviceContext *device_ctx = (FFHWDeviceContext*)device_ref_in->data; + const HWContextType *hw_type = device_ctx->hw_type; + FFHWFramesContext *ctxi; AVHWFramesContext *ctx; AVBufferRef *buf, *device_ref = NULL; - ctx = av_mallocz(sizeof(*ctx)); - if (!ctx) + ctxi = av_mallocz(sizeof(*ctxi)); + if (!ctxi) return NULL; - - ctx->internal = av_mallocz(sizeof(*ctx->internal)); - if (!ctx->internal) - goto fail; - - if (hw_type->frames_priv_size) { - ctx->internal->priv = av_mallocz(hw_type->frames_priv_size); - if (!ctx->internal->priv) - goto fail; - } + ctx = &ctxi->p; if (hw_type->frames_hwctx_size) { ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size); @@ -288,20 +276,16 @@ AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in) ctx->av_class = &hwframe_ctx_class; ctx->device_ref = device_ref; - ctx->device_ctx = device_ctx; + ctx->device_ctx = &device_ctx->p; ctx->format = AV_PIX_FMT_NONE; ctx->sw_format = AV_PIX_FMT_NONE; - ctx->internal->hw_type = hw_type; + ctxi->hw_type = hw_type; return buf; fail: - if (device_ref) - av_buffer_unref(&device_ref); - if (ctx->internal) - av_freep(&ctx->internal->priv); - av_freep(&ctx->internal); + av_buffer_unref(&device_ref); av_freep(&ctx->hwctx); av_freep(&ctx); return NULL; @@ -337,24 +321,25 @@ fail: int av_hwframe_ctx_init(AVBufferRef *ref) { - AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data; + FFHWFramesContext *ctxi = (FFHWFramesContext*)ref->data; + AVHWFramesContext *ctx = &ctxi->p; const enum AVPixelFormat *pix_fmt; int ret; - if (ctx->internal->source_frames) { + if (ctxi->source_frames) { /* A derived frame context is already initialised. */ return 0; } /* validate the pixel format */ - for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) { + for (pix_fmt = ctxi->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) { if (*pix_fmt == ctx->format) break; } if (*pix_fmt == AV_PIX_FMT_NONE) { av_log(ctx, AV_LOG_ERROR, "The hardware pixel format '%s' is not supported by the device type '%s'\n", - av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name); + av_get_pix_fmt_name(ctx->format), ctxi->hw_type->name); return AVERROR(ENOSYS); } @@ -364,39 +349,35 @@ int av_hwframe_ctx_init(AVBufferRef *ref) return ret; /* format-specific init */ - if (ctx->internal->hw_type->frames_init) { - ret = ctx->internal->hw_type->frames_init(ctx); + if (ctxi->hw_type->frames_init) { + ret = ctxi->hw_type->frames_init(ctx); if (ret < 0) - goto fail; + return ret; } - if (ctx->internal->pool_internal && !ctx->pool) - ctx->pool = ctx->internal->pool_internal; + if (ctxi->pool_internal && !ctx->pool) + ctx->pool = ctxi->pool_internal; /* preallocate the frames in the pool, if requested */ if (ctx->initial_pool_size > 0) { ret = hwframe_pool_prealloc(ref); if (ret < 0) - goto fail; + return ret; } return 0; -fail: - if (ctx->internal->hw_type->frames_uninit) - ctx->internal->hw_type->frames_uninit(ctx); - return ret; } int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats, int flags) { - AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data; + FFHWFramesContext *ctxi = (FFHWFramesContext*)hwframe_ref->data; - if (!ctx->internal->hw_type->transfer_get_formats) + if (!ctxi->hw_type->transfer_get_formats) return AVERROR(ENOSYS); - return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats); + return ctxi->hw_type->transfer_get_formats(&ctxi->p, dir, formats); } static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags) @@ -451,7 +432,6 @@ fail: int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags) { - AVHWFramesContext *ctx; int ret; if (!dst->buf[0]) @@ -464,41 +444,41 @@ int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags) * the specific combination of hardware. */ if (src->hw_frames_ctx && dst->hw_frames_ctx) { - AVHWFramesContext *src_ctx = - (AVHWFramesContext*)src->hw_frames_ctx->data; - AVHWFramesContext *dst_ctx = - (AVHWFramesContext*)dst->hw_frames_ctx->data; + FFHWFramesContext *src_ctx = + (FFHWFramesContext*)src->hw_frames_ctx->data; + FFHWFramesContext *dst_ctx = + (FFHWFramesContext*)dst->hw_frames_ctx->data; - if (src_ctx->internal->source_frames) { + if (src_ctx->source_frames) { av_log(src_ctx, AV_LOG_ERROR, "A device with a derived frame context cannot be used as " "the source of a HW -> HW transfer."); return AVERROR(ENOSYS); } - if (dst_ctx->internal->source_frames) { + if (dst_ctx->source_frames) { av_log(src_ctx, AV_LOG_ERROR, "A device with a derived frame context cannot be used as " "the destination of a HW -> HW transfer."); return AVERROR(ENOSYS); } - ret = src_ctx->internal->hw_type->transfer_data_from(src_ctx, dst, src); + ret = src_ctx->hw_type->transfer_data_from(&src_ctx->p, dst, src); if (ret == AVERROR(ENOSYS)) - ret = dst_ctx->internal->hw_type->transfer_data_to(dst_ctx, dst, src); + ret = dst_ctx->hw_type->transfer_data_to(&dst_ctx->p, dst, src); if (ret < 0) return ret; } else { if (src->hw_frames_ctx) { - ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; + FFHWFramesContext *ctx = (FFHWFramesContext*)src->hw_frames_ctx->data; - ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src); + ret = ctx->hw_type->transfer_data_from(&ctx->p, dst, src); if (ret < 0) return ret; } else if (dst->hw_frames_ctx) { - ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data; + FFHWFramesContext *ctx = (FFHWFramesContext*)dst->hw_frames_ctx->data; - ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src); + ret = ctx->hw_type->transfer_data_to(&ctx->p, dst, src); if (ret < 0) return ret; } else { @@ -510,10 +490,11 @@ int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags) int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) { - AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data; + FFHWFramesContext *ctxi = (FFHWFramesContext*)hwframe_ref->data; + AVHWFramesContext *ctx = &ctxi->p; int ret; - if (ctx->internal->source_frames) { + if (ctxi->source_frames) { // This is a derived frame context, so we allocate in the source // and map the frame immediately. AVFrame *src_frame; @@ -527,7 +508,7 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) if (!src_frame) return AVERROR(ENOMEM); - ret = av_hwframe_get_buffer(ctx->internal->source_frames, + ret = av_hwframe_get_buffer(ctxi->source_frames, src_frame, 0); if (ret < 0) { av_frame_free(&src_frame); @@ -535,7 +516,7 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) } ret = av_hwframe_map(frame, src_frame, - ctx->internal->source_allocation_map_flags); + ctxi->source_allocation_map_flags); if (ret) { av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived " "frame context: %d.\n", ret); @@ -550,7 +531,7 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) return 0; } - if (!ctx->internal->hw_type->frames_get_buffer) + if (!ctxi->hw_type->frames_get_buffer) return AVERROR(ENOSYS); if (!ctx->pool) @@ -560,7 +541,7 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) if (!frame->hw_frames_ctx) return AVERROR(ENOMEM); - ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame); + ret = ctxi->hw_type->frames_get_buffer(ctx, frame); if (ret < 0) { av_buffer_unref(&frame->hw_frames_ctx); return ret; @@ -573,8 +554,8 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref) { - AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data; - const HWContextType *hw_type = ctx->internal->hw_type; + FFHWDeviceContext *ctx = (FFHWDeviceContext*)ref->data; + const HWContextType *hw_type = ctx->hw_type; if (hw_type->device_hwconfig_size == 0) return NULL; @@ -585,8 +566,8 @@ void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref) AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, const void *hwconfig) { - AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data; - const HWContextType *hw_type = ctx->internal->hw_type; + FFHWDeviceContext *ctx = (FFHWDeviceContext*)ref->data; + const HWContextType *hw_type = ctx->hw_type; AVHWFramesConstraints *constraints; if (!hw_type->frames_get_constraints) @@ -599,7 +580,7 @@ AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, constraints->min_width = constraints->min_height = 0; constraints->max_width = constraints->max_height = INT_MAX; - if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) { + if (hw_type->frames_get_constraints(&ctx->p, hwconfig, constraints) >= 0) { return constraints; } else { av_hwframe_constraints_free(&constraints); @@ -620,7 +601,7 @@ int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags) { AVBufferRef *device_ref = NULL; - AVHWDeviceContext *device_ctx; + FFHWDeviceContext *device_ctx; int ret = 0; device_ref = av_hwdevice_ctx_alloc(type); @@ -628,15 +609,15 @@ int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, ret = AVERROR(ENOMEM); goto fail; } - device_ctx = (AVHWDeviceContext*)device_ref->data; + device_ctx = (FFHWDeviceContext*)device_ref->data; - if (!device_ctx->internal->hw_type->device_create) { + if (!device_ctx->hw_type->device_create) { ret = AVERROR(ENOSYS); goto fail; } - ret = device_ctx->internal->hw_type->device_create(device_ctx, device, - opts, flags); + ret = device_ctx->hw_type->device_create(&device_ctx->p, device, + opts, flags); if (ret < 0) goto fail; @@ -658,13 +639,13 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, AVDictionary *options, int flags) { AVBufferRef *dst_ref = NULL, *tmp_ref; - AVHWDeviceContext *dst_ctx, *tmp_ctx; + FFHWDeviceContext *dst_ctx; int ret = 0; tmp_ref = src_ref; while (tmp_ref) { - tmp_ctx = (AVHWDeviceContext*)tmp_ref->data; - if (tmp_ctx->type == type) { + FFHWDeviceContext *tmp_ctx = (FFHWDeviceContext*)tmp_ref->data; + if (tmp_ctx->p.type == type) { dst_ref = av_buffer_ref(tmp_ref); if (!dst_ref) { ret = AVERROR(ENOMEM); @@ -672,7 +653,7 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, } goto done; } - tmp_ref = tmp_ctx->internal->source_device; + tmp_ref = tmp_ctx->source_device; } dst_ref = av_hwdevice_ctx_alloc(type); @@ -680,19 +661,18 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, ret = AVERROR(ENOMEM); goto fail; } - dst_ctx = (AVHWDeviceContext*)dst_ref->data; + dst_ctx = (FFHWDeviceContext*)dst_ref->data; tmp_ref = src_ref; while (tmp_ref) { - tmp_ctx = (AVHWDeviceContext*)tmp_ref->data; - if (dst_ctx->internal->hw_type->device_derive) { - ret = dst_ctx->internal->hw_type->device_derive(dst_ctx, - tmp_ctx, - options, - flags); + FFHWDeviceContext *tmp_ctx = (FFHWDeviceContext*)tmp_ref->data; + if (dst_ctx->hw_type->device_derive) { + ret = dst_ctx->hw_type->device_derive(&dst_ctx->p, + &tmp_ctx->p, + options, flags); if (ret == 0) { - dst_ctx->internal->source_device = av_buffer_ref(src_ref); - if (!dst_ctx->internal->source_device) { + dst_ctx->source_device = av_buffer_ref(src_ref); + if (!dst_ctx->source_device) { ret = AVERROR(ENOMEM); goto fail; } @@ -704,7 +684,7 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, if (ret != AVERROR(ENOSYS)) goto fail; } - tmp_ref = tmp_ctx->internal->source_device; + tmp_ref = tmp_ctx->source_device; } ret = AVERROR(ENOSYS); @@ -799,19 +779,18 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags) { AVBufferRef *orig_dst_frames = dst->hw_frames_ctx; enum AVPixelFormat orig_dst_fmt = dst->format; - AVHWFramesContext *src_frames, *dst_frames; HWMapDescriptor *hwmap; int ret; if (src->hw_frames_ctx && dst->hw_frames_ctx) { - src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data; - dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data; + FFHWFramesContext *src_frames = (FFHWFramesContext*)src->hw_frames_ctx->data; + FFHWFramesContext *dst_frames = (FFHWFramesContext*)dst->hw_frames_ctx->data; if ((src_frames == dst_frames && - src->format == dst_frames->sw_format && - dst->format == dst_frames->format) || - (src_frames->internal->source_frames && - src_frames->internal->source_frames->data == + src->format == dst_frames->p.sw_format && + dst->format == dst_frames->p.format) || + (src_frames->source_frames && + src_frames->source_frames->data == (uint8_t*)dst_frames)) { // This is an unmap operation. We don't need to directly // do anything here other than fill in the original frame, @@ -828,12 +807,12 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags) } if (src->hw_frames_ctx) { - src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data; + FFHWFramesContext *src_frames = (FFHWFramesContext*)src->hw_frames_ctx->data; - if (src_frames->format == src->format && - src_frames->internal->hw_type->map_from) { - ret = src_frames->internal->hw_type->map_from(src_frames, - dst, src, flags); + if (src_frames->p.format == src->format && + src_frames->hw_type->map_from) { + ret = src_frames->hw_type->map_from(&src_frames->p, + dst, src, flags); if (ret >= 0) return ret; else if (ret != AVERROR(ENOSYS)) @@ -842,12 +821,12 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags) } if (dst->hw_frames_ctx) { - dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data; + FFHWFramesContext *dst_frames = (FFHWFramesContext*)dst->hw_frames_ctx->data; - if (dst_frames->format == dst->format && - dst_frames->internal->hw_type->map_to) { - ret = dst_frames->internal->hw_type->map_to(dst_frames, - dst, src, flags); + if (dst_frames->p.format == dst->format && + dst_frames->hw_type->map_to) { + ret = dst_frames->hw_type->map_to(&dst_frames->p, + dst, src, flags); if (ret >= 0) return ret; else if (ret != AVERROR(ENOSYS)) @@ -881,21 +860,21 @@ int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, int flags) { AVBufferRef *dst_ref = NULL; - AVHWFramesContext *dst = NULL; - AVHWFramesContext *src = (AVHWFramesContext*)source_frame_ctx->data; + FFHWFramesContext *dsti = NULL; + FFHWFramesContext *srci = (FFHWFramesContext*)source_frame_ctx->data; + AVHWFramesContext *dst, *src = &srci->p; int ret; - if (src->internal->source_frames) { + if (srci->source_frames) { AVHWFramesContext *src_src = - (AVHWFramesContext*)src->internal->source_frames->data; + (AVHWFramesContext*)srci->source_frames->data; AVHWDeviceContext *dst_dev = (AVHWDeviceContext*)derived_device_ctx->data; if (src_src->device_ctx == dst_dev) { // This is actually an unmapping, so we just return a // reference to the source frame context. - *derived_frame_ctx = - av_buffer_ref(src->internal->source_frames); + *derived_frame_ctx = av_buffer_ref(srci->source_frames); if (!*derived_frame_ctx) { ret = AVERROR(ENOMEM); goto fail; @@ -910,31 +889,32 @@ int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, goto fail; } - dst = (AVHWFramesContext*)dst_ref->data; + dsti = (FFHWFramesContext*)dst_ref->data; + dst = &dsti->p; dst->format = format; dst->sw_format = src->sw_format; dst->width = src->width; dst->height = src->height; - dst->internal->source_frames = av_buffer_ref(source_frame_ctx); - if (!dst->internal->source_frames) { + dsti->source_frames = av_buffer_ref(source_frame_ctx); + if (!dsti->source_frames) { ret = AVERROR(ENOMEM); goto fail; } - dst->internal->source_allocation_map_flags = + dsti->source_allocation_map_flags = flags & (AV_HWFRAME_MAP_READ | AV_HWFRAME_MAP_WRITE | AV_HWFRAME_MAP_OVERWRITE | AV_HWFRAME_MAP_DIRECT); ret = AVERROR(ENOSYS); - if (src->internal->hw_type->frames_derive_from) - ret = src->internal->hw_type->frames_derive_from(dst, src, flags); + if (srci->hw_type->frames_derive_from) + ret = srci->hw_type->frames_derive_from(dst, src, flags); if (ret == AVERROR(ENOSYS) && - dst->internal->hw_type->frames_derive_to) - ret = dst->internal->hw_type->frames_derive_to(dst, src, flags); + dsti->hw_type->frames_derive_to) + ret = dsti->hw_type->frames_derive_to(dst, src, flags); if (ret == AVERROR(ENOSYS)) ret = 0; if (ret) @@ -944,8 +924,8 @@ int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, return 0; fail: - if (dst) - av_buffer_unref(&dst->internal->source_frames); + if (dsti) + av_buffer_unref(&dsti->source_frames); av_buffer_unref(&dst_ref); return ret; } diff --git a/media/ffvpx/libavutil/hwcontext.h b/media/ffvpx/libavutil/hwcontext.h index 2b33721a97..bac30debae 100644 --- a/media/ffvpx/libavutil/hwcontext.h +++ b/media/ffvpx/libavutil/hwcontext.h @@ -40,8 +40,6 @@ enum AVHWDeviceType { AV_HWDEVICE_TYPE_D3D12VA, }; -typedef struct AVHWDeviceInternal AVHWDeviceInternal; - /** * This struct aggregates all the (hardware/vendor-specific) "high-level" state, * i.e. state that is not tied to a concrete processing configuration. @@ -66,12 +64,6 @@ typedef struct AVHWDeviceContext { const AVClass *av_class; /** - * Private data used internally by libavutil. Must not be accessed in any - * way by the caller. - */ - AVHWDeviceInternal *internal; - - /** * This field identifies the underlying API used for hardware access. * * This field is set when this struct is allocated and never changed @@ -110,8 +102,6 @@ typedef struct AVHWDeviceContext { void *user_opaque; } AVHWDeviceContext; -typedef struct AVHWFramesInternal AVHWFramesInternal; - /** * This struct describes a set or pool of "hardware" frames (i.e. those with * data not located in normal system memory). All the frames in the pool are @@ -129,12 +119,6 @@ typedef struct AVHWFramesContext { const AVClass *av_class; /** - * Private data used internally by libavutil. Must not be accessed in any - * way by the caller. - */ - AVHWFramesInternal *internal; - - /** * A reference to the parent AVHWDeviceContext. This reference is owned and * managed by the enclosing AVHWFramesContext, but the caller may derive * additional references from it. @@ -153,9 +137,12 @@ typedef struct AVHWFramesContext { * The format-specific data, allocated and freed automatically along with * this context. * - * Should be cast by the user to the format-specific context defined in the - * corresponding header (hwframe_*.h) and filled as described in the - * documentation before calling av_hwframe_ctx_init(). + * The user shall ignore this field if the corresponding format-specific + * header (hwcontext_*.h) does not define a context to be used as + * AVHWFramesContext.hwctx. + * + * Otherwise, it should be cast by the user to said context and filled + * as described in the documentation before calling av_hwframe_ctx_init(). * * After any frames using this context are created, the contents of this * struct should not be modified by the caller. diff --git a/media/ffvpx/libavutil/hwcontext_internal.h b/media/ffvpx/libavutil/hwcontext_internal.h index 4df516ee6a..e32b786238 100644 --- a/media/ffvpx/libavutil/hwcontext_internal.h +++ b/media/ffvpx/libavutil/hwcontext_internal.h @@ -41,11 +41,6 @@ typedef struct HWContextType { * i.e. AVHWDeviceContext.hwctx */ size_t device_hwctx_size; - /** - * size of the private data, i.e. - * AVHWDeviceInternal.priv - */ - size_t device_priv_size; /** * Size of the hardware-specific device configuration. @@ -58,11 +53,6 @@ typedef struct HWContextType { * i.e. AVHWFramesContext.hwctx */ size_t frames_hwctx_size; - /** - * size of the private data, i.e. - * AVHWFramesInternal.priv - */ - size_t frames_priv_size; int (*device_create)(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags); @@ -100,20 +90,13 @@ typedef struct HWContextType { AVHWFramesContext *src_ctx, int flags); } HWContextType; -struct AVHWDeviceInternal { - const HWContextType *hw_type; - void *priv; - +typedef struct FFHWFramesContext { /** - * For a derived device, a reference to the original device - * context it was derived from. + * The public AVHWFramesContext. See hwcontext.h for it. */ - AVBufferRef *source_device; -}; + AVHWFramesContext p; -struct AVHWFramesInternal { const HWContextType *hw_type; - void *priv; AVBufferPool *pool_internal; @@ -127,7 +110,12 @@ struct AVHWFramesInternal { * frame context when trying to allocate in the derived context. */ int source_allocation_map_flags; -}; +} FFHWFramesContext; + +static inline FFHWFramesContext *ffhwframesctx(AVHWFramesContext *ctx) +{ + return (FFHWFramesContext*)ctx; +} typedef struct HWMapDescriptor { /** diff --git a/media/ffvpx/libavutil/hwcontext_vaapi.c b/media/ffvpx/libavutil/hwcontext_vaapi.c index 29fc8bd648..56d03aa4cd 100644 --- a/media/ffvpx/libavutil/hwcontext_vaapi.c +++ b/media/ffvpx/libavutil/hwcontext_vaapi.c @@ -75,12 +75,22 @@ typedef struct VAAPISurfaceFormat { } VAAPISurfaceFormat; typedef struct VAAPIDeviceContext { + /** + * The public AVVAAPIDeviceContext. See hwcontext_vaapi.h for it. + */ + AVVAAPIDeviceContext p; + // Surface formats which can be used with this device. VAAPISurfaceFormat *formats; int nb_formats; } VAAPIDeviceContext; typedef struct VAAPIFramesContext { + /** + * The public AVVAAPIFramesContext. See hwcontext_vaapi.h for it. + */ + AVVAAPIFramesContext p; + // Surface attributes set at create time. VASurfaceAttrib *attributes; int nb_attributes; @@ -207,7 +217,7 @@ static int vaapi_get_image_format(AVHWDeviceContext *hwdev, enum AVPixelFormat pix_fmt, VAImageFormat **image_format) { - VAAPIDeviceContext *ctx = hwdev->internal->priv; + VAAPIDeviceContext *ctx = hwdev->hwctx; int i; for (i = 0; i < ctx->nb_formats; i++) { @@ -224,9 +234,9 @@ static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, const void *hwconfig, AVHWFramesConstraints *constraints) { - AVVAAPIDeviceContext *hwctx = hwdev->hwctx; + VAAPIDeviceContext *ctx = hwdev->hwctx; + AVVAAPIDeviceContext *hwctx = &ctx->p; const AVVAAPIHWConfig *config = hwconfig; - VAAPIDeviceContext *ctx = hwdev->internal->priv; VASurfaceAttrib *attr_list = NULL; VAStatus vas; enum AVPixelFormat pix_fmt; @@ -384,8 +394,8 @@ static const struct { static int vaapi_device_init(AVHWDeviceContext *hwdev) { - VAAPIDeviceContext *ctx = hwdev->internal->priv; - AVVAAPIDeviceContext *hwctx = hwdev->hwctx; + VAAPIDeviceContext *ctx = hwdev->hwctx; + AVVAAPIDeviceContext *hwctx = &ctx->p; VAImageFormat *image_list = NULL; VAStatus vas; const char *vendor_string; @@ -474,7 +484,7 @@ fail: static void vaapi_device_uninit(AVHWDeviceContext *hwdev) { - VAAPIDeviceContext *ctx = hwdev->internal->priv; + VAAPIDeviceContext *ctx = hwdev->hwctx; av_freep(&ctx->formats); } @@ -498,9 +508,9 @@ static void vaapi_buffer_free(void *opaque, uint8_t *data) static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size) { AVHWFramesContext *hwfc = opaque; - VAAPIFramesContext *ctx = hwfc->internal->priv; + VAAPIFramesContext *ctx = hwfc->hwctx; + AVVAAPIFramesContext *avfc = &ctx->p; AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; - AVVAAPIFramesContext *avfc = hwfc->hwctx; VASurfaceID surface_id; VAStatus vas; AVBufferRef *ref; @@ -541,8 +551,8 @@ static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size) static int vaapi_frames_init(AVHWFramesContext *hwfc) { - AVVAAPIFramesContext *avfc = hwfc->hwctx; - VAAPIFramesContext *ctx = hwfc->internal->priv; + VAAPIFramesContext *ctx = hwfc->hwctx; + AVVAAPIFramesContext *avfc = &ctx->p; AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; const VAAPIFormatDescriptor *desc; VAImageFormat *expected_format; @@ -623,10 +633,10 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc) avfc->surface_ids = NULL; } - hwfc->internal->pool_internal = + ffhwframesctx(hwfc)->pool_internal = av_buffer_pool_init2(sizeof(VASurfaceID), hwfc, &vaapi_pool_alloc, NULL); - if (!hwfc->internal->pool_internal) { + if (!ffhwframesctx(hwfc)->pool_internal) { av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n"); err = AVERROR(ENOMEM); goto fail; @@ -644,7 +654,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc) goto fail; } } else { - test_surface = av_buffer_pool_get(hwfc->internal->pool_internal); + test_surface = av_buffer_pool_get(ffhwframesctx(hwfc)->pool_internal); if (!test_surface) { av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " "internal buffer pool.\n"); @@ -693,8 +703,8 @@ fail: static void vaapi_frames_uninit(AVHWFramesContext *hwfc) { - AVVAAPIFramesContext *avfc = hwfc->hwctx; - VAAPIFramesContext *ctx = hwfc->internal->priv; + VAAPIFramesContext *ctx = hwfc->hwctx; + AVVAAPIFramesContext *avfc = &ctx->p; av_freep(&avfc->surface_ids); av_freep(&ctx->attributes); @@ -718,7 +728,7 @@ static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats) { - VAAPIDeviceContext *ctx = hwfc->device_ctx->internal->priv; + VAAPIDeviceContext *ctx = hwfc->device_ctx->hwctx; enum AVPixelFormat *pix_fmts; int i, k, sw_format_available; @@ -791,7 +801,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; - VAAPIFramesContext *ctx = hwfc->internal->priv; + VAAPIFramesContext *ctx = hwfc->hwctx; VASurfaceID surface_id; const VAAPIFormatDescriptor *desc; VAImageFormat *image_format; @@ -1070,7 +1080,7 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { #if VA_CHECK_VERSION(1, 1, 0) - VAAPIFramesContext *src_vafc = src_fc->internal->priv; + VAAPIFramesContext *src_vafc = src_fc->hwctx; int use_prime2; #else int k; @@ -2007,11 +2017,9 @@ const HWContextType ff_hwcontext_type_vaapi = { .type = AV_HWDEVICE_TYPE_VAAPI, .name = "VAAPI", - .device_hwctx_size = sizeof(AVVAAPIDeviceContext), - .device_priv_size = sizeof(VAAPIDeviceContext), + .device_hwctx_size = sizeof(VAAPIDeviceContext), .device_hwconfig_size = sizeof(AVVAAPIHWConfig), - .frames_hwctx_size = sizeof(AVVAAPIFramesContext), - .frames_priv_size = sizeof(VAAPIFramesContext), + .frames_hwctx_size = sizeof(VAAPIFramesContext), .device_create = &vaapi_device_create, .device_derive = &vaapi_device_derive, diff --git a/media/ffvpx/libavutil/imgutils.c b/media/ffvpx/libavutil/imgutils.c index 1e15f7c920..d246381563 100644 --- a/media/ffvpx/libavutil/imgutils.c +++ b/media/ffvpx/libavutil/imgutils.c @@ -25,10 +25,10 @@ #include "common.h" #include "imgutils.h" #include "imgutils_internal.h" -#include "internal.h" #include "intreadwrite.h" #include "log.h" #include "mathematics.h" +#include "mem.h" #include "pixdesc.h" #include "rational.h" diff --git a/media/ffvpx/libavutil/imgutils_internal.h b/media/ffvpx/libavutil/imgutils_internal.h index d515858413..3e47731a50 100644 --- a/media/ffvpx/libavutil/imgutils_internal.h +++ b/media/ffvpx/libavutil/imgutils_internal.h @@ -22,6 +22,10 @@ #include <stddef.h> #include <stdint.h> +#include "pixfmt.h" + +int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt); + int ff_image_copy_plane_uc_from_x86(uint8_t *dst, ptrdiff_t dst_linesize, const uint8_t *src, ptrdiff_t src_linesize, ptrdiff_t bytewidth, int height); diff --git a/media/ffvpx/libavutil/internal.h b/media/ffvpx/libavutil/internal.h index 461c0df9ad..ac1af367e9 100644 --- a/media/ffvpx/libavutil/internal.h +++ b/media/ffvpx/libavutil/internal.h @@ -40,8 +40,8 @@ #include <stdio.h> #include "config.h" #include "attributes.h" +#include "libm.h" #include "macros.h" -#include "pixfmt.h" #ifndef attribute_align_arg #if ARCH_X86_32 && AV_GCC_VERSION_AT_LEAST(4,2) @@ -74,16 +74,6 @@ #endif -#define FF_MEMORY_POISON 0x2a - -/* Check if the hard coded offset of a struct member still matches reality. - * Induce a compilation failure if not. - */ -#define AV_CHECK_OFFSET(s, m, o) struct check_##o { \ - int x_##o[offsetof(s, m) == o? 1: -1]; \ - } - - #define FF_ALLOC_TYPED_ARRAY(p, nelem) (p = av_malloc_array(nelem, sizeof(*p))) #define FF_ALLOCZ_TYPED_ARRAY(p, nelem) (p = av_calloc(nelem, sizeof(*p))) @@ -94,8 +84,6 @@ */ #define FF_FIELD_AT(type, off, obj) (*(type *)((char *)&(obj) + (off))) -#include "libm.h" - /** * Return NULL if CONFIG_SMALL is true, otherwise the argument * without modification. Used to disable the definition of strings. @@ -163,8 +151,6 @@ void avpriv_request_sample(void *avc, #define SUINT32 uint32_t #endif -int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt); - static av_always_inline av_const int avpriv_mirror(int x, int w) { if (!w) diff --git a/media/ffvpx/libavutil/intreadwrite.h b/media/ffvpx/libavutil/intreadwrite.h index 21df7887f3..d0a5773b54 100644 --- a/media/ffvpx/libavutil/intreadwrite.h +++ b/media/ffvpx/libavutil/intreadwrite.h @@ -583,9 +583,7 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; #endif /* Parameters for AV_COPY*, AV_SWAP*, AV_ZERO* must be - * naturally aligned. They may be implemented using MMX, - * so emms_c() must be called before using any float code - * afterwards. + * naturally aligned. */ #define AV_COPY(n, d, s) \ diff --git a/media/ffvpx/libavutil/mem.c b/media/ffvpx/libavutil/mem.c index 36b8940a0c..b205d3fb25 100644 --- a/media/ffvpx/libavutil/mem.c +++ b/media/ffvpx/libavutil/mem.c @@ -62,14 +62,16 @@ void free(void *ptr); #endif /* MALLOC_PREFIX */ -#define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16)) +#define ALIGN (HAVE_SIMD_ALIGN_64 ? 64 : (HAVE_SIMD_ALIGN_32 ? 32 : 16)) + +#define FF_MEMORY_POISON 0x2a /* NOTE: if you want to override these functions with your own * implementations (not recommended) you have to link libav* as * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags. * Note that this will cost performance. */ -static atomic_size_t max_alloc_size = ATOMIC_VAR_INIT(INT_MAX); +static atomic_size_t max_alloc_size = INT_MAX; void av_max_alloc(size_t max){ atomic_store_explicit(&max_alloc_size, max, memory_order_relaxed); diff --git a/media/ffvpx/libavutil/mem.h b/media/ffvpx/libavutil/mem.h index be697408a2..ab7648ac57 100644 --- a/media/ffvpx/libavutil/mem.h +++ b/media/ffvpx/libavutil/mem.h @@ -116,7 +116,7 @@ * be allocated * @see av_mallocz() */ -void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1) __attribute__((visibility("default"))); +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); /** * Allocate a memory block with alignment suitable for all memory accesses diff --git a/media/ffvpx/libavutil/mem_internal.h b/media/ffvpx/libavutil/mem_internal.h index 2448c606f1..20f9b3e3f2 100644 --- a/media/ffvpx/libavutil/mem_internal.h +++ b/media/ffvpx/libavutil/mem_internal.h @@ -27,8 +27,6 @@ #include "attributes.h" #include "macros.h" -#include "mem.h" -#include "version.h" /** * @def DECLARE_ALIGNED(n,t,v) @@ -76,27 +74,50 @@ */ #if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ALIGNED_T(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v #elif defined(__DJGPP__) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ALIGNED_T(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v #elif defined(__GNUC__) || defined(__clang__) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ALIGNED_T(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v #elif defined(_MSC_VER) - #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ALIGNED_T(n,t,v) __declspec(align(n)) t v #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v #else - #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ALIGNED_T(n,t,v) t v #define DECLARE_ASM_ALIGNED(n,t,v) t v #define DECLARE_ASM_CONST(n,t,v) static const t v #endif +#if HAVE_SIMD_ALIGN_64 + #define ALIGN_64 64 + #define ALIGN_32 32 +#elif HAVE_SIMD_ALIGN_32 + #define ALIGN_64 32 + #define ALIGN_32 32 +#else + #define ALIGN_64 16 + #define ALIGN_32 16 +#endif + +#define DECLARE_ALIGNED(n,t,v) DECLARE_ALIGNED_V(n,t,v) + +// Macro needs to be double-wrapped in order to expand +// possible other macros being passed for n. +#define DECLARE_ALIGNED_V(n,t,v) DECLARE_ALIGNED_##n(t,v) + +#define DECLARE_ALIGNED_4(t,v) DECLARE_ALIGNED_T( 4, t, v) +#define DECLARE_ALIGNED_8(t,v) DECLARE_ALIGNED_T( 8, t, v) +#define DECLARE_ALIGNED_16(t,v) DECLARE_ALIGNED_T( 16, t, v) +#define DECLARE_ALIGNED_32(t,v) DECLARE_ALIGNED_T(ALIGN_32, t, v) +#define DECLARE_ALIGNED_64(t,v) DECLARE_ALIGNED_T(ALIGN_64, t, v) + // Some broken preprocessors need a second expansion // to be forced to tokenize __VA_ARGS__ #define E1(x) x diff --git a/media/ffvpx/libavutil/moz.build b/media/ffvpx/libavutil/moz.build index 4839375c10..c3b3a21fbe 100644 --- a/media/ffvpx/libavutil/moz.build +++ b/media/ffvpx/libavutil/moz.build @@ -35,6 +35,7 @@ SOURCES += [ 'imgutils.c', 'log.c', 'log2_tab.c', + 'mastering_display_metadata.c', 'mathematics.c', 'mem.c', 'opt.c', @@ -56,13 +57,11 @@ if not CONFIG['MOZ_FFVPX_AUDIOONLY']: SOURCES += [ 'adler32.c', 'base64.c', - 'color_utils.c', 'film_grain_params.c', 'hdr_dynamic_metadata.c', 'integer.c', 'intmath.c', 'lls.c', - 'mastering_display_metadata.c', 'pixelutils.c', 'threadmessage.c', 'timecode.c', @@ -79,6 +78,11 @@ EXPORTS.ffvpx = [ "tx.h" ] +c11_flags = ["-std=gnu11"] +if CONFIG["CC_TYPE"] == "clang-cl": + c11_flags.insert(0, "-Xclang") +CFLAGS += c11_flags + SYMBOLS_FILE = 'avutil.symbols' NoVisibilityFlags() diff --git a/media/ffvpx/libavutil/opt.c b/media/ffvpx/libavutil/opt.c index 0908751752..d11e9d2ac5 100644 --- a/media/ffvpx/libavutil/opt.c +++ b/media/ffvpx/libavutil/opt.c @@ -29,10 +29,10 @@ #include "avassert.h" #include "avstring.h" #include "channel_layout.h" -#include "common.h" #include "dict.h" #include "eval.h" #include "log.h" +#include "mem.h" #include "parseutils.h" #include "pixdesc.h" #include "mathematics.h" @@ -43,6 +43,8 @@ #include <float.h> +#define TYPE_BASE(type) ((type) & ~AV_OPT_TYPE_FLAG_ARRAY) + const AVOption *av_opt_next(const void *obj, const AVOption *last) { const AVClass *class; @@ -56,6 +58,98 @@ const AVOption *av_opt_next(const void *obj, const AVOption *last) return NULL; } +static const size_t opt_elem_size[] = { + [AV_OPT_TYPE_FLAGS] = sizeof(unsigned), + [AV_OPT_TYPE_INT] = sizeof(int), + [AV_OPT_TYPE_INT64] = sizeof(int64_t), + [AV_OPT_TYPE_UINT64] = sizeof(uint64_t), + [AV_OPT_TYPE_DOUBLE] = sizeof(double), + [AV_OPT_TYPE_FLOAT] = sizeof(float), + [AV_OPT_TYPE_STRING] = sizeof(char *), + [AV_OPT_TYPE_RATIONAL] = sizeof(AVRational), + [AV_OPT_TYPE_BINARY] = sizeof(uint8_t *), + [AV_OPT_TYPE_DICT] = sizeof(AVDictionary *), + [AV_OPT_TYPE_IMAGE_SIZE] = sizeof(int[2]), + [AV_OPT_TYPE_VIDEO_RATE] = sizeof(AVRational), + [AV_OPT_TYPE_PIXEL_FMT] = sizeof(int), + [AV_OPT_TYPE_SAMPLE_FMT] = sizeof(int), + [AV_OPT_TYPE_DURATION] = sizeof(int64_t), + [AV_OPT_TYPE_COLOR] = sizeof(uint8_t[4]), + [AV_OPT_TYPE_CHLAYOUT] = sizeof(AVChannelLayout), + [AV_OPT_TYPE_BOOL] = sizeof(int), +}; + +// option is plain old data +static int opt_is_pod(enum AVOptionType type) +{ + switch (type) { + case AV_OPT_TYPE_FLAGS: + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_FLOAT: + case AV_OPT_TYPE_RATIONAL: + case AV_OPT_TYPE_UINT64: + case AV_OPT_TYPE_IMAGE_SIZE: + case AV_OPT_TYPE_PIXEL_FMT: + case AV_OPT_TYPE_SAMPLE_FMT: + case AV_OPT_TYPE_VIDEO_RATE: + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_COLOR: + case AV_OPT_TYPE_BOOL: + return 1; + } + return 0; +} + +static uint8_t opt_array_sep(const AVOption *o) +{ + const AVOptionArrayDef *d = o->default_val.arr; + av_assert1(o->type & AV_OPT_TYPE_FLAG_ARRAY); + return (d && d->sep) ? d->sep : ','; +} + +static void *opt_array_pelem(const AVOption *o, void *array, unsigned idx) +{ + av_assert1(o->type & AV_OPT_TYPE_FLAG_ARRAY); + return (uint8_t *)array + idx * opt_elem_size[TYPE_BASE(o->type)]; +} + +static unsigned *opt_array_pcount(const void *parray) +{ + return (unsigned *)((const void * const *)parray + 1); +} + +static void opt_free_elem(const AVOption *o, void *ptr) +{ + switch (TYPE_BASE(o->type)) { + case AV_OPT_TYPE_STRING: + case AV_OPT_TYPE_BINARY: + av_freep(ptr); + break; + + case AV_OPT_TYPE_DICT: + av_dict_free((AVDictionary **)ptr); + break; + + case AV_OPT_TYPE_CHLAYOUT: + av_channel_layout_uninit((AVChannelLayout *)ptr); + break; + + default: + break; + } +} + +static void opt_free_array(const AVOption *o, void *parray, unsigned *count) +{ + for (unsigned i = 0; i < *count; i++) + opt_free_elem(o, opt_array_pelem(o, *(void **)parray, i)); + + av_freep(parray); + *count = 0; +} + static int read_number(const AVOption *o, const void *dst, double *num, int *den, int64_t *intnum) { switch (o->type) { @@ -72,11 +166,6 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den case AV_OPT_TYPE_INT: *intnum = *(int *)dst; return 0; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: -FF_ENABLE_DEPRECATION_WARNINGS -#endif case AV_OPT_TYPE_DURATION: case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_UINT64: @@ -93,7 +182,7 @@ FF_ENABLE_DEPRECATION_WARNINGS *den = ((AVRational *)dst)->den; return 0; case AV_OPT_TYPE_CONST: - *num = o->default_val.dbl; + *intnum = o->default_val.i64; return 0; } return AVERROR(EINVAL); @@ -101,14 +190,16 @@ FF_ENABLE_DEPRECATION_WARNINGS static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum) { - if (o->type != AV_OPT_TYPE_FLAGS && + const enum AVOptionType type = TYPE_BASE(o->type); + + if (type != AV_OPT_TYPE_FLAGS && (!den || o->max * den < num * intnum || o->min * den > num * intnum)) { num = den ? num * intnum / den : (num && intnum ? INFINITY : NAN); av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n", num, o->name, o->min, o->max); return AVERROR(ERANGE); } - if (o->type == AV_OPT_TYPE_FLAGS) { + if (type == AV_OPT_TYPE_FLAGS) { double d = num*intnum/den; if (d < -1.5 || d > 0xFFFFFFFF+0.5 || (llrint(d*256) & 255)) { av_log(obj, AV_LOG_ERROR, @@ -118,7 +209,7 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int } } - switch (o->type) { + switch (type) { case AV_OPT_TYPE_PIXEL_FMT: *(enum AVPixelFormat *)dst = llrint(num / den) * intnum; break; @@ -131,11 +222,6 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int *(int *)dst = llrint(num / den) * intnum; break; case AV_OPT_TYPE_DURATION: -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: -FF_ENABLE_DEPRECATION_WARNINGS -#endif case AV_OPT_TYPE_INT64:{ double d = num / den; if (intnum == 1 && d == (double)INT64_MAX) { @@ -223,6 +309,8 @@ static int set_string_binary(void *obj, const AVOption *o, const char *val, uint static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst) { av_freep(dst); + if (!val) + return 0; *dst = av_strdup(val); return *dst ? 0 : AVERROR(ENOMEM); } @@ -237,9 +325,10 @@ static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **d static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst) { + const enum AVOptionType type = TYPE_BASE(o->type); int ret = 0; - if (o->type == AV_OPT_TYPE_RATIONAL || o->type == AV_OPT_TYPE_VIDEO_RATE) { + if (type == AV_OPT_TYPE_RATIONAL || type == AV_OPT_TYPE_VIDEO_RATE) { int num, den; char c; if (sscanf(val, "%d%*1[:/]%d%c", &num, &den, &c) == 2) { @@ -256,7 +345,7 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con double d; int64_t intnum = 1; - if (o->type == AV_OPT_TYPE_FLAGS) { + if (type == AV_OPT_TYPE_FLAGS) { if (*val == '+' || *val == '-') cmd = *(val++); for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++) @@ -312,8 +401,8 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con } } } - if (o->type == AV_OPT_TYPE_FLAGS) { - read_number(o, dst, NULL, NULL, &intnum); + if (type == AV_OPT_TYPE_FLAGS) { + intnum = *(unsigned int*)dst; if (cmd == '+') d = intnum | (int64_t)d; else if (cmd == '-') @@ -444,16 +533,26 @@ static int set_string_fmt(void *obj, const AVOption *o, const char *val, uint8_t return 0; } +static int get_pix_fmt(const char *name) +{ + return av_get_pix_fmt(name); +} + static int set_string_pixel_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst) { return set_string_fmt(obj, o, val, dst, - AV_PIX_FMT_NB, av_get_pix_fmt, "pixel format"); + AV_PIX_FMT_NB, get_pix_fmt, "pixel format"); +} + +static int get_sample_fmt(const char *name) +{ + return av_get_sample_fmt(name); } static int set_string_sample_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst) { return set_string_fmt(obj, o, val, dst, - AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format"); + AV_SAMPLE_FMT_NB, get_sample_fmt, "sample format"); } static int set_string_dict(void *obj, const AVOption *o, const char *val, uint8_t **dst) @@ -484,33 +583,20 @@ static int set_string_channel_layout(void *obj, const AVOption *o, return av_channel_layout_from_string(channel_layout, val); } -int av_opt_set(void *obj, const char *name, const char *val, int search_flags) +static int opt_set_elem(void *obj, void *target_obj, const AVOption *o, + const char *val, void *dst) { - int ret = 0; - void *dst, *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; -FF_DISABLE_DEPRECATION_WARNINGS - if (!val && (o->type != AV_OPT_TYPE_STRING && - o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT && - o->type != AV_OPT_TYPE_IMAGE_SIZE && - o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR && -#if FF_API_OLD_CHANNEL_LAYOUT - o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && -#endif - o->type != AV_OPT_TYPE_BOOL)) - return AVERROR(EINVAL); -FF_ENABLE_DEPRECATION_WARNINGS + const enum AVOptionType type = TYPE_BASE(o->type); + int ret; - if (o->flags & AV_OPT_FLAG_READONLY) + if (!val && (type != AV_OPT_TYPE_STRING && + type != AV_OPT_TYPE_PIXEL_FMT && type != AV_OPT_TYPE_SAMPLE_FMT && + type != AV_OPT_TYPE_IMAGE_SIZE && + type != AV_OPT_TYPE_DURATION && type != AV_OPT_TYPE_COLOR && + type != AV_OPT_TYPE_BOOL)) return AVERROR(EINVAL); - if (o->flags & AV_OPT_FLAG_DEPRECATED) - av_log(obj, AV_LOG_WARNING, "The \"%s\" option is deprecated: %s\n", name, o->help); - - dst = ((uint8_t *)target_obj) + o->offset; - switch (o->type) { + switch (type) { case AV_OPT_TYPE_BOOL: return set_string_bool(obj, o, val, dst); case AV_OPT_TYPE_STRING: @@ -557,23 +643,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } case AV_OPT_TYPE_COLOR: return set_string_color(obj, o, val, dst); -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: - if (!val || !strcmp(val, "none")) { - *(int64_t *)dst = 0; - } else { - int64_t cl = av_get_channel_layout(val); - if (!cl) { - av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val); - ret = AVERROR(EINVAL); - } - *(int64_t *)dst = cl; - return ret; - } - break; -FF_ENABLE_DEPRECATION_WARNINGS -#endif case AV_OPT_TYPE_CHLAYOUT: ret = set_string_channel_layout(obj, o, val, dst); if (ret < 0) { @@ -589,6 +658,104 @@ FF_ENABLE_DEPRECATION_WARNINGS return AVERROR(EINVAL); } +static int opt_set_array(void *obj, void *target_obj, const AVOption *o, + const char *val, void *dst) +{ + const AVOptionArrayDef *arr = o->default_val.arr; + const size_t elem_size = opt_elem_size[TYPE_BASE(o->type)]; + const uint8_t sep = opt_array_sep(o); + uint8_t *str = NULL; + + void *elems = NULL; + unsigned nb_elems = 0; + int ret; + + if (val && *val) { + str = av_malloc(strlen(val) + 1); + if (!str) + return AVERROR(ENOMEM); + } + + // split and unescape the string + while (val && *val) { + uint8_t *p = str; + void *tmp; + + if (arr && arr->size_max && nb_elems >= arr->size_max) { + av_log(obj, AV_LOG_ERROR, + "Cannot assign more than %u elements to array option %s\n", + arr->size_max, o->name); + ret = AVERROR(EINVAL); + goto fail; + } + + for (; *val; val++, p++) { + if (*val == '\\' && val[1]) + val++; + else if (*val == sep) { + val++; + break; + } + *p = *val; + } + *p = 0; + + tmp = av_realloc_array(elems, nb_elems + 1, elem_size); + if (!tmp) { + ret = AVERROR(ENOMEM); + goto fail; + } + elems = tmp; + + tmp = opt_array_pelem(o, elems, nb_elems); + memset(tmp, 0, elem_size); + + ret = opt_set_elem(obj, target_obj, o, str, tmp); + if (ret < 0) + goto fail; + nb_elems++; + } + av_freep(&str); + + opt_free_array(o, dst, opt_array_pcount(dst)); + + if (arr && nb_elems < arr->size_min) { + av_log(obj, AV_LOG_ERROR, + "Cannot assign fewer than %u elements to array option %s\n", + arr->size_min, o->name); + ret = AVERROR(EINVAL); + goto fail; + } + + *((void **)dst) = elems; + *opt_array_pcount(dst) = nb_elems; + + return 0; +fail: + av_freep(&str); + opt_free_array(o, &elems, &nb_elems); + return ret; +} + +int av_opt_set(void *obj, const char *name, const char *val, int search_flags) +{ + void *dst, *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + + if (o->flags & AV_OPT_FLAG_READONLY) + return AVERROR(EINVAL); + + if (o->flags & AV_OPT_FLAG_DEPRECATED) + av_log(obj, AV_LOG_WARNING, "The \"%s\" option is deprecated: %s\n", name, o->help); + + dst = ((uint8_t *)target_obj) + o->offset; + + return ((o->type & AV_OPT_TYPE_FLAG_ARRAY) ? + opt_set_array : opt_set_elem)(obj, target_obj, o, val, dst); +} + #define OPT_EVAL_NUMBER(name, opttype, vartype) \ int av_opt_eval_ ## name(void *obj, const AVOption *o, \ const char *val, vartype *name ## _out) \ @@ -614,7 +781,7 @@ static int set_number(void *obj, const char *name, double num, int den, int64_t if (!o || !target_obj) return AVERROR_OPTION_NOT_FOUND; - if (o->flags & AV_OPT_FLAG_READONLY) + if ((o->flags & AV_OPT_FLAG_READONLY) || (o->type & AV_OPT_TYPE_FLAG_ARRAY)) return AVERROR(EINVAL); dst = ((uint8_t *)target_obj) + o->offset; @@ -697,7 +864,8 @@ int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int searc return AVERROR_OPTION_NOT_FOUND; if (o->type != AV_OPT_TYPE_VIDEO_RATE) { av_log(obj, AV_LOG_ERROR, - "The value set by option '%s' is not a video rate.\n", o->name); + "The value set by option '%s' is not a video rate.\n", + o->name); return AVERROR(EINVAL); } if (val.num <= 0 || val.den <= 0) @@ -744,26 +912,6 @@ int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB); } -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS -int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags) -{ - void *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); - - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) { - av_log(obj, AV_LOG_ERROR, - "The value set by option '%s' is not a channel layout.\n", o->name); - return AVERROR(EINVAL); - } - *(int64_t *)(((uint8_t *)target_obj) + o->offset) = cl; - return 0; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags) { @@ -834,145 +982,224 @@ static void format_duration(char *buf, size_t size, int64_t d) *(--e) = 0; } -int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) +static int opt_get_elem(const AVOption *o, uint8_t **pbuf, size_t buf_len, + void *dst, int search_flags) { - void *dst, *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); - uint8_t *bin, buf[128]; - int len, i, ret; - int64_t i64; - - if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST)) - return AVERROR_OPTION_NOT_FOUND; - - if (o->flags & AV_OPT_FLAG_DEPRECATED) - av_log(obj, AV_LOG_WARNING, "The \"%s\" option is deprecated: %s\n", name, o->help); - - dst = (uint8_t *)target_obj + o->offset; + int ret; - buf[0] = 0; - switch (o->type) { + switch (TYPE_BASE(o->type)) { case AV_OPT_TYPE_BOOL: - ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(get_bool_name(*(int *)dst), "invalid")); + ret = snprintf(*pbuf, buf_len, "%s", get_bool_name(*(int *)dst)); break; case AV_OPT_TYPE_FLAGS: - ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst); + ret = snprintf(*pbuf, buf_len, "0x%08X", *(int *)dst); break; case AV_OPT_TYPE_INT: - ret = snprintf(buf, sizeof(buf), "%d", *(int *)dst); + ret = snprintf(*pbuf, buf_len, "%d", *(int *)dst); break; case AV_OPT_TYPE_INT64: - ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t *)dst); + ret = snprintf(*pbuf, buf_len, "%"PRId64, *(int64_t *)dst); break; case AV_OPT_TYPE_UINT64: - ret = snprintf(buf, sizeof(buf), "%"PRIu64, *(uint64_t *)dst); + ret = snprintf(*pbuf, buf_len, "%"PRIu64, *(uint64_t *)dst); break; case AV_OPT_TYPE_FLOAT: - ret = snprintf(buf, sizeof(buf), "%f", *(float *)dst); + ret = snprintf(*pbuf, buf_len, "%f", *(float *)dst); break; case AV_OPT_TYPE_DOUBLE: - ret = snprintf(buf, sizeof(buf), "%f", *(double *)dst); + ret = snprintf(*pbuf, buf_len, "%f", *(double *)dst); break; case AV_OPT_TYPE_VIDEO_RATE: case AV_OPT_TYPE_RATIONAL: - ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational *)dst)->num, ((AVRational *)dst)->den); + ret = snprintf(*pbuf, buf_len, "%d/%d", ((AVRational *)dst)->num, ((AVRational *)dst)->den); break; case AV_OPT_TYPE_CONST: - ret = snprintf(buf, sizeof(buf), "%f", o->default_val.dbl); + ret = snprintf(*pbuf, buf_len, "%"PRId64, o->default_val.i64); break; case AV_OPT_TYPE_STRING: if (*(uint8_t **)dst) { - *out_val = av_strdup(*(uint8_t **)dst); + *pbuf = av_strdup(*(uint8_t **)dst); } else if (search_flags & AV_OPT_ALLOW_NULL) { - *out_val = NULL; + *pbuf = NULL; return 0; } else { - *out_val = av_strdup(""); + *pbuf = av_strdup(""); } - return *out_val ? 0 : AVERROR(ENOMEM); - case AV_OPT_TYPE_BINARY: + return *pbuf ? 0 : AVERROR(ENOMEM); + case AV_OPT_TYPE_BINARY: { + const uint8_t *bin; + int len; + if (!*(uint8_t **)dst && (search_flags & AV_OPT_ALLOW_NULL)) { - *out_val = NULL; + *pbuf = NULL; return 0; } len = *(int *)(((uint8_t *)dst) + sizeof(uint8_t *)); if ((uint64_t)len * 2 + 1 > INT_MAX) return AVERROR(EINVAL); - if (!(*out_val = av_malloc(len * 2 + 1))) + if (!(*pbuf = av_malloc(len * 2 + 1))) return AVERROR(ENOMEM); if (!len) { - *out_val[0] = '\0'; + *pbuf[0] = '\0'; return 0; } bin = *(uint8_t **)dst; - for (i = 0; i < len; i++) - snprintf(*out_val + i * 2, 3, "%02X", bin[i]); + for (int i = 0; i < len; i++) + snprintf(*pbuf + i * 2, 3, "%02X", bin[i]); return 0; + } case AV_OPT_TYPE_IMAGE_SIZE: - ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]); + ret = snprintf(*pbuf, buf_len, "%dx%d", ((int *)dst)[0], ((int *)dst)[1]); break; case AV_OPT_TYPE_PIXEL_FMT: - ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum AVPixelFormat *)dst), "none")); + ret = snprintf(*pbuf, buf_len, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum AVPixelFormat *)dst), "none")); break; case AV_OPT_TYPE_SAMPLE_FMT: - ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none")); + ret = snprintf(*pbuf, buf_len, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none")); break; - case AV_OPT_TYPE_DURATION: - i64 = *(int64_t *)dst; - format_duration(buf, sizeof(buf), i64); - ret = strlen(buf); // no overflow possible, checked by an assert + case AV_OPT_TYPE_DURATION: { + int64_t i64 = *(int64_t *)dst; + format_duration(*pbuf, buf_len, i64); + ret = strlen(*pbuf); // no overflow possible, checked by an assert break; + } case AV_OPT_TYPE_COLOR: - ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x", + ret = snprintf(*pbuf, buf_len, "0x%02x%02x%02x%02x", (int)((uint8_t *)dst)[0], (int)((uint8_t *)dst)[1], (int)((uint8_t *)dst)[2], (int)((uint8_t *)dst)[3]); break; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: - - i64 = *(int64_t *)dst; - ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64); - break; -FF_ENABLE_DEPRECATION_WARNINGS -#endif case AV_OPT_TYPE_CHLAYOUT: - ret = av_channel_layout_describe(dst, buf, sizeof(buf)); + ret = av_channel_layout_describe(dst, *pbuf, buf_len); break; case AV_OPT_TYPE_DICT: if (!*(AVDictionary **)dst && (search_flags & AV_OPT_ALLOW_NULL)) { - *out_val = NULL; + *pbuf = NULL; return 0; } - return av_dict_get_string(*(AVDictionary **)dst, (char **)out_val, '=', ':'); + return av_dict_get_string(*(AVDictionary **)dst, (char **)pbuf, '=', ':'); default: return AVERROR(EINVAL); } + return ret; +} + +static int opt_get_array(const AVOption *o, void *dst, uint8_t **out_val) +{ + const unsigned count = *opt_array_pcount(dst); + const uint8_t sep = opt_array_sep(o); + + uint8_t *str = NULL; + size_t str_len = 0; + int ret; + + *out_val = NULL; + + for (unsigned i = 0; i < count; i++) { + uint8_t buf[128], *out = buf; + size_t out_len; + + ret = opt_get_elem(o, &out, sizeof(buf), + opt_array_pelem(o, *(void **)dst, i), 0); + if (ret < 0) + goto fail; + + out_len = strlen(out); + if (out_len > SIZE_MAX / 2 - !!i || + !!i + out_len * 2 > SIZE_MAX - str_len - 1) { + ret = AVERROR(ERANGE); + goto fail; + } + + // terminator escaping separator + // ↓ ↓ ↓ + ret = av_reallocp(&str, str_len + 1 + out_len * 2 + !!i); + if (ret < 0) + goto fail; + + // add separator if needed + if (i) + str[str_len++] = sep; + + // escape the element + for (unsigned j = 0; j < out_len; j++) { + uint8_t val = out[j]; + if (val == sep || val == '\\') + str[str_len++] = '\\'; + str[str_len++] = val; + } + str[str_len] = 0; + +fail: + if (out != buf) + av_freep(&out); + if (ret < 0) { + av_freep(&str); + return ret; + } + } + + *out_val = str; + + return 0; +} + +int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) +{ + void *dst, *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + uint8_t *out, buf[128]; + int ret; + + if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST)) + return AVERROR_OPTION_NOT_FOUND; + + if (o->flags & AV_OPT_FLAG_DEPRECATED) + av_log(obj, AV_LOG_WARNING, "The \"%s\" option is deprecated: %s\n", name, o->help); + + dst = (uint8_t *)target_obj + o->offset; + + if (o->type & AV_OPT_TYPE_FLAG_ARRAY) { + ret = opt_get_array(o, dst, out_val); + if (ret < 0) + return ret; + if (!*out_val && !(search_flags & AV_OPT_ALLOW_NULL)) { + *out_val = av_strdup(""); + if (!*out_val) + return AVERROR(ENOMEM); + } + return 0; + } + + buf[0] = 0; + out = buf; + ret = opt_get_elem(o, &out, sizeof(buf), dst, search_flags); + if (ret < 0) + return ret; + if (out != buf) { + *out_val = out; + return 0; + } + if (ret >= sizeof(buf)) return AVERROR(EINVAL); - *out_val = av_strdup(buf); + *out_val = av_strdup(out); return *out_val ? 0 : AVERROR(ENOMEM); } -static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum, +static int get_number(void *obj, const char *name, double *num, int *den, int64_t *intnum, int search_flags) { void *dst, *target_obj; const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); if (!o || !target_obj) - goto error; + return AVERROR_OPTION_NOT_FOUND; + if (o->type & AV_OPT_TYPE_FLAG_ARRAY) + return AVERROR(EINVAL); dst = ((uint8_t *)target_obj) + o->offset; - if (o_out) *o_out= o; - return read_number(o, dst, num, den, intnum); - -error: - *den = - *intnum = 0; - return -1; } int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val) @@ -981,7 +1208,7 @@ int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_v double num = 1; int ret, den = 1; - if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) + if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) return ret; if (num == den) *out_val = intnum; @@ -996,7 +1223,7 @@ int av_opt_get_double(void *obj, const char *name, int search_flags, double *out double num = 1; int ret, den = 1; - if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) + if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) return ret; *out_val = num * intnum / den; return 0; @@ -1008,7 +1235,7 @@ int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_ double num = 1; int ret, den = 1; - if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) + if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) return ret; if (num == 1.0 && (int)intnum == intnum) @@ -1026,7 +1253,7 @@ int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_ return AVERROR_OPTION_NOT_FOUND; if (o->type != AV_OPT_TYPE_IMAGE_SIZE) { av_log(obj, AV_LOG_ERROR, - "The value for option '%s' is not an image size.\n", name); + "The value for option '%s' is not a image size.\n", name); return AVERROR(EINVAL); } @@ -1042,7 +1269,7 @@ int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRatio double num = 1; int ret, den = 1; - if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) + if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) return ret; if (num == 1.0 && (int)intnum == intnum) @@ -1080,27 +1307,6 @@ int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AV return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample"); } -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS -int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl) -{ - void *dst, *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) { - av_log(obj, AV_LOG_ERROR, - "The value for option '%s' is not a channel layout.\n", name); - return AVERROR(EINVAL); - } - - dst = ((uint8_t*)target_obj) + o->offset; - *cl = *(int64_t *)dst; - return 0; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *cl) { void *dst, *target_obj; @@ -1231,6 +1437,120 @@ static char *get_opt_flags_string(void *obj, const char *unit, int64_t value) return NULL; } +static void log_type(void *av_log_obj, const AVOption *o, + enum AVOptionType parent_type) +{ + const char *desc[] = { + [AV_OPT_TYPE_FLAGS] = "<flags>", + [AV_OPT_TYPE_INT] = "<int>", + [AV_OPT_TYPE_INT64] = "<int64>", + [AV_OPT_TYPE_UINT64] = "<uint64>", + [AV_OPT_TYPE_DOUBLE] = "<double>", + [AV_OPT_TYPE_FLOAT] = "<float>", + [AV_OPT_TYPE_STRING] = "<string>", + [AV_OPT_TYPE_RATIONAL] = "<rational>", + [AV_OPT_TYPE_BINARY] = "<binary>", + [AV_OPT_TYPE_DICT] = "<dictionary>", + [AV_OPT_TYPE_IMAGE_SIZE] = "<image_size>", + [AV_OPT_TYPE_VIDEO_RATE] = "<video_rate>", + [AV_OPT_TYPE_PIXEL_FMT] = "<pix_fmt>", + [AV_OPT_TYPE_SAMPLE_FMT] = "<sample_fmt>", + [AV_OPT_TYPE_DURATION] = "<duration>", + [AV_OPT_TYPE_COLOR] = "<color>", + [AV_OPT_TYPE_CHLAYOUT] = "<channel_layout>", + [AV_OPT_TYPE_BOOL] = "<boolean>", + }; + const enum AVOptionType type = TYPE_BASE(o->type); + + if (o->type == AV_OPT_TYPE_CONST && TYPE_BASE(parent_type) == AV_OPT_TYPE_INT) + av_log(av_log_obj, AV_LOG_INFO, "%-12"PRId64" ", o->default_val.i64); + else if (type < FF_ARRAY_ELEMS(desc) && desc[type]) { + if (o->type & AV_OPT_TYPE_FLAG_ARRAY) + av_log(av_log_obj, AV_LOG_INFO, "[%-10s]", desc[type]); + else + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", desc[type]); + } + else + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); +} + +static void log_default(void *obj, void *av_log_obj, const AVOption *opt) +{ + if (opt->type == AV_OPT_TYPE_CONST || opt->type == AV_OPT_TYPE_BINARY) + return; + if ((opt->type == AV_OPT_TYPE_COLOR || + opt->type == AV_OPT_TYPE_IMAGE_SIZE || + opt->type == AV_OPT_TYPE_STRING || + opt->type == AV_OPT_TYPE_DICT || + opt->type == AV_OPT_TYPE_CHLAYOUT || + opt->type == AV_OPT_TYPE_VIDEO_RATE) && + !opt->default_val.str) + return; + + if (opt->type & AV_OPT_TYPE_FLAG_ARRAY) { + const AVOptionArrayDef *arr = opt->default_val.arr; + if (arr && arr->def) + av_log(av_log_obj, AV_LOG_INFO, " (default %s)", arr->def); + return; + } + + av_log(av_log_obj, AV_LOG_INFO, " (default "); + switch (opt->type) { + case AV_OPT_TYPE_BOOL: + av_log(av_log_obj, AV_LOG_INFO, "%s", get_bool_name(opt->default_val.i64)); + break; + case AV_OPT_TYPE_FLAGS: { + char *def_flags = get_opt_flags_string(obj, opt->unit, opt->default_val.i64); + if (def_flags) { + av_log(av_log_obj, AV_LOG_INFO, "%s", def_flags); + av_freep(&def_flags); + } else { + av_log(av_log_obj, AV_LOG_INFO, "%"PRIX64, opt->default_val.i64); + } + break; + } + case AV_OPT_TYPE_DURATION: { + char buf[25]; + format_duration(buf, sizeof(buf), opt->default_val.i64); + av_log(av_log_obj, AV_LOG_INFO, "%s", buf); + break; + } + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_UINT64: + case AV_OPT_TYPE_INT64: { + const char *def_const = get_opt_const_name(obj, opt->unit, opt->default_val.i64); + if (def_const) + av_log(av_log_obj, AV_LOG_INFO, "%s", def_const); + else + log_int_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64); + break; + } + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_FLOAT: + log_value(av_log_obj, AV_LOG_INFO, opt->default_val.dbl); + break; + case AV_OPT_TYPE_RATIONAL: { + AVRational q = av_d2q(opt->default_val.dbl, INT_MAX); + av_log(av_log_obj, AV_LOG_INFO, "%d/%d", q.num, q.den); } + break; + case AV_OPT_TYPE_PIXEL_FMT: + av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(opt->default_val.i64), "none")); + break; + case AV_OPT_TYPE_SAMPLE_FMT: + av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none")); + break; + case AV_OPT_TYPE_COLOR: + case AV_OPT_TYPE_IMAGE_SIZE: + case AV_OPT_TYPE_STRING: + case AV_OPT_TYPE_DICT: + case AV_OPT_TYPE_VIDEO_RATE: + case AV_OPT_TYPE_CHLAYOUT: + av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str); + break; + } + av_log(av_log_obj, AV_LOG_INFO, ")"); +} + static void opt_list(void *obj, void *av_log_obj, const char *unit, int req_flags, int rej_flags, enum AVOptionType parent_type) { @@ -1259,76 +1579,8 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? " " : "-", opt->name); - switch (opt->type) { - case AV_OPT_TYPE_FLAGS: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<flags>"); - break; - case AV_OPT_TYPE_INT: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int>"); - break; - case AV_OPT_TYPE_INT64: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int64>"); - break; - case AV_OPT_TYPE_UINT64: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<uint64>"); - break; - case AV_OPT_TYPE_DOUBLE: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<double>"); - break; - case AV_OPT_TYPE_FLOAT: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<float>"); - break; - case AV_OPT_TYPE_STRING: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<string>"); - break; - case AV_OPT_TYPE_RATIONAL: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<rational>"); - break; - case AV_OPT_TYPE_BINARY: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<binary>"); - break; - case AV_OPT_TYPE_DICT: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<dictionary>"); - break; - case AV_OPT_TYPE_IMAGE_SIZE: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<image_size>"); - break; - case AV_OPT_TYPE_VIDEO_RATE: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<video_rate>"); - break; - case AV_OPT_TYPE_PIXEL_FMT: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<pix_fmt>"); - break; - case AV_OPT_TYPE_SAMPLE_FMT: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<sample_fmt>"); - break; - case AV_OPT_TYPE_DURATION: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<duration>"); - break; - case AV_OPT_TYPE_COLOR: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color>"); - break; - case AV_OPT_TYPE_CHLAYOUT: -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: -FF_ENABLE_DEPRECATION_WARNINGS -#endif - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<channel_layout>"); - break; - case AV_OPT_TYPE_BOOL: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<boolean>"); - break; - case AV_OPT_TYPE_CONST: - if (parent_type == AV_OPT_TYPE_INT) - av_log(av_log_obj, AV_LOG_INFO, "%-12"PRId64" ", opt->default_val.i64); - else - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); - break; - default: - av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); - break; - } + log_type(av_log_obj, opt, parent_type); + av_log(av_log_obj, AV_LOG_INFO, "%c%c%c%c%c%c%c%c%c%c%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.', (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.', @@ -1365,78 +1617,7 @@ FF_ENABLE_DEPRECATION_WARNINGS av_opt_freep_ranges(&r); } - if (opt->type != AV_OPT_TYPE_CONST && - opt->type != AV_OPT_TYPE_BINARY && - !((opt->type == AV_OPT_TYPE_COLOR || - opt->type == AV_OPT_TYPE_IMAGE_SIZE || - opt->type == AV_OPT_TYPE_STRING || - opt->type == AV_OPT_TYPE_DICT || - opt->type == AV_OPT_TYPE_CHLAYOUT || - opt->type == AV_OPT_TYPE_VIDEO_RATE) && - !opt->default_val.str)) { - av_log(av_log_obj, AV_LOG_INFO, " (default "); - switch (opt->type) { - case AV_OPT_TYPE_BOOL: - av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(get_bool_name(opt->default_val.i64), "invalid")); - break; - case AV_OPT_TYPE_FLAGS: { - char *def_flags = get_opt_flags_string(obj, opt->unit, opt->default_val.i64); - if (def_flags) { - av_log(av_log_obj, AV_LOG_INFO, "%s", def_flags); - av_freep(&def_flags); - } else { - av_log(av_log_obj, AV_LOG_INFO, "%"PRIX64, opt->default_val.i64); - } - break; - } - case AV_OPT_TYPE_DURATION: { - char buf[25]; - format_duration(buf, sizeof(buf), opt->default_val.i64); - av_log(av_log_obj, AV_LOG_INFO, "%s", buf); - break; - } - case AV_OPT_TYPE_INT: - case AV_OPT_TYPE_UINT64: - case AV_OPT_TYPE_INT64: { - const char *def_const = get_opt_const_name(obj, opt->unit, opt->default_val.i64); - if (def_const) - av_log(av_log_obj, AV_LOG_INFO, "%s", def_const); - else - log_int_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64); - break; - } - case AV_OPT_TYPE_DOUBLE: - case AV_OPT_TYPE_FLOAT: - log_value(av_log_obj, AV_LOG_INFO, opt->default_val.dbl); - break; - case AV_OPT_TYPE_RATIONAL: { - AVRational q = av_d2q(opt->default_val.dbl, INT_MAX); - av_log(av_log_obj, AV_LOG_INFO, "%d/%d", q.num, q.den); } - break; - case AV_OPT_TYPE_PIXEL_FMT: - av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(opt->default_val.i64), "none")); - break; - case AV_OPT_TYPE_SAMPLE_FMT: - av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none")); - break; - case AV_OPT_TYPE_COLOR: - case AV_OPT_TYPE_IMAGE_SIZE: - case AV_OPT_TYPE_STRING: - case AV_OPT_TYPE_DICT: - case AV_OPT_TYPE_VIDEO_RATE: - case AV_OPT_TYPE_CHLAYOUT: - av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str); - break; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: - av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64); - break; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - } - av_log(av_log_obj, AV_LOG_INFO, ")"); - } + log_default(obj, av_log_obj, opt); av_log(av_log_obj, AV_LOG_INFO, "\n"); if (opt->unit && opt->type != AV_OPT_TYPE_CONST) @@ -1473,6 +1654,21 @@ void av_opt_set_defaults2(void *s, int mask, int flags) if (opt->flags & AV_OPT_FLAG_READONLY) continue; + if (opt->type & AV_OPT_TYPE_FLAG_ARRAY) { + const AVOptionArrayDef *arr = opt->default_val.arr; + const char sep = opt_array_sep(opt); + + av_assert0(sep && sep != '\\' && + (sep < 'a' || sep > 'z') && + (sep < 'A' || sep > 'Z') && + (sep < '0' || sep > '9')); + + if (arr && arr->def) + opt_set_array(s, s, opt, arr->def, dst); + + continue; + } + switch (opt->type) { case AV_OPT_TYPE_CONST: /* Nothing to be done here */ @@ -1483,11 +1679,6 @@ void av_opt_set_defaults2(void *s, int mask, int flags) case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_UINT64: case AV_OPT_TYPE_DURATION: -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: -FF_ENABLE_DEPRECATION_WARNINGS -#endif case AV_OPT_TYPE_PIXEL_FMT: case AV_OPT_TYPE_SAMPLE_FMT: write_number(s, opt, dst, 1, 1, opt->default_val.i64); @@ -1670,7 +1861,6 @@ int av_opt_set_from_string(void *ctx, const char *opts, { int ret, count = 0; const char *dummy_shorthand = NULL; - char *av_uninit(parsed_key), *av_uninit(value); const char *key; if (!opts) @@ -1679,6 +1869,7 @@ int av_opt_set_from_string(void *ctx, const char *opts, shorthand = &dummy_shorthand; while (*opts) { + char *parsed_key, *value; ret = av_opt_get_key_value(&opts, key_val_sep, pairs_sep, *shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0, &parsed_key, &value); @@ -1720,23 +1911,12 @@ void av_opt_free(void *obj) { const AVOption *o = NULL; while ((o = av_opt_next(obj, o))) { - switch (o->type) { - case AV_OPT_TYPE_STRING: - case AV_OPT_TYPE_BINARY: - av_freep((uint8_t *)obj + o->offset); - break; - - case AV_OPT_TYPE_DICT: - av_dict_free((AVDictionary **)(((uint8_t *)obj) + o->offset)); - break; + void *pitem = (uint8_t *)obj + o->offset; - case AV_OPT_TYPE_CHLAYOUT: - av_channel_layout_uninit((AVChannelLayout *)(((uint8_t *)obj) + o->offset)); - break; - - default: - break; - } + if (o->type & AV_OPT_TYPE_FLAG_ARRAY) + opt_free_array(o, pitem, opt_array_pcount(pitem)); + else + opt_free_elem(o, pitem); } } @@ -1838,48 +2018,93 @@ const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter) void *av_opt_ptr(const AVClass *class, void *obj, const char *name) { const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL); - if(!opt) + + // no direct access to array-type options + if (!opt || (opt->type & AV_OPT_TYPE_FLAG_ARRAY)) return NULL; return (uint8_t*)obj + opt->offset; } -static int opt_size(enum AVOptionType type) +static int opt_copy_elem(void *logctx, enum AVOptionType type, + void *dst, const void *src) { - switch(type) { - case AV_OPT_TYPE_BOOL: - case AV_OPT_TYPE_INT: - case AV_OPT_TYPE_FLAGS: - return sizeof(int); - case AV_OPT_TYPE_DURATION: -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: -FF_ENABLE_DEPRECATION_WARNINGS -#endif - case AV_OPT_TYPE_INT64: - case AV_OPT_TYPE_UINT64: - return sizeof(int64_t); - case AV_OPT_TYPE_DOUBLE: - return sizeof(double); - case AV_OPT_TYPE_FLOAT: - return sizeof(float); - case AV_OPT_TYPE_STRING: - return sizeof(uint8_t*); - case AV_OPT_TYPE_VIDEO_RATE: - case AV_OPT_TYPE_RATIONAL: - return sizeof(AVRational); - case AV_OPT_TYPE_BINARY: - return sizeof(uint8_t*) + sizeof(int); - case AV_OPT_TYPE_IMAGE_SIZE: - return sizeof(int[2]); - case AV_OPT_TYPE_PIXEL_FMT: - return sizeof(enum AVPixelFormat); - case AV_OPT_TYPE_SAMPLE_FMT: - return sizeof(enum AVSampleFormat); - case AV_OPT_TYPE_COLOR: - return 4; + if (type == AV_OPT_TYPE_STRING) { + const char *src_str = *(const char *const *)src; + char **dstp = (char **)dst; + if (*dstp != src_str) + av_freep(dstp); + if (src_str) { + *dstp = av_strdup(src_str); + if (!*dstp) + return AVERROR(ENOMEM); + } + } else if (type == AV_OPT_TYPE_BINARY) { + const uint8_t *const *src8 = (const uint8_t *const *)src; + uint8_t **dst8 = (uint8_t **)dst; + int len = *(const int *)(src8 + 1); + if (*dst8 != *src8) + av_freep(dst8); + *dst8 = av_memdup(*src8, len); + if (len && !*dst8) { + *(int *)(dst8 + 1) = 0; + return AVERROR(ENOMEM); + } + *(int *)(dst8 + 1) = len; + } else if (type == AV_OPT_TYPE_CONST) { + // do nothing + } else if (type == AV_OPT_TYPE_DICT) { + const AVDictionary *sdict = *(const AVDictionary * const *)src; + AVDictionary **ddictp = (AVDictionary **)dst; + if (sdict != *ddictp) + av_dict_free(ddictp); + *ddictp = NULL; + return av_dict_copy(ddictp, sdict, 0); + } else if (type == AV_OPT_TYPE_CHLAYOUT) { + if (dst != src) + return av_channel_layout_copy(dst, src); + } else if (opt_is_pod(type)) { + size_t size = opt_elem_size[type]; + memcpy(dst, src, size); + } else { + av_log(logctx, AV_LOG_ERROR, "Unhandled option type: %d\n", type); + return AVERROR(EINVAL); } - return AVERROR(EINVAL); + + return 0; +} + +static int opt_copy_array(void *logctx, const AVOption *o, + void **pdst, const void * const *psrc) +{ + unsigned nb_elems = *opt_array_pcount(psrc); + void *dst = NULL; + int ret; + + if (*pdst == *psrc) { + *pdst = NULL; + *opt_array_pcount(pdst) = 0; + } + + opt_free_array(o, pdst, opt_array_pcount(pdst)); + + dst = av_calloc(nb_elems, opt_elem_size[TYPE_BASE(o->type)]); + if (!dst) + return AVERROR(ENOMEM); + + for (unsigned i = 0; i < nb_elems; i++) { + ret = opt_copy_elem(logctx, TYPE_BASE(o->type), + opt_array_pelem(o, dst, i), + opt_array_pelem(o, *(void**)psrc, i)); + if (ret < 0) { + opt_free_array(o, &dst, &nb_elems); + return ret; + } + } + + *pdst = dst; + *opt_array_pcount(pdst) = nb_elems; + + return 0; } int av_opt_copy(void *dst, const void *src) @@ -1898,47 +2123,12 @@ int av_opt_copy(void *dst, const void *src) while ((o = av_opt_next(src, o))) { void *field_dst = (uint8_t *)dst + o->offset; void *field_src = (uint8_t *)src + o->offset; - uint8_t **field_dst8 = (uint8_t **)field_dst; - uint8_t **field_src8 = (uint8_t **)field_src; - - if (o->type == AV_OPT_TYPE_STRING) { - if (*field_dst8 != *field_src8) - av_freep(field_dst8); - *field_dst8 = av_strdup(*field_src8); - if (*field_src8 && !*field_dst8) - ret = AVERROR(ENOMEM); - } else if (o->type == AV_OPT_TYPE_BINARY) { - int len = *(int *)(field_src8 + 1); - if (*field_dst8 != *field_src8) - av_freep(field_dst8); - *field_dst8 = av_memdup(*field_src8, len); - if (len && !*field_dst8) { - ret = AVERROR(ENOMEM); - len = 0; - } - *(int *)(field_dst8 + 1) = len; - } else if (o->type == AV_OPT_TYPE_CONST) { - // do nothing - } else if (o->type == AV_OPT_TYPE_DICT) { - AVDictionary **sdict = (AVDictionary **) field_src; - AVDictionary **ddict = (AVDictionary **) field_dst; - int ret2; - if (*sdict != *ddict) - av_dict_free(ddict); - *ddict = NULL; - ret2 = av_dict_copy(ddict, *sdict, 0); - if (ret2 < 0) - ret = ret2; - } else if (o->type == AV_OPT_TYPE_CHLAYOUT) { - if (field_dst != field_src) - ret = av_channel_layout_copy(field_dst, field_src); - } else { - int size = opt_size(o->type); - if (size < 0) - ret = size; - else - memcpy(field_dst, field_src, size); - } + + int err = (o->type & AV_OPT_TYPE_FLAG_ARRAY) ? + opt_copy_array(dst, o, field_dst, field_src) : + opt_copy_elem (dst, o->type, field_dst, field_src); + if (err < 0) + ret = err; } return ret; } @@ -1995,11 +2185,6 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch case AV_OPT_TYPE_DOUBLE: case AV_OPT_TYPE_DURATION: case AV_OPT_TYPE_COLOR: -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: -FF_ENABLE_DEPRECATION_WARNINGS -#endif break; case AV_OPT_TYPE_STRING: range->component_min = 0; @@ -2059,8 +2244,7 @@ void av_opt_freep_ranges(AVOptionRanges **rangesp) int av_opt_is_set_to_default(void *obj, const AVOption *o) { int64_t i64; - double d, d2; - float f; + double d; AVRational q; int ret, w, h; char *str; @@ -2071,6 +2255,24 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o) dst = ((uint8_t*)obj) + o->offset; + if (o->type & AV_OPT_TYPE_FLAG_ARRAY) { + const char *def = o->default_val.arr ? o->default_val.arr->def : NULL; + uint8_t *val; + + ret = opt_get_array(o, dst, &val); + if (ret < 0) + return ret; + + if (!!val != !!def) + ret = 0; + else if (val) + ret = !strcmp(val, def); + + av_freep(&val); + + return ret; + } + switch (o->type) { case AV_OPT_TYPE_CONST: return 1; @@ -2079,11 +2281,6 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o) case AV_OPT_TYPE_PIXEL_FMT: case AV_OPT_TYPE_SAMPLE_FMT: case AV_OPT_TYPE_INT: -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - case AV_OPT_TYPE_CHANNEL_LAYOUT: -FF_ENABLE_DEPRECATION_WARNINGS -#endif case AV_OPT_TYPE_DURATION: case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_UINT64: @@ -2105,13 +2302,11 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; return !strcmp(str, o->default_val.str); case AV_OPT_TYPE_DOUBLE: - read_number(o, dst, &d, NULL, NULL); + d = *(double *)dst; return o->default_val.dbl == d; case AV_OPT_TYPE_FLOAT: - read_number(o, dst, &d, NULL, NULL); - f = o->default_val.dbl; - d2 = f; - return d2 == d; + d = *(float *)dst; + return (float)o->default_val.dbl == d; case AV_OPT_TYPE_RATIONAL: q = av_d2q(o->default_val.dbl, INT_MAX); return !av_cmp_q(*(AVRational*)dst, q); diff --git a/media/ffvpx/libavutil/opt.h b/media/ffvpx/libavutil/opt.h index 461b5d3b6b..e6013662f6 100644 --- a/media/ffvpx/libavutil/opt.h +++ b/media/ffvpx/libavutil/opt.h @@ -43,6 +43,16 @@ * ("objects"). An option can have a help text, a type and a range of possible * values. Options may then be enumerated, read and written to. * + * There are two modes of access to members of AVOption and its child structs. + * One is called 'native access', and refers to access from the code that + * declares the AVOption in question. The other is 'foreign access', and refers + * to access from other code. + * + * Certain struct members in this header are documented as 'native access only' + * or similar - it means that only the code that declared the AVOption in + * question is allowed to access the field. This allows us to extend the + * semantics of those fields without breaking API compatibility. + * * @section avoptions_implement Implementing AVOptions * This section describes how to add AVOptions capabilities to a struct. * @@ -221,7 +231,7 @@ */ enum AVOptionType{ - AV_OPT_TYPE_FLAGS, + AV_OPT_TYPE_FLAGS = 1, AV_OPT_TYPE_INT, AV_OPT_TYPE_INT64, AV_OPT_TYPE_DOUBLE, @@ -238,14 +248,99 @@ enum AVOptionType{ AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational AV_OPT_TYPE_DURATION, AV_OPT_TYPE_COLOR, -#if FF_API_OLD_CHANNEL_LAYOUT - AV_OPT_TYPE_CHANNEL_LAYOUT, -#endif AV_OPT_TYPE_BOOL, AV_OPT_TYPE_CHLAYOUT, + + /** + * May be combined with another regular option type to declare an array + * option. + * + * For array options, @ref AVOption.offset should refer to a pointer + * corresponding to the option type. The pointer should be immediately + * followed by an unsigned int that will store the number of elements in the + * array. + */ + AV_OPT_TYPE_FLAG_ARRAY = (1 << 16), }; /** + * A generic parameter which can be set by the user for muxing or encoding. + */ +#define AV_OPT_FLAG_ENCODING_PARAM (1 << 0) +/** + * A generic parameter which can be set by the user for demuxing or decoding. + */ +#define AV_OPT_FLAG_DECODING_PARAM (1 << 1) +#define AV_OPT_FLAG_AUDIO_PARAM (1 << 3) +#define AV_OPT_FLAG_VIDEO_PARAM (1 << 4) +#define AV_OPT_FLAG_SUBTITLE_PARAM (1 << 5) +/** + * The option is intended for exporting values to the caller. + */ +#define AV_OPT_FLAG_EXPORT (1 << 6) +/** + * The option may not be set through the AVOptions API, only read. + * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. + */ +#define AV_OPT_FLAG_READONLY (1 << 7) +/** + * A generic parameter which can be set by the user for bit stream filtering. + */ +#define AV_OPT_FLAG_BSF_PARAM (1 << 8) + +/** + * A generic parameter which can be set by the user at runtime. + */ +#define AV_OPT_FLAG_RUNTIME_PARAM (1 << 15) +/** + * A generic parameter which can be set by the user for filtering. + */ +#define AV_OPT_FLAG_FILTERING_PARAM (1 << 16) +/** + * Set if option is deprecated, users should refer to AVOption.help text for + * more information. + */ +#define AV_OPT_FLAG_DEPRECATED (1 << 17) +/** + * Set if option constants can also reside in child objects. + */ +#define AV_OPT_FLAG_CHILD_CONSTS (1 << 18) + +/** + * May be set as default_val for AV_OPT_TYPE_FLAG_ARRAY options. + */ +typedef struct AVOptionArrayDef { + /** + * Native access only. + * + * Default value of the option, as would be serialized by av_opt_get() (i.e. + * using the value of sep as the separator). + */ + const char *def; + + /** + * Minimum number of elements in the array. When this field is non-zero, def + * must be non-NULL and contain at least this number of elements. + */ + unsigned size_min; + /** + * Maximum number of elements in the array, 0 when unlimited. + */ + unsigned size_max; + + /** + * Separator between array elements in string representations of this + * option, used by av_opt_set() and av_opt_get(). It must be a printable + * ASCII character, excluding alphanumeric and the backslash. A comma is + * used when sep=0. + * + * The separator and the backslash must be backslash-escaped in order to + * appear in string representations of the option value. + */ + char sep; +} AVOptionArrayDef; + +/** * AVOption */ typedef struct AVOption { @@ -258,6 +353,8 @@ typedef struct AVOption { const char *help; /** + * Native access only. + * * The offset relative to the context structure where the option * value is stored. It should be 0 for named constants. */ @@ -265,6 +362,7 @@ typedef struct AVOption { enum AVOptionType type; /** + * Native access only, except when documented otherwise. * the default value for scalar options */ union { @@ -273,31 +371,22 @@ typedef struct AVOption { const char *str; /* TODO those are unused now */ AVRational q; + + /** + * Used for AV_OPT_TYPE_FLAG_ARRAY options. May be NULL. + * + * Foreign access to some members allowed, as noted in AVOptionArrayDef + * documentation. + */ + const AVOptionArrayDef *arr; } default_val; double min; ///< minimum valid value for the option double max; ///< maximum valid value for the option + /** + * A combination of AV_OPT_FLAG_*. + */ int flags; -#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding -#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding -#define AV_OPT_FLAG_AUDIO_PARAM 8 -#define AV_OPT_FLAG_VIDEO_PARAM 16 -#define AV_OPT_FLAG_SUBTITLE_PARAM 32 -/** - * The option is intended for exporting values to the caller. - */ -#define AV_OPT_FLAG_EXPORT 64 -/** - * The option may not be set through the AVOptions API, only read. - * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. - */ -#define AV_OPT_FLAG_READONLY 128 -#define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering -#define AV_OPT_FLAG_RUNTIME_PARAM (1<<15) ///< a generic parameter which can be set by the user at runtime -#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering -#define AV_OPT_FLAG_DEPRECATED (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information -#define AV_OPT_FLAG_CHILD_CONSTS (1<<18) ///< set if option constants can also reside in child objects -//FIXME think about enc-audio, ... style flags /** * The logical unit to which the option belongs. Non-constant @@ -376,15 +465,9 @@ typedef struct AVOptionRanges { } AVOptionRanges; /** - * Show the obj options. - * - * @param req_flags requested flags for the options to show. Show only the - * options for which it is opt->flags & req_flags. - * @param rej_flags rejected flags for the options to show. Show only the - * options for which it is !(opt->flags & req_flags). - * @param av_log_obj log context to use for showing the options + * @defgroup opt_mng AVOption (un)initialization and inspection. + * @{ */ -int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); /** * Set the values of all AVOption fields to their default values. @@ -405,160 +488,36 @@ void av_opt_set_defaults(void *s); void av_opt_set_defaults2(void *s, int mask, int flags); /** - * Parse the key/value pairs list in opts. For each key/value pair - * found, stores the value in the field in ctx that is named like the - * key. ctx must be an AVClass context, storing is done using - * AVOptions. - * - * @param opts options string to parse, may be NULL - * @param key_val_sep a 0-terminated list of characters used to - * separate key from value - * @param pairs_sep a 0-terminated list of characters used to separate - * two pairs from each other - * @return the number of successfully set key/value pairs, or a negative - * value corresponding to an AVERROR code in case of error: - * AVERROR(EINVAL) if opts cannot be parsed, - * the error code issued by av_opt_set() if a key/value pair - * cannot be set - */ -int av_set_options_string(void *ctx, const char *opts, - const char *key_val_sep, const char *pairs_sep); - -/** - * Parse the key-value pairs list in opts. For each key=value pair found, - * set the value of the corresponding option in ctx. - * - * @param ctx the AVClass object to set options on - * @param opts the options string, key-value pairs separated by a - * delimiter - * @param shorthand a NULL-terminated array of options names for shorthand - * notation: if the first field in opts has no key part, - * the key is taken from the first element of shorthand; - * then again for the second, etc., until either opts is - * finished, shorthand is finished or a named option is - * found; after that, all options must be named - * @param key_val_sep a 0-terminated list of characters used to separate - * key from value, for example '=' - * @param pairs_sep a 0-terminated list of characters used to separate - * two pairs from each other, for example ':' or ',' - * @return the number of successfully set key=value pairs, or a negative - * value corresponding to an AVERROR code in case of error: - * AVERROR(EINVAL) if opts cannot be parsed, - * the error code issued by av_set_string3() if a key/value pair - * cannot be set - * - * Options names must use only the following characters: a-z A-Z 0-9 - . / _ - * Separators must use characters distinct from option names and from each - * other. - */ -int av_opt_set_from_string(void *ctx, const char *opts, - const char *const *shorthand, - const char *key_val_sep, const char *pairs_sep); -/** * Free all allocated objects in obj. */ void av_opt_free(void *obj); /** - * Check whether a particular flag is set in a flags field. - * - * @param field_name the name of the flag field option - * @param flag_name the name of the flag to check - * @return non-zero if the flag is set, zero if the flag isn't set, - * isn't of the right type, or the flags field doesn't exist. - */ -int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); - -/** - * Set all the options from a given dictionary on an object. - * - * @param obj a struct whose first element is a pointer to AVClass - * @param options options to process. This dictionary will be freed and replaced - * by a new one containing all options not found in obj. - * Of course this new dictionary needs to be freed by caller - * with av_dict_free(). - * - * @return 0 on success, a negative AVERROR if some option was found in obj, - * but could not be set. - * - * @see av_dict_copy() - */ -int av_opt_set_dict(void *obj, struct AVDictionary **options); - - -/** - * Set all the options from a given dictionary on an object. - * - * @param obj a struct whose first element is a pointer to AVClass - * @param options options to process. This dictionary will be freed and replaced - * by a new one containing all options not found in obj. - * Of course this new dictionary needs to be freed by caller - * with av_dict_free(). - * @param search_flags A combination of AV_OPT_SEARCH_*. - * - * @return 0 on success, a negative AVERROR if some option was found in obj, - * but could not be set. + * Iterate over all AVOptions belonging to obj. * - * @see av_dict_copy() + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL */ -int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); +const AVOption *av_opt_next(const void *obj, const AVOption *prev); /** - * Extract a key-value pair from the beginning of a string. - * - * @param ropts pointer to the options string, will be updated to - * point to the rest of the string (one of the pairs_sep - * or the final NUL) - * @param key_val_sep a 0-terminated list of characters used to separate - * key from value, for example '=' - * @param pairs_sep a 0-terminated list of characters used to separate - * two pairs from each other, for example ':' or ',' - * @param flags flags; see the AV_OPT_FLAG_* values below - * @param rkey parsed key; must be freed using av_free() - * @param rval parsed value; must be freed using av_free() - * - * @return >=0 for success, or a negative value corresponding to an - * AVERROR code in case of error; in particular: - * AVERROR(EINVAL) if no key is present + * Iterate over AVOptions-enabled children of obj. * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL */ -int av_opt_get_key_value(const char **ropts, - const char *key_val_sep, const char *pairs_sep, - unsigned flags, - char **rkey, char **rval); - -enum { - - /** - * Accept to parse a value without a key; the key will then be returned - * as NULL. - */ - AV_OPT_FLAG_IMPLICIT_KEY = 1, -}; +void *av_opt_child_next(void *obj, void *prev); /** - * @defgroup opt_eval_funcs Evaluating option strings - * @{ - * This group of functions can be used to evaluate option strings - * and get numbers out of them. They do the same thing as av_opt_set(), - * except the result is written into the caller-supplied pointer. - * - * @param obj a struct whose first element is a pointer to AVClass. - * @param o an option for which the string is to be evaluated. - * @param val string to be evaluated. - * @param *_out value of the string will be written here. + * Iterate over potential AVOptions-enabled children of parent. * - * @return 0 on success, a negative number on failure. - */ -int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); -int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); -int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); -int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); -int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); -int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); -/** - * @} + * @param iter a pointer where iteration state is stored. + * @return AVClass corresponding to next potential child or NULL */ +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); #define AV_OPT_SEARCH_CHILDREN (1 << 0) /**< Search in possible children of the given object first. */ @@ -633,31 +592,161 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, int opt_flags, int search_flags, void **target_obj); /** - * Iterate over all AVOptions belonging to obj. + * Show the obj options. * - * @param obj an AVOptions-enabled struct or a double pointer to an - * AVClass describing it. - * @param prev result of the previous call to av_opt_next() on this object - * or NULL - * @return next AVOption or NULL + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options */ -const AVOption *av_opt_next(const void *obj, const AVOption *prev); +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); /** - * Iterate over AVOptions-enabled children of obj. + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present * - * @param prev result of a previous call to this function or NULL - * @return next AVOptions-enabled child or NULL */ -void *av_opt_child_next(void *obj, void *prev); +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; /** - * Iterate over potential AVOptions-enabled children of parent. + * @} + */ + +/** + * @defgroup opt_write Setting and modifying option values + * @{ + */ + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. * - * @param iter a pointer where iteration state is stored. - * @return AVClass corresponding to next potential child or NULL + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_opt_set() if a key/value pair + * cannot be set */ -const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Copy options from src object into dest object. + * + * The underlying AVClass of both src and dest must coincide. The guarantee + * below does not apply if this is not fulfilled. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * Even on error it is guaranteed that allocated options from src and dest + * no longer alias each other afterwards; in particular calling av_opt_free() + * on both src and dest is safe afterwards if dest has been memdup'ed from src. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); /** * @defgroup opt_set_funcs Option setting functions @@ -697,10 +786,6 @@ int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_ int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); -#if FF_API_OLD_CHANNEL_LAYOUT -attribute_deprecated -int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags); -#endif int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, int search_flags); /** * @note Any old dictionary present is discarded and replaced with a copy of the new one. The @@ -726,6 +811,12 @@ int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, in /** * @} + * @} + */ + +/** + * @defgroup opt_read Reading option values + * @{ */ /** @@ -756,10 +847,6 @@ int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_ int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); -#if FF_API_OLD_CHANNEL_LAYOUT -attribute_deprecated -int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout); -#endif int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout); /** * @param[out] out_val The returned dictionary is a copy of the actual value and must @@ -769,70 +856,40 @@ int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDiction /** * @} */ -/** - * Gets a pointer to the requested field in a struct. - * This function allows accessing a struct even when its fields are moved or - * renamed since the application making the access has been compiled, - * - * @returns a pointer to the field, it can be cast to the correct type and read - * or written to. - */ -void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); - -/** - * Free an AVOptionRanges struct and set it to NULL. - */ -void av_opt_freep_ranges(AVOptionRanges **ranges); /** - * Get a list of allowed ranges for the given option. - * - * The returned list may depend on other fields in obj like for example profile. - * - * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored - * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance - * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. * - * The result must be freed with av_opt_freep_ranges. + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. * - * @return number of compontents returned on success, a negative errro code otherwise + * @return 0 on success, a negative number on failure. */ -int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); - +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); /** - * Copy options from src object into dest object. - * - * The underlying AVClass of both src and dest must coincide. The guarantee - * below does not apply if this is not fulfilled. - * - * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. - * Original memory allocated for such options is freed unless both src and dest options points to the same memory. - * - * Even on error it is guaranteed that allocated options from src and dest - * no longer alias each other afterwards; in particular calling av_opt_free() - * on both src and dest is safe afterwards if dest has been memdup'ed from src. - * - * @param dest Object to copy from - * @param src Object to copy into - * @return 0 on success, negative on error + * @} */ -int av_opt_copy(void *dest, const void *src); /** - * Get a default list of allowed ranges for the given option. - * - * This list is constructed without using the AVClass.query_ranges() callback - * and can be used as fallback from within the callback. - * - * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored - * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance - * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges - * - * The result must be freed with av_opt_free_ranges. + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, * - * @return number of compontents returned on success, a negative errro code otherwise + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. */ -int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); /** * Check if given option is set to its default value. @@ -860,6 +917,15 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o); */ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); #define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. #define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. @@ -884,6 +950,47 @@ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_fla */ int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + /** * @} */ diff --git a/media/ffvpx/libavutil/pixdesc.c b/media/ffvpx/libavutil/pixdesc.c index f6d4d01460..1c0bcf2232 100644 --- a/media/ffvpx/libavutil/pixdesc.c +++ b/media/ffvpx/libavutil/pixdesc.c @@ -460,12 +460,6 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, -#if FF_API_XVMC - [AV_PIX_FMT_XVMC] = { - .name = "xvmc", - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, -#endif [AV_PIX_FMT_UYVY422] = { .name = "uyvy422", .nb_components = 3, @@ -2860,6 +2854,9 @@ static const char * const color_space_names[] = { [AVCOL_SPC_CHROMA_DERIVED_NCL] = "chroma-derived-nc", [AVCOL_SPC_CHROMA_DERIVED_CL] = "chroma-derived-c", [AVCOL_SPC_ICTCP] = "ictcp", + [AVCOL_SPC_IPT_C2] = "ipt-c2", + [AVCOL_SPC_YCGCO_RE] = "ycgco-re", + [AVCOL_SPC_YCGCO_RO] = "ycgco-ro", }; static const char * const chroma_location_names[] = { diff --git a/media/ffvpx/libavutil/pixfmt.h b/media/ffvpx/libavutil/pixfmt.h index 9c87571f49..a7f50e1690 100644 --- a/media/ffvpx/libavutil/pixfmt.h +++ b/media/ffvpx/libavutil/pixfmt.h @@ -33,6 +33,13 @@ #define AVPALETTE_COUNT 256 /** + * Maximum number of planes in any pixel format. + * This should be used when a maximum is needed, but code should not + * be written to require a maximum for no good reason. + */ +#define AV_VIDEO_MAX_PLANES 4 + +/** * Pixel format. * * @note @@ -288,10 +295,6 @@ enum AVPixelFormat { AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian -#if FF_API_XVMC - AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing -#endif - AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian @@ -620,6 +623,9 @@ enum AVColorSpace { AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_IPT_C2 = 15, ///< SMPTE ST 2128, IPT-C2 + AVCOL_SPC_YCGCO_RE = 16, ///< YCgCo-R, even addition of bits + AVCOL_SPC_YCGCO_RO = 17, ///< YCgCo-R, odd addition of bits AVCOL_SPC_NB ///< Not part of ABI }; diff --git a/media/ffvpx/libavutil/rational.c b/media/ffvpx/libavutil/rational.c index eb148ddb12..329fbf3302 100644 --- a/media/ffvpx/libavutil/rational.c +++ b/media/ffvpx/libavutil/rational.c @@ -114,7 +114,7 @@ AVRational av_d2q(double d, int max) return (AVRational) { d < 0 ? -1 : 1, 0 }; frexp(d, &exponent); exponent = FFMAX(exponent-1, 0); - den = 1LL << (61 - exponent); + den = 1LL << (62 - exponent); // (int64_t)rint() and llrint() do not work with gcc on ia64 and sparc64, // see Ticket2713 for affected gcc/glibc versions av_reduce(&a.num, &a.den, floor(d * den + 0.5), den, max); diff --git a/media/ffvpx/libavutil/rational.h b/media/ffvpx/libavutil/rational.h index 8cbfc8e066..849f47f38d 100644 --- a/media/ffvpx/libavutil/rational.h +++ b/media/ffvpx/libavutil/rational.h @@ -168,6 +168,10 @@ static av_always_inline AVRational av_inv_q(AVRational q) * In case of infinity, the returned value is expressed as `{1, 0}` or * `{-1, 0}` depending on the sign. * + * In general rational numbers with |num| <= 1<<26 && |den| <= 1<<26 + * can be recovered exactly from their double representation. + * (no exceptions were found within 1B random ones) + * * @param d `double` to convert * @param max Maximum allowed numerator and denominator * @return `d` in AVRational form diff --git a/media/ffvpx/libavutil/thread.h b/media/ffvpx/libavutil/thread.h index 2ded498c89..2c00c7cc35 100644 --- a/media/ffvpx/libavutil/thread.h +++ b/media/ffvpx/libavutil/thread.h @@ -26,6 +26,8 @@ #if HAVE_PRCTL #include <sys/prctl.h> +#elif (HAVE_PTHREAD_SETNAME_NP || HAVE_PTHREAD_SET_NAME_NP) && HAVE_PTHREAD_NP_H +#include <pthread_np.h> #endif #include "error.h" @@ -213,11 +215,25 @@ static inline int ff_thread_once(char *control, void (*routine)(void)) static inline int ff_thread_setname(const char *name) { + int ret = 0; + #if HAVE_PRCTL - return AVERROR(prctl(PR_SET_NAME, name)); + ret = AVERROR(prctl(PR_SET_NAME, name)); +#elif HAVE_PTHREAD_SETNAME_NP +#if defined(__APPLE__) + ret = AVERROR(pthread_setname_np(name)); +#elif defined(__NetBSD__) + ret = AVERROR(pthread_setname_np(pthread_self(), "%s", name)); +#else + ret = AVERROR(pthread_setname_np(pthread_self(), name)); +#endif +#elif HAVE_PTHREAD_SET_NAME_NP + pthread_set_name_np(pthread_self(), name); +#else + ret = AVERROR(ENOSYS); #endif - return AVERROR(ENOSYS); + return ret; } #endif /* AVUTIL_THREAD_H */ diff --git a/media/ffvpx/libavutil/timecode.c b/media/ffvpx/libavutil/timecode.c index b93f05b4b8..bd879bd3cc 100644 --- a/media/ffvpx/libavutil/timecode.c +++ b/media/ffvpx/libavutil/timecode.c @@ -210,7 +210,7 @@ static int fps_from_frame_rate(AVRational rate) { if (!rate.den || !rate.num) return -1; - return (rate.num + rate.den/2) / rate.den; + return (rate.num + rate.den/2LL) / rate.den; } int av_timecode_check_frame_rate(AVRational rate) diff --git a/media/ffvpx/libavutil/timestamp.h b/media/ffvpx/libavutil/timestamp.h index 9ae64da8a1..fa53a46b98 100644 --- a/media/ffvpx/libavutil/timestamp.h +++ b/media/ffvpx/libavutil/timestamp.h @@ -62,11 +62,18 @@ static inline char *av_ts_make_string(char *buf, int64_t ts) * @param tb the timebase of the timestamp * @return the buffer in input */ -static inline char *av_ts_make_time_string(char *buf, int64_t ts, AVRational *tb) +char *av_ts_make_time_string2(char *buf, int64_t ts, AVRational tb); + +/** + * Fill the provided buffer with a string containing a timestamp + * representation. + * + * @see av_ts_make_time_string2 + */ +static inline char *av_ts_make_time_string(char *buf, int64_t ts, + const AVRational *tb) { - if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS"); - else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.6g", av_q2d(*tb) * ts); - return buf; + return av_ts_make_time_string2(buf, ts, *tb); } /** diff --git a/media/ffvpx/libavutil/tx.c b/media/ffvpx/libavutil/tx.c index a1f767039b..426303d1f3 100644 --- a/media/ffvpx/libavutil/tx.c +++ b/media/ffvpx/libavutil/tx.c @@ -19,6 +19,7 @@ #include "avassert.h" #include "intmath.h" #include "cpu.h" +#include "mem.h" #include "qsort.h" #include "bprint.h" @@ -593,7 +594,8 @@ static void print_type(AVBPrint *bp, enum AVTXType type) "unknown"); } -static void print_cd_info(const FFTXCodelet *cd, int prio, int len, int print_prio) +static void print_cd_info(const FFTXCodelet *cd, int prio, int len, int print_prio, + int log_level) { AVBPrint bp; av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); @@ -643,7 +645,7 @@ static void print_cd_info(const FFTXCodelet *cd, int prio, int len, int print_pr if (print_prio) av_bprintf(&bp, ", prio: %i", prio); - av_log(NULL, AV_LOG_DEBUG, "%s\n", bp.str); + av_log(NULL, log_level, "%s\n", bp.str); } static void print_tx_structure(AVTXContext *s, int depth) @@ -653,7 +655,7 @@ static void print_tx_structure(AVTXContext *s, int depth) for (int i = 0; i <= depth; i++) av_log(NULL, AV_LOG_DEBUG, " "); - print_cd_info(cd, cd->prio, s->len, 0); + print_cd_info(cd, cd->prio, s->len, 0, AV_LOG_DEBUG); for (int i = 0; i < s->nb_sub; i++) print_tx_structure(&s->sub[i], depth + 1); @@ -816,11 +818,11 @@ av_cold int ff_tx_init_subtx(AVTXContext *s, enum AVTXType type, AV_QSORT(cd_matches, nb_cd_matches, TXCodeletMatch, cmp_matches); #if !CONFIG_SMALL - av_log(NULL, AV_LOG_DEBUG, "%s\n", bp.str); + av_log(NULL, AV_LOG_TRACE, "%s\n", bp.str); for (int i = 0; i < nb_cd_matches; i++) { - av_log(NULL, AV_LOG_DEBUG, " %i: ", i + 1); - print_cd_info(cd_matches[i].cd, cd_matches[i].prio, 0, 1); + av_log(NULL, AV_LOG_TRACE, " %i: ", i + 1); + print_cd_info(cd_matches[i].cd, cd_matches[i].prio, 0, 1, AV_LOG_TRACE); } #endif @@ -914,10 +916,12 @@ av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, if (!(flags & AV_TX_INPLACE)) flags |= FF_TX_OUT_OF_PLACE; - if (!scale && ((type == AV_TX_FLOAT_MDCT) || (type == AV_TX_INT32_MDCT))) - scale = &default_scale_f; - else if (!scale && (type == AV_TX_DOUBLE_MDCT)) + if (!scale && ((type == AV_TX_DOUBLE_MDCT) || (type == AV_TX_DOUBLE_DCT) || + (type == AV_TX_DOUBLE_DCT_I) || (type == AV_TX_DOUBLE_DST_I) || + (type == AV_TX_DOUBLE_RDFT))) scale = &default_scale_d; + else if (!scale && !TYPE_IS(FFT, type)) + scale = &default_scale_f; ret = ff_tx_init_subtx(&tmp, type, flags, NULL, len, inv, scale); if (ret < 0) diff --git a/media/ffvpx/libavutil/tx_template.c b/media/ffvpx/libavutil/tx_template.c index a2c27465cb..701ef0d6de 100644 --- a/media/ffvpx/libavutil/tx_template.c +++ b/media/ffvpx/libavutil/tx_template.c @@ -24,6 +24,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "mem.h" + #define TABLE_DEF(name, size) \ DECLARE_ALIGNED(32, TXSample, TX_TAB(ff_tx_tab_ ##name))[size] diff --git a/media/ffvpx/libavutil/version.h b/media/ffvpx/libavutil/version.h index 772c4e209c..da1a833255 100644 --- a/media/ffvpx/libavutil/version.h +++ b/media/ffvpx/libavutil/version.h @@ -78,9 +78,9 @@ * @{ */ -#define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 36 -#define LIBAVUTIL_VERSION_MICRO 101 +#define LIBAVUTIL_VERSION_MAJOR 59 +#define LIBAVUTIL_VERSION_MINOR 13 +#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ @@ -105,20 +105,13 @@ * @{ */ -#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_PKT_DURATION (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_REORDERED_OPAQUE (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_FRAME_PICTURE_NUMBER (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_FRAME_KEY (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_PALETTE_HAS_CHANGED (LIBAVUTIL_VERSION_MAJOR < 59) -#define FF_API_VULKAN_CONTIGUOUS_MEMORY (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_FRAME_KEY (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_PALETTE_HAS_CHANGED (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_VULKAN_CONTIGUOUS_MEMORY (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_H274_FILM_GRAIN_VCS (LIBAVUTIL_VERSION_MAJOR < 60) /** * @} diff --git a/media/ffvpx/libavutil/x86/emms.h b/media/ffvpx/libavutil/x86/emms.h deleted file mode 100644 index 8ceec110cf..0000000000 --- a/media/ffvpx/libavutil/x86/emms.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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_X86_EMMS_H -#define AVUTIL_X86_EMMS_H - -#include "config.h" -#include "libavutil/attributes.h" - -void avpriv_emms_asm(void); - -#if HAVE_MMX_INLINE -#ifndef __MMX__ -#include "libavutil/cpu.h" -#endif - -# define emms_c emms_c -/** - * Empty mmx state. - * this must be called between any dsp function and float/double code. - * for example sin(); dsp->idct_put(); emms_c(); cos() - * Note, *alloc() and *free() also use float code in some libc implementations - * thus this also applies to them or any function using them. - */ -static av_always_inline void emms_c(void) -{ -/* Some inlined functions may also use mmx instructions regardless of - * runtime cpuflags. With that in mind, we unconditionally empty the - * mmx state if the target cpu chosen at configure time supports it. - */ -#if !defined(__MMX__) - if(av_get_cpu_flags() & AV_CPU_FLAG_MMX) -#endif - __asm__ volatile ("emms" ::: "memory"); -} -#elif HAVE_MMX && HAVE_MM_EMPTY -# include <mmintrin.h> -# define emms_c _mm_empty -#elif HAVE_MMX_EXTERNAL -# define emms_c avpriv_emms_asm -#endif /* HAVE_MMX_INLINE */ - -#endif /* AVUTIL_X86_EMMS_H */ diff --git a/media/ffvpx/libavutil/x86/fixed_dsp_init.c b/media/ffvpx/libavutil/x86/fixed_dsp_init.c index d3f4b2e325..3dd508a4f4 100644 --- a/media/ffvpx/libavutil/x86/fixed_dsp_init.c +++ b/media/ffvpx/libavutil/x86/fixed_dsp_init.c @@ -16,14 +16,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" - #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/fixed_dsp.h" #include "cpu.h" -void ff_butterflies_fixed_sse2(int *av_restrict src0, int *av_restrict src1, int len); +void ff_butterflies_fixed_sse2(int *restrict src0, int *restrict src1, int len); av_cold void ff_fixed_dsp_init_x86(AVFixedDSPContext *fdsp) { diff --git a/media/ffvpx/libavutil/x86/float_dsp_init.c b/media/ffvpx/libavutil/x86/float_dsp_init.c index ad6b506259..093bce9b94 100644 --- a/media/ffvpx/libavutil/x86/float_dsp_init.c +++ b/media/ffvpx/libavutil/x86/float_dsp_init.c @@ -16,13 +16,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" - #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/float_dsp.h" #include "cpu.h" -#include "asm.h" void ff_vector_fmul_sse(float *dst, const float *src0, const float *src1, int len); @@ -76,7 +73,7 @@ void ff_vector_fmul_reverse_avx2(float *dst, const float *src0, float ff_scalarproduct_float_sse(const float *v1, const float *v2, int order); float ff_scalarproduct_float_fma3(const float *v1, const float *v2, int order); -void ff_butterflies_float_sse(float *av_restrict src0, float *av_restrict src1, int len); +void ff_butterflies_float_sse(float *restrict src0, float *restrict src1, int len); av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) { diff --git a/media/ffvpx/libavutil/x86/intreadwrite.h b/media/ffvpx/libavutil/x86/intreadwrite.h index 40f375b013..5e57d6a8cd 100644 --- a/media/ffvpx/libavutil/x86/intreadwrite.h +++ b/media/ffvpx/libavutil/x86/intreadwrite.h @@ -27,42 +27,6 @@ #if HAVE_MMX -#if !HAVE_FAST_64BIT && defined(__MMX__) - -#define FF_COPY_SWAP_ZERO_USES_MMX - -#define AV_COPY64 AV_COPY64 -static av_always_inline void AV_COPY64(void *d, const void *s) -{ - __asm__("movq %1, %%mm0 \n\t" - "movq %%mm0, %0 \n\t" - : "=m"(*(uint64_t*)d) - : "m" (*(const uint64_t*)s) - : "mm0"); -} - -#define AV_SWAP64 AV_SWAP64 -static av_always_inline void AV_SWAP64(void *a, void *b) -{ - __asm__("movq %1, %%mm0 \n\t" - "movq %0, %%mm1 \n\t" - "movq %%mm0, %0 \n\t" - "movq %%mm1, %1 \n\t" - : "+m"(*(uint64_t*)a), "+m"(*(uint64_t*)b) - ::"mm0", "mm1"); -} - -#define AV_ZERO64 AV_ZERO64 -static av_always_inline void AV_ZERO64(void *d) -{ - __asm__("pxor %%mm0, %%mm0 \n\t" - "movq %%mm0, %0 \n\t" - : "=m"(*(uint64_t*)d) - :: "mm0"); -} - -#endif /* !HAVE_FAST_64BIT && defined(__MMX__) */ - #ifdef __SSE__ #define AV_COPY128 AV_COPY128 diff --git a/media/ffvpx/libavutil/x86/moz.build b/media/ffvpx/libavutil/x86/moz.build index df33768f66..9a730c5746 100644 --- a/media/ffvpx/libavutil/x86/moz.build +++ b/media/ffvpx/libavutil/x86/moz.build @@ -16,6 +16,8 @@ SOURCES += [ 'imgutils_init.c', 'lls.asm', 'lls_init.c', + 'pixelutils.asm', + 'pixelutils_init.c', 'tx_float.asm', 'tx_float_init.c', ] diff --git a/media/ffvpx/libavutil/x86/tx_float.asm b/media/ffvpx/libavutil/x86/tx_float.asm index e1533a8595..42006848f1 100644 --- a/media/ffvpx/libavutil/x86/tx_float.asm +++ b/media/ffvpx/libavutil/x86/tx_float.asm @@ -46,7 +46,7 @@ %endif %assign i 16 -%rep 14 +%rep 18 cextern tab_ %+ i %+ _float ; ff_tab_i_float... %assign i (i << 1) %endrep @@ -1385,7 +1385,11 @@ FFT_SPLIT_RADIX_DEF 8192, .16384pt FFT_SPLIT_RADIX_DEF 16384, .32768pt FFT_SPLIT_RADIX_DEF 32768, .65536pt FFT_SPLIT_RADIX_DEF 65536, .131072pt -FFT_SPLIT_RADIX_DEF 131072 +FFT_SPLIT_RADIX_DEF 131072, .262144pt +FFT_SPLIT_RADIX_DEF 262144, .524288pt +FFT_SPLIT_RADIX_DEF 524288, .1048576pt +FFT_SPLIT_RADIX_DEF 1048576, .2097152pt +FFT_SPLIT_RADIX_DEF 2097152 ;=============================================================================== ; Final synthesis + deinterleaving code diff --git a/media/ffvpx/libavutil/x86/tx_float_init.c b/media/ffvpx/libavutil/x86/tx_float_init.c index d3c0beb50f..36da9325e5 100644 --- a/media/ffvpx/libavutil/x86/tx_float_init.c +++ b/media/ffvpx/libavutil/x86/tx_float_init.c @@ -19,6 +19,7 @@ #define TX_FLOAT #include "libavutil/tx_priv.h" #include "libavutil/attributes.h" +#include "libavutil/mem.h" #include "libavutil/x86/cpu.h" #include "config.h" @@ -270,15 +271,15 @@ const FFTXCodelet * const ff_tx_codelet_list_float_x86[] = { AV_TX_INPLACE | FF_TX_PRESHUFFLE | FF_TX_ASM_CALL, AV_CPU_FLAG_AVXSLOW), TX_DEF(fft32_ns, FFT, 32, 32, 2, 0, 352, b8_i2, fma3, FMA3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, AV_CPU_FLAG_AVXSLOW), - TX_DEF(fft_sr, FFT, 64, 131072, 2, 0, 256, b8_i2, avx, AVX, 0, AV_CPU_FLAG_AVXSLOW), - TX_DEF(fft_sr_asm, FFT, 64, 131072, 2, 0, 320, b8_i2, avx, AVX, + TX_DEF(fft_sr, FFT, 64, 2097152, 2, 0, 256, b8_i2, avx, AVX, 0, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft_sr_asm, FFT, 64, 2097152, 2, 0, 320, b8_i2, avx, AVX, AV_TX_INPLACE | FF_TX_PRESHUFFLE | FF_TX_ASM_CALL, AV_CPU_FLAG_AVXSLOW), - TX_DEF(fft_sr_ns, FFT, 64, 131072, 2, 0, 320, b8_i2, avx, AVX, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + TX_DEF(fft_sr_ns, FFT, 64, 2097152, 2, 0, 320, b8_i2, avx, AVX, AV_TX_INPLACE | FF_TX_PRESHUFFLE, AV_CPU_FLAG_AVXSLOW), - TX_DEF(fft_sr, FFT, 64, 131072, 2, 0, 288, b8_i2, fma3, FMA3, 0, AV_CPU_FLAG_AVXSLOW), - TX_DEF(fft_sr_asm, FFT, 64, 131072, 2, 0, 352, b8_i2, fma3, FMA3, + TX_DEF(fft_sr, FFT, 64, 2097152, 2, 0, 288, b8_i2, fma3, FMA3, 0, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft_sr_asm, FFT, 64, 2097152, 2, 0, 352, b8_i2, fma3, FMA3, AV_TX_INPLACE | FF_TX_PRESHUFFLE | FF_TX_ASM_CALL, AV_CPU_FLAG_AVXSLOW), - TX_DEF(fft_sr_ns, FFT, 64, 131072, 2, 0, 352, b8_i2, fma3, FMA3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + TX_DEF(fft_sr_ns, FFT, 64, 2097152, 2, 0, 352, b8_i2, fma3, FMA3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, AV_CPU_FLAG_AVXSLOW), #if HAVE_AVX2_EXTERNAL @@ -287,11 +288,11 @@ const FFTXCodelet * const ff_tx_codelet_list_float_x86[] = { TX_DEF(fft15_ns, FFT, 15, 15, 15, 0, 384, factor_init, avx2, AVX2, AV_TX_INPLACE | FF_TX_PRESHUFFLE, AV_CPU_FLAG_AVXSLOW), - TX_DEF(fft_sr, FFT, 64, 131072, 2, 0, 320, b8_i2, avx2, AVX2, 0, + TX_DEF(fft_sr, FFT, 64, 2097152, 2, 0, 320, b8_i2, avx2, AVX2, 0, AV_CPU_FLAG_AVXSLOW | AV_CPU_FLAG_SLOW_GATHER), - TX_DEF(fft_sr_asm, FFT, 64, 131072, 2, 0, 384, b8_i2, avx2, AVX2, + TX_DEF(fft_sr_asm, FFT, 64, 2097152, 2, 0, 384, b8_i2, avx2, AVX2, AV_TX_INPLACE | FF_TX_PRESHUFFLE | FF_TX_ASM_CALL, AV_CPU_FLAG_AVXSLOW | AV_CPU_FLAG_SLOW_GATHER), - TX_DEF(fft_sr_ns, FFT, 64, 131072, 2, 0, 384, b8_i2, avx2, AVX2, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + TX_DEF(fft_sr_ns, FFT, 64, 2097152, 2, 0, 384, b8_i2, avx2, AVX2, AV_TX_INPLACE | FF_TX_PRESHUFFLE, AV_CPU_FLAG_AVXSLOW | AV_CPU_FLAG_SLOW_GATHER), TX_DEF(fft_pfa_15xM, FFT, 60, TX_LEN_UNLIMITED, 15, 2, 320, fft_pfa_init, avx2, AVX2, diff --git a/media/ffvpx/libavutil/x86/x86inc.asm b/media/ffvpx/libavutil/x86/x86inc.asm index e099ee4b10..e61d924bc1 100644 --- a/media/ffvpx/libavutil/x86/x86inc.asm +++ b/media/ffvpx/libavutil/x86/x86inc.asm @@ -1,7 +1,7 @@ ;***************************************************************************** -;* x86inc.asm: x264asm abstraction layer +;* x86inc.asm: x86 abstraction layer ;***************************************************************************** -;* Copyright (C) 2005-2018 x264 project +;* Copyright (C) 2005-2024 x264 project ;* ;* Authors: Loren Merritt <lorenm@u.washington.edu> ;* Henrik Gramner <henrik@gramner.com> @@ -21,21 +21,14 @@ ;* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ;***************************************************************************** -; This is a header file for the x264ASM assembly language, which uses +; This is a header file for the x86inc.asm assembly language, which uses ; NASM/YASM syntax combined with a large number of macros to provide easy ; abstraction between different calling conventions (x86_32, win64, linux64). ; It also has various other useful features to simplify writing the kind of -; DSP functions that are most often used in x264. - -; Unlike the rest of x264, this file is available under an ISC license, as it -; has significant usefulness outside of x264 and we want it to be available -; to the largest audience possible. Of course, if you modify it for your own -; purposes to add a new feature, we strongly encourage contributing a patch -; as this feature might be useful for others as well. Send patches or ideas -; to x264-devel@videolan.org . +; DSP functions that are most often used. %ifndef private_prefix - %define private_prefix x264 + %error private_prefix not defined %endif %ifndef public_prefix @@ -68,12 +61,19 @@ %endif %define FORMAT_ELF 0 +%define FORMAT_MACHO 0 %ifidn __OUTPUT_FORMAT__,elf %define FORMAT_ELF 1 %elifidn __OUTPUT_FORMAT__,elf32 %define FORMAT_ELF 1 %elifidn __OUTPUT_FORMAT__,elf64 %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,macho + %define FORMAT_MACHO 1 +%elifidn __OUTPUT_FORMAT__,macho32 + %define FORMAT_MACHO 1 +%elifidn __OUTPUT_FORMAT__,macho64 + %define FORMAT_MACHO 1 %endif %ifdef PREFIX @@ -82,6 +82,11 @@ %define mangle(x) x %endif +; Use VEX-encoding even in non-AVX functions +%ifndef FORCE_VEX_ENCODING + %define FORCE_VEX_ENCODING 0 +%endif + ; aout does not support align= ; NOTE: This section is out of sync with x264, in order to ; keep supporting OS/2. @@ -99,28 +104,27 @@ %endif %endmacro -%if WIN64 - %define PIC -%elif ARCH_X86_64 == 0 -; x86_32 doesn't require PIC. -; Some distros prefer shared objects to be PIC, but nothing breaks if -; the code contains a few textrels, so we'll skip that complexity. - %undef PIC -%endif -%ifdef PIC +%if ARCH_X86_64 + %define PIC 1 ; always use PIC on x86-64 default rel +%elifidn __OUTPUT_FORMAT__,win32 + %define PIC 0 ; PIC isn't used on 32-bit Windows +%elifndef PIC + %define PIC 0 %endif -%macro CPUNOP 1 - %if HAVE_CPUNOP - CPU %1 +%define HAVE_PRIVATE_EXTERN 1 +%ifdef __NASM_VERSION_ID__ + %use smartalign + %if __NASM_VERSION_ID__ < 0x020e0000 ; 2.14 + %define HAVE_PRIVATE_EXTERN 0 %endif -%endmacro +%endif ; Macros to eliminate most code duplication between x86_32 and x86_64: ; Currently this works only for leaf functions which load all their arguments ; into registers at the start, and make no other use of the stack. Luckily that -; covers most of x264's asm. +; covers most use cases. ; PROLOGUE: ; %1 = number of arguments. loads them from stack if needed. @@ -232,6 +236,18 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %define gprsize 4 %endif +%macro LEA 2 +%if ARCH_X86_64 + lea %1, [%2] +%elif PIC + call $+5 ; special-cased to not affect the RSB on most CPU:s + pop %1 + add %1, (%2)-$+1 +%else + mov %1, %2 +%endif +%endmacro + ; Repeats an instruction/operation for multiple arguments. ; Example usage: "REPX {psrlw x, 8}, m0, m1, m2, m3" %macro REPX 2-* ; operation, args @@ -303,6 +319,10 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %endif %endmacro +%if ARCH_X86_64 == 0 + %define movsxd movifnidn +%endif + %macro movsxdifnidn 2 %ifnidn %1, %2 movsxd %1, %2 @@ -354,7 +374,46 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %define vzeroupper_required (mmsize > 16 && (ARCH_X86_64 == 0 || xmm_regs_used > 16 || notcpuflag(avx512))) %define high_mm_regs (16*cpuflag(avx512)) -%macro ALLOC_STACK 1-2 0 ; stack_size, n_xmm_regs (for win64 only) +; Large stack allocations on Windows need to use stack probing in order +; to guarantee that all stack memory is committed before accessing it. +; This is done by ensuring that the guard page(s) at the end of the +; currently committed pages are touched prior to any pages beyond that. +%if WIN64 + %assign STACK_PROBE_SIZE 8192 +%elifidn __OUTPUT_FORMAT__, win32 + %assign STACK_PROBE_SIZE 4096 +%else + %assign STACK_PROBE_SIZE 0 +%endif + +%macro PROBE_STACK 1 ; stack_size + %if STACK_PROBE_SIZE + %assign %%i STACK_PROBE_SIZE + %rep %1 / STACK_PROBE_SIZE + mov eax, [rsp-%%i] + %assign %%i %%i+STACK_PROBE_SIZE + %endrep + %endif +%endmacro + +%macro RESET_STACK_STATE 0 + %ifidn rstk, rsp + %assign stack_offset stack_offset - stack_size_padded + %else + %xdefine rstk rsp + %endif + %assign stack_size 0 + %assign stack_size_padded 0 + %assign xmm_regs_used 0 +%endmacro + +%macro ALLOC_STACK 0-2 0, 0 ; stack_size, n_xmm_regs + RESET_STACK_STATE + %ifnum %2 + %if mmsize != 8 + %assign xmm_regs_used %2 + %endif + %endif %ifnum %1 %if %1 != 0 %assign %%pad 0 @@ -364,16 +423,14 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %endif %if WIN64 %assign %%pad %%pad + 32 ; shadow space - %if mmsize != 8 - %assign xmm_regs_used %2 - %if xmm_regs_used > 8 - %assign %%pad %%pad + (xmm_regs_used-8)*16 ; callee-saved xmm registers - %endif + %if xmm_regs_used > 8 + %assign %%pad %%pad + (xmm_regs_used-8)*16 ; callee-saved xmm registers %endif %endif %if required_stack_alignment <= STACK_ALIGNMENT ; maintain the current stack alignment %assign stack_size_padded stack_size + %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) + PROBE_STACK stack_size_padded SUB rsp, stack_size_padded %else %assign %%reg_num (regs_used - 1) @@ -389,6 +446,7 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %xdefine rstkm rstk %endif %assign stack_size_padded stack_size + ((%%pad + required_stack_alignment-1) & ~(required_stack_alignment-1)) + PROBE_STACK stack_size_padded mov rstk, rsp and rsp, ~(required_stack_alignment-1) sub rsp, stack_size_padded @@ -399,7 +457,7 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %endif %endmacro -%macro SETUP_STACK_POINTER 1 +%macro SETUP_STACK_POINTER 0-1 0 %ifnum %1 %if %1 != 0 && required_stack_alignment > STACK_ALIGNMENT %if %1 > 0 @@ -462,35 +520,62 @@ DECLARE_REG 14, R13, 120 %endif %endmacro -%macro WIN64_PUSH_XMM 0 - ; Use the shadow space to store XMM6 and XMM7, the rest needs stack space allocated. - %if xmm_regs_used > 6 + high_mm_regs - movaps [rstk + stack_offset + 8], xmm6 - %endif - %if xmm_regs_used > 7 + high_mm_regs - movaps [rstk + stack_offset + 24], xmm7 - %endif - %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 - %if %%xmm_regs_on_stack > 0 - %assign %%i 8 - %rep %%xmm_regs_on_stack - movaps [rsp + (%%i-8)*16 + stack_size + 32], xmm %+ %%i - %assign %%i %%i+1 - %endrep +; Push XMM registers to the stack. If no argument is specified all used register +; will be pushed, otherwise only push previously unpushed registers. +%macro WIN64_PUSH_XMM 0-2 ; new_xmm_regs_used, xmm_regs_pushed + %if mmsize != 8 + %if %0 == 2 + %assign %%pushed %2 + %assign xmm_regs_used %1 + %elif %0 == 1 + %assign %%pushed xmm_regs_used + %assign xmm_regs_used %1 + %else + %assign %%pushed 0 + %endif + ; Use the shadow space to store XMM6 and XMM7, the rest needs stack space allocated. + %if %%pushed <= 6 + high_mm_regs && xmm_regs_used > 6 + high_mm_regs + movaps [rstk + stack_offset + 8], xmm6 + %endif + %if %%pushed <= 7 + high_mm_regs && xmm_regs_used > 7 + high_mm_regs + movaps [rstk + stack_offset + 24], xmm7 + %endif + %assign %%pushed %%pushed - high_mm_regs - 8 + %if %%pushed < 0 + %assign %%pushed 0 + %endif + %assign %%regs_to_push xmm_regs_used - %%pushed - high_mm_regs - 8 + %if %%regs_to_push > 0 + ASSERT (%%regs_to_push + %%pushed) * 16 <= stack_size_padded - stack_size - 32 + %assign %%i %%pushed + 8 + %rep %%regs_to_push + movaps [rsp + (%%i-8)*16 + stack_size + 32], xmm %+ %%i + %assign %%i %%i+1 + %endrep + %endif %endif %endmacro -%macro WIN64_SPILL_XMM 1 - %assign xmm_regs_used %1 - ASSERT xmm_regs_used <= 16 + high_mm_regs - %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 - %if %%xmm_regs_on_stack > 0 - ; Allocate stack space for callee-saved xmm registers plus shadow space and align the stack. - %assign %%pad %%xmm_regs_on_stack*16 + 32 - %assign stack_size_padded %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) - SUB rsp, stack_size_padded +; Allocated stack space for XMM registers and push all, or a subset, of those +%macro WIN64_SPILL_XMM 1-2 ; xmm_regs_used, xmm_regs_reserved + RESET_STACK_STATE + %if mmsize != 8 + %assign xmm_regs_used %1 + ASSERT xmm_regs_used <= 16 + high_mm_regs + %if %0 == 2 + ASSERT %2 >= %1 + %assign %%xmm_regs_on_stack %2 - high_mm_regs - 8 + %else + %assign %%xmm_regs_on_stack %1 - high_mm_regs - 8 + %endif + %if %%xmm_regs_on_stack > 0 + ; Allocate stack space for callee-saved xmm registers plus shadow space and align the stack. + %assign %%pad %%xmm_regs_on_stack*16 + 32 + %assign stack_size_padded %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) + SUB rsp, stack_size_padded + %endif + WIN64_PUSH_XMM %endif - WIN64_PUSH_XMM %endmacro %macro WIN64_RESTORE_XMM_INTERNAL 0 @@ -521,9 +606,7 @@ DECLARE_REG 14, R13, 120 %macro WIN64_RESTORE_XMM 0 WIN64_RESTORE_XMM_INTERNAL - %assign stack_offset (stack_offset-stack_size_padded) - %assign stack_size_padded 0 - %assign xmm_regs_used 0 + RESET_STACK_STATE %endmacro %define has_epilogue regs_used > 7 || stack_size > 0 || vzeroupper_required || xmm_regs_used > 6+high_mm_regs @@ -558,12 +641,11 @@ DECLARE_REG 14, R13, 72 %macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... %assign num_args %1 %assign regs_used %2 - %assign xmm_regs_used %3 ASSERT regs_used >= num_args SETUP_STACK_POINTER %4 ASSERT regs_used <= 15 PUSH_IF_USED 9, 10, 11, 12, 13, 14 - ALLOC_STACK %4 + ALLOC_STACK %4, %3 LOAD_IF_USED 6, 7, 8, 9, 10, 11, 12, 13, 14 %if %0 > 4 %ifnum %4 @@ -627,7 +709,7 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 SETUP_STACK_POINTER %4 ASSERT regs_used <= 7 PUSH_IF_USED 3, 4, 5, 6 - ALLOC_STACK %4 + ALLOC_STACK %4, %3 LOAD_IF_USED 0, 1, 2, 3, 4, 5, 6 %if %0 > 4 %ifnum %4 @@ -660,11 +742,19 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 %endif ;====================================================================== %if WIN64 == 0 - %macro WIN64_SPILL_XMM 1 + %macro WIN64_SPILL_XMM 1-2 + RESET_STACK_STATE + %if mmsize != 8 + %assign xmm_regs_used %1 + %endif %endmacro %macro WIN64_RESTORE_XMM 0 + RESET_STACK_STATE %endmacro - %macro WIN64_PUSH_XMM 0 + %macro WIN64_PUSH_XMM 0-2 + %if mmsize != 8 && %0 >= 1 + %assign xmm_regs_used %1 + %endif %endmacro %endif @@ -705,7 +795,7 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, jna, jnae, jb, jbe, jnb, jnbe, jc, jnc, js, jns, jo, jno, jp, jnp -%macro TAIL_CALL 2 ; callee, is_nonadjacent +%macro TAIL_CALL 1-2 1 ; callee, is_nonadjacent %if has_epilogue call %1 RET @@ -735,22 +825,25 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %endmacro %macro cglobal_internal 2-3+ annotate_function_size - %if %1 - %xdefine %%FUNCTION_PREFIX private_prefix - %xdefine %%VISIBILITY hidden - %else - %xdefine %%FUNCTION_PREFIX public_prefix - %xdefine %%VISIBILITY - %endif %ifndef cglobaled_%2 - %xdefine %2 mangle(%%FUNCTION_PREFIX %+ _ %+ %2) + %if %1 + %xdefine %2 mangle(private_prefix %+ _ %+ %2) + %else + %xdefine %2 mangle(public_prefix %+ _ %+ %2) + %endif %xdefine %2.skip_prologue %2 %+ .skip_prologue CAT_XDEFINE cglobaled_, %2, 1 %endif %xdefine current_function %2 %xdefine current_function_section __SECT__ %if FORMAT_ELF - global %2:function %%VISIBILITY + %if %1 + global %2:function hidden + %else + global %2:function + %endif + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN && %1 + global %2:private_extern %else global %2 %endif @@ -771,6 +864,8 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %macro cglobal_label 1 %if FORMAT_ELF global current_function %+ %1:function hidden + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN + global current_function %+ %1:private_extern %else global current_function %+ %1 %endif @@ -796,15 +891,34 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %xdefine %1 mangle(private_prefix %+ _ %+ %1) %if FORMAT_ELF global %1:data hidden + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN + global %1:private_extern %else global %1 %endif %1: %2 %endmacro -; This is needed for ELF, otherwise the GNU linker assumes the stack is executable by default. %if FORMAT_ELF + ; The GNU linker assumes the stack is executable by default. [SECTION .note.GNU-stack noalloc noexec nowrite progbits] + + %ifdef __NASM_VERSION_ID__ + %if __NASM_VERSION_ID__ >= 0x020e0300 ; 2.14.03 + %if ARCH_X86_64 + ; Control-flow Enforcement Technology (CET) properties. + [SECTION .note.gnu.property alloc noexec nowrite note align=gprsize] + dd 0x00000004 ; n_namesz + dd gprsize + 8 ; n_descsz + dd 0x00000005 ; n_type = NT_GNU_PROPERTY_TYPE_0 + db "GNU",0 ; n_name + dd 0xc0000002 ; pr_type = GNU_PROPERTY_X86_FEATURE_1_AND + dd 0x00000004 ; pr_datasz + dd 0x00000002 ; pr_data = GNU_PROPERTY_X86_FEATURE_1_SHSTK + dd 0x00000000 ; pr_padding + %endif + %endif + %endif %endif ; Tell debuggers how large the function was. @@ -828,32 +942,34 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, ; cpuflags %assign cpuflags_mmx (1<<0) -%assign cpuflags_mmx2 (1<<1) | cpuflags_mmx -%assign cpuflags_3dnow (1<<2) | cpuflags_mmx -%assign cpuflags_3dnowext (1<<3) | cpuflags_3dnow -%assign cpuflags_sse (1<<4) | cpuflags_mmx2 -%assign cpuflags_sse2 (1<<5) | cpuflags_sse -%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2 -%assign cpuflags_lzcnt (1<<7) | cpuflags_sse2 -%assign cpuflags_sse3 (1<<8) | cpuflags_sse2 -%assign cpuflags_ssse3 (1<<9) | cpuflags_sse3 -%assign cpuflags_sse4 (1<<10)| cpuflags_ssse3 -%assign cpuflags_sse42 (1<<11)| cpuflags_sse4 -%assign cpuflags_aesni (1<<12)| cpuflags_sse42 -%assign cpuflags_avx (1<<13)| cpuflags_sse42 -%assign cpuflags_xop (1<<14)| cpuflags_avx -%assign cpuflags_fma4 (1<<15)| cpuflags_avx -%assign cpuflags_fma3 (1<<16)| cpuflags_avx -%assign cpuflags_bmi1 (1<<17)| cpuflags_avx|cpuflags_lzcnt -%assign cpuflags_bmi2 (1<<18)| cpuflags_bmi1 -%assign cpuflags_avx2 (1<<19)| cpuflags_fma3|cpuflags_bmi2 -%assign cpuflags_avx512 (1<<20)| cpuflags_avx2 ; F, CD, BW, DQ, VL -%assign cpuflags_avx512icl (1<<25)| cpuflags_avx512 - -%assign cpuflags_cache32 (1<<21) -%assign cpuflags_cache64 (1<<22) -%assign cpuflags_aligned (1<<23) ; not a cpu feature, but a function variant -%assign cpuflags_atom (1<<24) +%assign cpuflags_mmx2 (1<<1) | cpuflags_mmx +%assign cpuflags_3dnow (1<<2) | cpuflags_mmx +%assign cpuflags_3dnowext (1<<3) | cpuflags_3dnow +%assign cpuflags_sse (1<<4) | cpuflags_mmx2 +%assign cpuflags_sse2 (1<<5) | cpuflags_sse +%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2 +%assign cpuflags_lzcnt (1<<7) | cpuflags_sse2 +%assign cpuflags_sse3 (1<<8) | cpuflags_sse2 +%assign cpuflags_ssse3 (1<<9) | cpuflags_sse3 +%assign cpuflags_sse4 (1<<10) | cpuflags_ssse3 +%assign cpuflags_sse42 (1<<11) | cpuflags_sse4 +%assign cpuflags_aesni (1<<12) | cpuflags_sse42 +%assign cpuflags_clmul (1<<13) | cpuflags_sse42 +%assign cpuflags_gfni (1<<14) | cpuflags_aesni|cpuflags_clmul +%assign cpuflags_avx (1<<15) | cpuflags_sse42 +%assign cpuflags_xop (1<<16) | cpuflags_avx +%assign cpuflags_fma4 (1<<17) | cpuflags_avx +%assign cpuflags_fma3 (1<<18) | cpuflags_avx +%assign cpuflags_bmi1 (1<<19) | cpuflags_avx|cpuflags_lzcnt +%assign cpuflags_bmi2 (1<<20) | cpuflags_bmi1 +%assign cpuflags_avx2 (1<<21) | cpuflags_fma3|cpuflags_bmi2 +%assign cpuflags_avx512 (1<<22) | cpuflags_avx2 ; F, CD, BW, DQ, VL +%assign cpuflags_avx512icl (1<<23) | cpuflags_avx512|cpuflags_gfni ; VNNI, IFMA, VBMI, VBMI2, VPOPCNTDQ, BITALG, VAES, VPCLMULQDQ + +%assign cpuflags_cache32 (1<<24) +%assign cpuflags_cache64 (1<<25) +%assign cpuflags_aligned (1<<26) ; not a cpu feature, but a function variant +%assign cpuflags_atom (1<<27) ; Returns a boolean value expressing whether or not the specified cpuflag is enabled. %define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1) @@ -895,9 +1011,17 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %endif %if ARCH_X86_64 || cpuflag(sse2) - CPUNOP amdnop + %ifdef __NASM_VERSION_ID__ + ALIGNMODE p6 + %else + CPU amdnop + %endif %else - CPUNOP basicnop + %ifdef __NASM_VERSION_ID__ + ALIGNMODE nop + %else + CPU basicnop + %endif %endif %endmacro @@ -971,7 +1095,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %endmacro %macro INIT_XMM 0-1+ - %assign avx_enabled 0 + %assign avx_enabled FORCE_VEX_ENCODING %define RESET_MM_PERMUTATION INIT_XMM %1 %define mmsize 16 %define mova movdqa @@ -983,6 +1107,9 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %if WIN64 AVX512_MM_PERMUTATION 6 ; Swap callee-saved registers with volatile registers %endif + %xdefine bcstw 1to8 + %xdefine bcstd 1to4 + %xdefine bcstq 1to2 %endmacro %macro INIT_YMM 0-1+ @@ -996,6 +1123,9 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, INIT_CPUFLAGS %1 DEFINE_MMREGS ymm AVX512_MM_PERMUTATION + %xdefine bcstw 1to16 + %xdefine bcstd 1to8 + %xdefine bcstq 1to4 %endmacro %macro INIT_ZMM 0-1+ @@ -1009,6 +1139,9 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, INIT_CPUFLAGS %1 DEFINE_MMREGS zmm AVX512_MM_PERMUTATION + %xdefine bcstw 1to32 + %xdefine bcstd 1to16 + %xdefine bcstq 1to8 %endmacro INIT_XMM @@ -1106,19 +1239,32 @@ INIT_XMM %endif %assign %%i 0 %rep num_mmregs - CAT_XDEFINE %%f, %%i, m %+ %%i + %xdefine %%tmp m %+ %%i + CAT_XDEFINE %%f, %%i, regnumof %+ %%tmp %assign %%i %%i+1 %endrep %endmacro -%macro LOAD_MM_PERMUTATION 1 ; name to load from - %ifdef %1_m0 +%macro LOAD_MM_PERMUTATION 0-1 ; name to load from + %if %0 + %xdefine %%f %1_m + %else + %xdefine %%f current_function %+ _m + %endif + %xdefine %%tmp %%f %+ 0 + %ifnum %%tmp + DEFINE_MMREGS mmtype %assign %%i 0 %rep num_mmregs - CAT_XDEFINE m, %%i, %1_m %+ %%i - CAT_XDEFINE nn, m %+ %%i, %%i + %xdefine %%tmp %%f %+ %%i + CAT_XDEFINE %%m, %%i, m %+ %%tmp %assign %%i %%i+1 %endrep + %rep num_mmregs + %assign %%i %%i-1 + CAT_XDEFINE m, %%i, %%m %+ %%i + CAT_XDEFINE nn, m %+ %%i, %%i + %endrep %endif %endmacro @@ -1224,8 +1370,22 @@ INIT_XMM %ifdef cpuname %if notcpuflag(%2) %error use of ``%1'' %2 instruction in cpuname function: current_function - %elif cpuflags_%2 < cpuflags_sse && notcpuflag(sse2) && __sizeofreg > 8 + %elif %3 == 0 && __sizeofreg == 16 && notcpuflag(sse2) %error use of ``%1'' sse2 instruction in cpuname function: current_function + %elif %3 == 0 && __sizeofreg == 32 && notcpuflag(avx2) + %error use of ``%1'' avx2 instruction in cpuname function: current_function + %elif __sizeofreg == 16 && notcpuflag(sse) + %error use of ``%1'' sse instruction in cpuname function: current_function + %elif __sizeofreg == 32 && notcpuflag(avx) + %error use of ``%1'' avx instruction in cpuname function: current_function + %elif __sizeofreg == 64 && notcpuflag(avx512) + %error use of ``%1'' avx512 instruction in cpuname function: current_function + %elifidn %1, pextrw ; special case because the base instruction is mmx2, + %ifnid %6 ; but sse4 is required for memory operands + %if notcpuflag(sse4) + %error use of ``%1'' sse4 instruction in cpuname function: current_function + %endif + %endif %endif %endif %endif @@ -1267,11 +1427,79 @@ INIT_XMM %1 %6, __src2 %endif %elif %0 >= 9 - __instr %6, %7, %8, %9 + %if avx_enabled && __sizeofreg >= 16 && %4 == 1 + %ifnnum regnumof%7 + %if %3 + vmovaps %6, %7 + %else + vmovdqa %6, %7 + %endif + __instr %6, %6, %8, %9 + %else + __instr %6, %7, %8, %9 + %endif + %else + __instr %6, %7, %8, %9 + %endif %elif %0 == 8 - __instr %6, %7, %8 + %if avx_enabled && __sizeofreg >= 16 && %4 == 0 + %xdefine __src1 %7 + %xdefine __src2 %8 + %if %5 + %ifnum regnumof%7 + %ifnum regnumof%8 + %if regnumof%7 < 8 && regnumof%8 >= 8 && regnumof%8 < 16 && sizeof%8 <= 32 + ; Most VEX-encoded instructions require an additional byte to encode when + ; src2 is a high register (e.g. m8..15). If the instruction is commutative + ; we can swap src1 and src2 when doing so reduces the instruction length. + %xdefine __src1 %8 + %xdefine __src2 %7 + %endif + %endif + %elifnum regnumof%8 ; put memory operands in src2 when possible + %xdefine __src1 %8 + %xdefine __src2 %7 + %else + %assign __emulate_avx 1 + %endif + %elifnnum regnumof%7 + ; EVEX allows imm8 shift instructions to be used with memory operands, + ; but VEX does not. This handles those special cases. + %ifnnum %8 + %assign __emulate_avx 1 + %elif notcpuflag(avx512) + %assign __emulate_avx 1 + %endif + %endif + %if __emulate_avx ; a separate load is required + %if %3 + vmovaps %6, %7 + %else + vmovdqa %6, %7 + %endif + __instr %6, %6, %8 + %else + __instr %6, __src1, __src2 + %endif + %else + __instr %6, %7, %8 + %endif %elif %0 == 7 - __instr %6, %7 + %if avx_enabled && __sizeofreg >= 16 && %5 + %xdefine __src1 %6 + %xdefine __src2 %7 + %ifnum regnumof%6 + %ifnum regnumof%7 + %if regnumof%6 < 8 && regnumof%7 >= 8 && regnumof%7 < 16 && sizeof%7 <= 32 + %xdefine __src1 %7 + %xdefine __src2 %6 + %endif + %endif + %endif + __instr %6, __src1, __src2 + %else + __instr %6, %7 + %endif %else __instr %6 %endif @@ -1318,8 +1546,8 @@ AVX_INSTR andpd, sse2, 1, 0, 1 AVX_INSTR andps, sse, 1, 0, 1 AVX_INSTR blendpd, sse4, 1, 1, 0 AVX_INSTR blendps, sse4, 1, 1, 0 -AVX_INSTR blendvpd, sse4 ; can't be emulated -AVX_INSTR blendvps, sse4 ; can't be emulated +AVX_INSTR blendvpd, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding +AVX_INSTR blendvps, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding AVX_INSTR cmpeqpd, sse2, 1, 0, 1 AVX_INSTR cmpeqps, sse, 1, 0, 1 AVX_INSTR cmpeqsd, sse2, 1, 0, 0 @@ -1356,38 +1584,41 @@ AVX_INSTR cmpunordpd, sse2, 1, 0, 1 AVX_INSTR cmpunordps, sse, 1, 0, 1 AVX_INSTR cmpunordsd, sse2, 1, 0, 0 AVX_INSTR cmpunordss, sse, 1, 0, 0 -AVX_INSTR comisd, sse2 -AVX_INSTR comiss, sse -AVX_INSTR cvtdq2pd, sse2 -AVX_INSTR cvtdq2ps, sse2 -AVX_INSTR cvtpd2dq, sse2 -AVX_INSTR cvtpd2ps, sse2 -AVX_INSTR cvtps2dq, sse2 -AVX_INSTR cvtps2pd, sse2 -AVX_INSTR cvtsd2si, sse2 +AVX_INSTR comisd, sse2, 1 +AVX_INSTR comiss, sse, 1 +AVX_INSTR cvtdq2pd, sse2, 1 +AVX_INSTR cvtdq2ps, sse2, 1 +AVX_INSTR cvtpd2dq, sse2, 1 +AVX_INSTR cvtpd2ps, sse2, 1 +AVX_INSTR cvtps2dq, sse2, 1 +AVX_INSTR cvtps2pd, sse2, 1 +AVX_INSTR cvtsd2si, sse2, 1 AVX_INSTR cvtsd2ss, sse2, 1, 0, 0 AVX_INSTR cvtsi2sd, sse2, 1, 0, 0 AVX_INSTR cvtsi2ss, sse, 1, 0, 0 AVX_INSTR cvtss2sd, sse2, 1, 0, 0 -AVX_INSTR cvtss2si, sse -AVX_INSTR cvttpd2dq, sse2 -AVX_INSTR cvttps2dq, sse2 -AVX_INSTR cvttsd2si, sse2 -AVX_INSTR cvttss2si, sse +AVX_INSTR cvtss2si, sse, 1 +AVX_INSTR cvttpd2dq, sse2, 1 +AVX_INSTR cvttps2dq, sse2, 1 +AVX_INSTR cvttsd2si, sse2, 1 +AVX_INSTR cvttss2si, sse, 1 AVX_INSTR divpd, sse2, 1, 0, 0 AVX_INSTR divps, sse, 1, 0, 0 AVX_INSTR divsd, sse2, 1, 0, 0 AVX_INSTR divss, sse, 1, 0, 0 AVX_INSTR dppd, sse4, 1, 1, 0 AVX_INSTR dpps, sse4, 1, 1, 0 -AVX_INSTR extractps, sse4 +AVX_INSTR extractps, sse4, 1 +AVX_INSTR gf2p8affineinvqb, gfni, 0, 1, 0 +AVX_INSTR gf2p8affineqb, gfni, 0, 1, 0 +AVX_INSTR gf2p8mulb, gfni, 0, 0, 0 AVX_INSTR haddpd, sse3, 1, 0, 0 AVX_INSTR haddps, sse3, 1, 0, 0 AVX_INSTR hsubpd, sse3, 1, 0, 0 AVX_INSTR hsubps, sse3, 1, 0, 0 AVX_INSTR insertps, sse4, 1, 1, 0 AVX_INSTR lddqu, sse3 -AVX_INSTR ldmxcsr, sse +AVX_INSTR ldmxcsr, sse, 1 AVX_INSTR maskmovdqu, sse2 AVX_INSTR maxpd, sse2, 1, 0, 1 AVX_INSTR maxps, sse, 1, 0, 1 @@ -1397,10 +1628,10 @@ AVX_INSTR minpd, sse2, 1, 0, 1 AVX_INSTR minps, sse, 1, 0, 1 AVX_INSTR minsd, sse2, 1, 0, 0 AVX_INSTR minss, sse, 1, 0, 0 -AVX_INSTR movapd, sse2 -AVX_INSTR movaps, sse +AVX_INSTR movapd, sse2, 1 +AVX_INSTR movaps, sse, 1 AVX_INSTR movd, mmx -AVX_INSTR movddup, sse3 +AVX_INSTR movddup, sse3, 1 AVX_INSTR movdqa, sse2 AVX_INSTR movdqu, sse2 AVX_INSTR movhlps, sse, 1, 0, 0 @@ -1409,19 +1640,19 @@ AVX_INSTR movhps, sse, 1, 0, 0 AVX_INSTR movlhps, sse, 1, 0, 0 AVX_INSTR movlpd, sse2, 1, 0, 0 AVX_INSTR movlps, sse, 1, 0, 0 -AVX_INSTR movmskpd, sse2 -AVX_INSTR movmskps, sse +AVX_INSTR movmskpd, sse2, 1 +AVX_INSTR movmskps, sse, 1 AVX_INSTR movntdq, sse2 AVX_INSTR movntdqa, sse4 -AVX_INSTR movntpd, sse2 -AVX_INSTR movntps, sse +AVX_INSTR movntpd, sse2, 1 +AVX_INSTR movntps, sse, 1 AVX_INSTR movq, mmx AVX_INSTR movsd, sse2, 1, 0, 0 -AVX_INSTR movshdup, sse3 -AVX_INSTR movsldup, sse3 +AVX_INSTR movshdup, sse3, 1 +AVX_INSTR movsldup, sse3, 1 AVX_INSTR movss, sse, 1, 0, 0 -AVX_INSTR movupd, sse2 -AVX_INSTR movups, sse +AVX_INSTR movupd, sse2, 1 +AVX_INSTR movups, sse, 1 AVX_INSTR mpsadbw, sse4, 0, 1, 0 AVX_INSTR mulpd, sse2, 1, 0, 1 AVX_INSTR mulps, sse, 1, 0, 1 @@ -1432,90 +1663,90 @@ AVX_INSTR orps, sse, 1, 0, 1 AVX_INSTR pabsb, ssse3 AVX_INSTR pabsd, ssse3 AVX_INSTR pabsw, ssse3 -AVX_INSTR packsswb, mmx, 0, 0, 0 AVX_INSTR packssdw, mmx, 0, 0, 0 -AVX_INSTR packuswb, mmx, 0, 0, 0 +AVX_INSTR packsswb, mmx, 0, 0, 0 AVX_INSTR packusdw, sse4, 0, 0, 0 +AVX_INSTR packuswb, mmx, 0, 0, 0 AVX_INSTR paddb, mmx, 0, 0, 1 -AVX_INSTR paddw, mmx, 0, 0, 1 AVX_INSTR paddd, mmx, 0, 0, 1 AVX_INSTR paddq, sse2, 0, 0, 1 AVX_INSTR paddsb, mmx, 0, 0, 1 AVX_INSTR paddsw, mmx, 0, 0, 1 AVX_INSTR paddusb, mmx, 0, 0, 1 AVX_INSTR paddusw, mmx, 0, 0, 1 +AVX_INSTR paddw, mmx, 0, 0, 1 AVX_INSTR palignr, ssse3, 0, 1, 0 AVX_INSTR pand, mmx, 0, 0, 1 AVX_INSTR pandn, mmx, 0, 0, 0 AVX_INSTR pavgb, mmx2, 0, 0, 1 AVX_INSTR pavgw, mmx2, 0, 0, 1 -AVX_INSTR pblendvb, sse4 ; can't be emulated +AVX_INSTR pblendvb, sse4, 0, 1, 0 ; last operand must be xmm0 with legacy encoding AVX_INSTR pblendw, sse4, 0, 1, 0 -AVX_INSTR pclmulqdq, fnord, 0, 1, 0 -AVX_INSTR pclmulhqhqdq, fnord, 0, 0, 0 -AVX_INSTR pclmulhqlqdq, fnord, 0, 0, 0 -AVX_INSTR pclmullqhqdq, fnord, 0, 0, 0 -AVX_INSTR pclmullqlqdq, fnord, 0, 0, 0 -AVX_INSTR pcmpestri, sse42 -AVX_INSTR pcmpestrm, sse42 -AVX_INSTR pcmpistri, sse42 -AVX_INSTR pcmpistrm, sse42 +AVX_INSTR pclmulhqhqdq, clmul, 0, 0, 0 +AVX_INSTR pclmulhqlqdq, clmul, 0, 0, 0 +AVX_INSTR pclmullqhqdq, clmul, 0, 0, 0 +AVX_INSTR pclmullqlqdq, clmul, 0, 0, 0 +AVX_INSTR pclmulqdq, clmul, 0, 1, 0 AVX_INSTR pcmpeqb, mmx, 0, 0, 1 -AVX_INSTR pcmpeqw, mmx, 0, 0, 1 AVX_INSTR pcmpeqd, mmx, 0, 0, 1 AVX_INSTR pcmpeqq, sse4, 0, 0, 1 +AVX_INSTR pcmpeqw, mmx, 0, 0, 1 +AVX_INSTR pcmpestri, sse42 +AVX_INSTR pcmpestrm, sse42 AVX_INSTR pcmpgtb, mmx, 0, 0, 0 -AVX_INSTR pcmpgtw, mmx, 0, 0, 0 AVX_INSTR pcmpgtd, mmx, 0, 0, 0 AVX_INSTR pcmpgtq, sse42, 0, 0, 0 +AVX_INSTR pcmpgtw, mmx, 0, 0, 0 +AVX_INSTR pcmpistri, sse42 +AVX_INSTR pcmpistrm, sse42 AVX_INSTR pextrb, sse4 AVX_INSTR pextrd, sse4 AVX_INSTR pextrq, sse4 AVX_INSTR pextrw, mmx2 -AVX_INSTR phaddw, ssse3, 0, 0, 0 AVX_INSTR phaddd, ssse3, 0, 0, 0 AVX_INSTR phaddsw, ssse3, 0, 0, 0 +AVX_INSTR phaddw, ssse3, 0, 0, 0 AVX_INSTR phminposuw, sse4 -AVX_INSTR phsubw, ssse3, 0, 0, 0 AVX_INSTR phsubd, ssse3, 0, 0, 0 AVX_INSTR phsubsw, ssse3, 0, 0, 0 +AVX_INSTR phsubw, ssse3, 0, 0, 0 AVX_INSTR pinsrb, sse4, 0, 1, 0 AVX_INSTR pinsrd, sse4, 0, 1, 0 AVX_INSTR pinsrq, sse4, 0, 1, 0 AVX_INSTR pinsrw, mmx2, 0, 1, 0 -AVX_INSTR pmaddwd, mmx, 0, 0, 1 AVX_INSTR pmaddubsw, ssse3, 0, 0, 0 +AVX_INSTR pmaddwd, mmx, 0, 0, 1 AVX_INSTR pmaxsb, sse4, 0, 0, 1 -AVX_INSTR pmaxsw, mmx2, 0, 0, 1 AVX_INSTR pmaxsd, sse4, 0, 0, 1 +AVX_INSTR pmaxsw, mmx2, 0, 0, 1 AVX_INSTR pmaxub, mmx2, 0, 0, 1 -AVX_INSTR pmaxuw, sse4, 0, 0, 1 AVX_INSTR pmaxud, sse4, 0, 0, 1 +AVX_INSTR pmaxuw, sse4, 0, 0, 1 AVX_INSTR pminsb, sse4, 0, 0, 1 -AVX_INSTR pminsw, mmx2, 0, 0, 1 AVX_INSTR pminsd, sse4, 0, 0, 1 +AVX_INSTR pminsw, mmx2, 0, 0, 1 AVX_INSTR pminub, mmx2, 0, 0, 1 -AVX_INSTR pminuw, sse4, 0, 0, 1 AVX_INSTR pminud, sse4, 0, 0, 1 +AVX_INSTR pminuw, sse4, 0, 0, 1 AVX_INSTR pmovmskb, mmx2 -AVX_INSTR pmovsxbw, sse4 AVX_INSTR pmovsxbd, sse4 AVX_INSTR pmovsxbq, sse4 +AVX_INSTR pmovsxbw, sse4 +AVX_INSTR pmovsxdq, sse4 AVX_INSTR pmovsxwd, sse4 AVX_INSTR pmovsxwq, sse4 -AVX_INSTR pmovsxdq, sse4 -AVX_INSTR pmovzxbw, sse4 AVX_INSTR pmovzxbd, sse4 AVX_INSTR pmovzxbq, sse4 +AVX_INSTR pmovzxbw, sse4 +AVX_INSTR pmovzxdq, sse4 AVX_INSTR pmovzxwd, sse4 AVX_INSTR pmovzxwq, sse4 -AVX_INSTR pmovzxdq, sse4 AVX_INSTR pmuldq, sse4, 0, 0, 1 AVX_INSTR pmulhrsw, ssse3, 0, 0, 1 AVX_INSTR pmulhuw, mmx2, 0, 0, 1 AVX_INSTR pmulhw, mmx, 0, 0, 1 -AVX_INSTR pmullw, mmx, 0, 0, 1 AVX_INSTR pmulld, sse4, 0, 0, 1 +AVX_INSTR pmullw, mmx, 0, 0, 1 AVX_INSTR pmuludq, sse2, 0, 0, 1 AVX_INSTR por, mmx, 0, 0, 1 AVX_INSTR psadbw, mmx2, 0, 0, 1 @@ -1524,57 +1755,57 @@ AVX_INSTR pshufd, sse2 AVX_INSTR pshufhw, sse2 AVX_INSTR pshuflw, sse2 AVX_INSTR psignb, ssse3, 0, 0, 0 -AVX_INSTR psignw, ssse3, 0, 0, 0 AVX_INSTR psignd, ssse3, 0, 0, 0 -AVX_INSTR psllw, mmx, 0, 0, 0 +AVX_INSTR psignw, ssse3, 0, 0, 0 AVX_INSTR pslld, mmx, 0, 0, 0 -AVX_INSTR psllq, mmx, 0, 0, 0 AVX_INSTR pslldq, sse2, 0, 0, 0 -AVX_INSTR psraw, mmx, 0, 0, 0 +AVX_INSTR psllq, mmx, 0, 0, 0 +AVX_INSTR psllw, mmx, 0, 0, 0 AVX_INSTR psrad, mmx, 0, 0, 0 -AVX_INSTR psrlw, mmx, 0, 0, 0 +AVX_INSTR psraw, mmx, 0, 0, 0 AVX_INSTR psrld, mmx, 0, 0, 0 -AVX_INSTR psrlq, mmx, 0, 0, 0 AVX_INSTR psrldq, sse2, 0, 0, 0 +AVX_INSTR psrlq, mmx, 0, 0, 0 +AVX_INSTR psrlw, mmx, 0, 0, 0 AVX_INSTR psubb, mmx, 0, 0, 0 -AVX_INSTR psubw, mmx, 0, 0, 0 AVX_INSTR psubd, mmx, 0, 0, 0 AVX_INSTR psubq, sse2, 0, 0, 0 AVX_INSTR psubsb, mmx, 0, 0, 0 AVX_INSTR psubsw, mmx, 0, 0, 0 AVX_INSTR psubusb, mmx, 0, 0, 0 AVX_INSTR psubusw, mmx, 0, 0, 0 +AVX_INSTR psubw, mmx, 0, 0, 0 AVX_INSTR ptest, sse4 AVX_INSTR punpckhbw, mmx, 0, 0, 0 -AVX_INSTR punpckhwd, mmx, 0, 0, 0 AVX_INSTR punpckhdq, mmx, 0, 0, 0 AVX_INSTR punpckhqdq, sse2, 0, 0, 0 +AVX_INSTR punpckhwd, mmx, 0, 0, 0 AVX_INSTR punpcklbw, mmx, 0, 0, 0 -AVX_INSTR punpcklwd, mmx, 0, 0, 0 AVX_INSTR punpckldq, mmx, 0, 0, 0 AVX_INSTR punpcklqdq, sse2, 0, 0, 0 +AVX_INSTR punpcklwd, mmx, 0, 0, 0 AVX_INSTR pxor, mmx, 0, 0, 1 -AVX_INSTR rcpps, sse +AVX_INSTR rcpps, sse, 1 AVX_INSTR rcpss, sse, 1, 0, 0 -AVX_INSTR roundpd, sse4 -AVX_INSTR roundps, sse4 +AVX_INSTR roundpd, sse4, 1 +AVX_INSTR roundps, sse4, 1 AVX_INSTR roundsd, sse4, 1, 1, 0 AVX_INSTR roundss, sse4, 1, 1, 0 -AVX_INSTR rsqrtps, sse +AVX_INSTR rsqrtps, sse, 1 AVX_INSTR rsqrtss, sse, 1, 0, 0 AVX_INSTR shufpd, sse2, 1, 1, 0 AVX_INSTR shufps, sse, 1, 1, 0 -AVX_INSTR sqrtpd, sse2 -AVX_INSTR sqrtps, sse +AVX_INSTR sqrtpd, sse2, 1 +AVX_INSTR sqrtps, sse, 1 AVX_INSTR sqrtsd, sse2, 1, 0, 0 AVX_INSTR sqrtss, sse, 1, 0, 0 -AVX_INSTR stmxcsr, sse +AVX_INSTR stmxcsr, sse, 1 AVX_INSTR subpd, sse2, 1, 0, 0 AVX_INSTR subps, sse, 1, 0, 0 AVX_INSTR subsd, sse2, 1, 0, 0 AVX_INSTR subss, sse, 1, 0, 0 -AVX_INSTR ucomisd, sse2 -AVX_INSTR ucomiss, sse +AVX_INSTR ucomisd, sse2, 1 +AVX_INSTR ucomiss, sse, 1 AVX_INSTR unpckhpd, sse2, 1, 0, 0 AVX_INSTR unpckhps, sse, 1, 0, 0 AVX_INSTR unpcklpd, sse2, 1, 0, 0 @@ -1584,8 +1815,41 @@ AVX_INSTR xorps, sse, 1, 0, 1 ; 3DNow instructions, for sharing code between AVX, SSE and 3DN AVX_INSTR pfadd, 3dnow, 1, 0, 1 -AVX_INSTR pfsub, 3dnow, 1, 0, 0 AVX_INSTR pfmul, 3dnow, 1, 0, 1 +AVX_INSTR pfsub, 3dnow, 1, 0, 0 + +;%1 == instruction +;%2 == minimal instruction set +%macro GPR_INSTR 2 + %macro %1 2-5 fnord, %1, %2 + %ifdef cpuname + %if notcpuflag(%5) + %error use of ``%4'' %5 instruction in cpuname function: current_function + %endif + %endif + %ifidn %3, fnord + %4 %1, %2 + %else + %4 %1, %2, %3 + %endif + %endmacro +%endmacro + +GPR_INSTR andn, bmi1 +GPR_INSTR bextr, bmi1 +GPR_INSTR blsi, bmi1 +GPR_INSTR blsmsk, bmi1 +GPR_INSTR blsr, bmi1 +GPR_INSTR bzhi, bmi2 +GPR_INSTR crc32, sse42 +GPR_INSTR mulx, bmi2 +GPR_INSTR pdep, bmi2 +GPR_INSTR pext, bmi2 +GPR_INSTR popcnt, sse42 +GPR_INSTR rorx, bmi2 +GPR_INSTR sarx, bmi2 +GPR_INSTR shlx, bmi2 +GPR_INSTR shrx, bmi2 ; base-4 constants for shuffles %assign i 0 @@ -1618,15 +1882,11 @@ AVX_INSTR pfmul, 3dnow, 1, 0, 1 %endmacro %endmacro -FMA_INSTR pmacsww, pmullw, paddw -FMA_INSTR pmacsdd, pmulld, paddd ; sse4 emulation -FMA_INSTR pmacsdql, pmuldq, paddq ; sse4 emulation +FMA_INSTR pmacsdd, pmulld, paddd ; sse4 emulation +FMA_INSTR pmacsdql, pmuldq, paddq ; sse4 emulation +FMA_INSTR pmacsww, pmullw, paddw FMA_INSTR pmadcswd, pmaddwd, paddd -; tzcnt is equivalent to "rep bsf" and is backwards-compatible with bsf. -; This lets us use tzcnt without bumping the yasm version requirement yet. -%define tzcnt rep bsf - ; Macros for consolidating FMA3 and FMA4 using 4-operand (dst, src1, src2, src3) syntax. ; FMA3 is only possible if dst is the same as one of the src registers. ; Either src2 or src3 can be a memory operand. @@ -1687,6 +1947,11 @@ FMA4_INSTR fnmsub, pd, ps, sd, ss %assign %%evex_required 1 %endif %endif + %ifnum regnumof%3 + %if regnumof%3 >= 16 || sizeof%3 > 32 + %assign %%evex_required 1 + %endif + %endif %if %%evex_required %6 %%args %else @@ -1711,16 +1976,3 @@ EVEX_INSTR vrcpps, vrcp14ps, 1 ; EVEX versions have higher precision EVEX_INSTR vrcpss, vrcp14ss, 1 EVEX_INSTR vrsqrtps, vrsqrt14ps, 1 EVEX_INSTR vrsqrtss, vrsqrt14ss, 1 - -; workaround: vpbroadcastq is broken in x86_32 due to a yasm bug (fixed in 1.3.0) -%ifdef __YASM_VER__ - %if __YASM_VERSION_ID__ < 0x01030000 && ARCH_X86_64 == 0 - %macro vpbroadcastq 2 - %if sizeof%1 == 16 - movddup %1, %2 - %else - vbroadcastsd %1, %2 - %endif - %endmacro - %endif -%endif diff --git a/media/ffvpx/libavutil/x86/x86util.asm b/media/ffvpx/libavutil/x86/x86util.asm index d7cd996842..836f6afcb8 100644 --- a/media/ffvpx/libavutil/x86/x86util.asm +++ b/media/ffvpx/libavutil/x86/x86util.asm @@ -802,10 +802,6 @@ %macro PMINSD 3 ; dst, src, tmp/unused %if cpuflag(sse4) pminsd %1, %2 -%elif cpuflag(sse2) - cvtdq2ps %1, %1 - minps %1, %2 - cvtps2dq %1, %1 %else mova %3, %2 pcmpgtd %3, %1 diff --git a/media/ffvpx/libavutil_visibility.h b/media/ffvpx/libavutil_visibility.h index a5cce0844a..1ed8d267ad 100644 --- a/media/ffvpx/libavutil_visibility.h +++ b/media/ffvpx/libavutil_visibility.h @@ -10,10 +10,10 @@ #define MOZILLA_AVUTIL_VISIBILITY_H #pragma GCC visibility push(default) -#include "libavutil/cpu.h" // We need av_log() to be visible so we can enable assertions in libavcodec. #include "libavutil/log.h" +#include "libavcodec/packet.h" #pragma GCC visibility pop |