commit e0de88fc96a55e4bb53c80b7970205d738aeef7a
parent dba4fc7e5995f501da0ff329806fc9a8031ee4f9
Author: Updatebot <updatebot@mozilla.com>
Date: Mon, 15 Dec 2025 20:47:07 +0000
Bug 2004760 - Update libvpx to 98a119c2c67d41f6354281f2cb719c8229c30601 r=chunmin
Differential Revision: https://phabricator.services.mozilla.com/D275496
Diffstat:
6 files changed, 263 insertions(+), 116 deletions(-)
diff --git a/media/libvpx/libvpx/examples/vpx_enc_fuzzer.cc b/media/libvpx/libvpx/examples/vpx_enc_fuzzer.cc
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2025 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * Fuzzer for libvpx encoders
+ * ==========================
+ * Requirements
+ * --------------
+ * Requires Clang 6.0 or above as -fsanitize=fuzzer is used as a linker
+ * option.
+
+ * Steps to build
+ * --------------
+ * Clone libvpx repository
+ $git clone https://chromium.googlesource.com/webm/libvpx
+
+ * Create a directory in parallel to libvpx and change directory
+ $mkdir vpx_enc_fuzzer
+ $cd vpx_enc_fuzzer/
+
+ * Enable sanitizers (Supported: address integer memory thread undefined)
+ $source ../libvpx/tools/set_analyzer_env.sh address
+
+ * Configure libvpx.
+ * Note --size-limit and VPX_MAX_ALLOCABLE_MEMORY are defined to avoid
+ * Out of memory errors when running generated fuzzer binary
+ $../libvpx/configure --disable-unit-tests --size-limit=12288x12288 \
+ --extra-cflags="-fsanitize=fuzzer-no-link \
+ -DVPX_MAX_ALLOCABLE_MEMORY=1073741824" \
+ --disable-webm-io --enable-debug --enable-vp8-encoder \
+ --enable-vp9-encoder --disable-examples
+
+ * Build libvpx
+ $make -j32
+
+ * Build vp9 fuzzer
+ $ $CXX $CXXFLAGS -std=gnu++17 -DENCODER=vp9 \
+ -fsanitize=fuzzer -I../libvpx -I. -Wl,--start-group \
+ ../libvpx/examples/vpx_enc_fuzzer.cc -o ./vpx_enc_fuzzer_vp9 \
+ ./libvpx.a -Wl,--end-group
+
+ * ENCODER should be defined as vp9 or vp8 to enable vp9/vp8
+ *
+ * create a corpus directory and copy some ivf files there.
+ * Based on which codec (vp8/vp9) is being tested, it is recommended to
+ * have corresponding ivf files in corpus directory
+ * Empty corpus directory also is acceptable, though not recommended
+ $mkdir CORPUS && cp some-files CORPUS
+
+ * Run fuzzing:
+ $./vpx_enc_fuzzer_vp9 CORPUS
+
+ * References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+#include "vpx_ports/mem_ops.h"
+#include "third_party/nalloc/nalloc.h"
+
+// fuzz header to have config options, before raw image data
+#define FUZZ_HDR_SZ 32
+
+#define VPXC_INTERFACE(name) VPXC_INTERFACE_(name)
+#define VPXC_INTERFACE_(name) vpx_codec_##name##_cx()
+
+extern "C" void usage_exit(void) { exit(EXIT_FAILURE); }
+
+static int vpx_img_plane_width(const vpx_image_t *img, int plane) {
+ if (plane > 0 && img->x_chroma_shift > 0)
+ return (img->d_w + 1) >> img->x_chroma_shift;
+ else
+ return img->d_w;
+}
+
+static int vpx_img_plane_height(const vpx_image_t *img, int plane) {
+ if (plane > 0 && img->y_chroma_shift > 0)
+ return (img->d_h + 1) >> img->y_chroma_shift;
+ else
+ return img->d_h;
+}
+
+static int fuzz_vpx_img_read(vpx_image_t *img, const uint8_t *data,
+ size_t size) {
+ int plane;
+ // TODO: wtc - Need to clamp the sample values so that they are in range
+ // For example, if the bit depth is 10, the sample values must be <= 1023.
+ assert(img->bit_depth == 8);
+ const size_t bytespp = (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
+
+ if (size == 0) return 0;
+ size_t used = 0;
+ for (plane = 0; plane < 3; ++plane) {
+ unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ int w = vpx_img_plane_width(img, plane);
+ const int h = vpx_img_plane_height(img, plane);
+ int y;
+
+ // Assuming that for nv12 we read all chroma data at once
+ if (img->fmt == VPX_IMG_FMT_NV12 && plane > 1) break;
+ // Fixing NV12 chroma width if it is odd
+ if (img->fmt == VPX_IMG_FMT_NV12 && plane == 1) w = (w + 1) & ~1;
+
+ for (y = 0; y < h; ++y) {
+ size_t nb = bytespp * w;
+ if (nb > size - used) {
+ nb = size - used;
+ }
+ memcpy(buf, data, nb);
+ memset(buf + nb, 0, bytespp * w - nb);
+ buf += stride;
+ data += nb;
+ used += nb;
+ }
+ }
+
+ return used;
+}
+
+static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
+ int frame_index, int flags, FILE *out,
+ vpx_enc_deadline_t quality) {
+ int got_pkts = 0;
+ vpx_codec_iter_t iter = NULL;
+ const vpx_codec_cx_pkt_t *pkt = NULL;
+ const vpx_codec_err_t res =
+ vpx_codec_encode(codec, img, frame_index, 1, flags, quality);
+ if (res != VPX_CODEC_OK) return 0;
+
+ while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
+ got_pkts = 1;
+
+ if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+ if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, out) !=
+ pkt->data.frame.sz)
+ return 0;
+ }
+ }
+
+ return got_pkts;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size <= FUZZ_HDR_SZ) {
+ return 0;
+ }
+ nalloc_init(nullptr);
+
+ int keyframe_interval = 0;
+ int frame_count = 0;
+ vpx_codec_ctx_t codec;
+ vpx_image_t raw;
+ vpx_codec_enc_cfg_t cfg;
+ vpx_enc_deadline_t quality = VPX_DL_GOOD_QUALITY;
+
+ if ((data[0] & 0x80) != 0) {
+ keyframe_interval = 8;
+ }
+ if ((data[0] & 0x40) != 0) {
+ quality = VPX_DL_REALTIME;
+ } else if ((data[0] & 0x20) != 0) {
+ quality = VPX_DL_BEST_QUALITY;
+ }
+
+ if (vpx_codec_enc_config_default(VPXC_INTERFACE(ENCODER), &cfg, 0)) abort();
+ FILE *out = fopen("/dev/null", "wb");
+
+ switch (data[0] & 0x1F) {
+ case 0: cfg.g_w = 64; cfg.g_h = 1;
+ case 1: cfg.g_w = 1; cfg.g_h = 48;
+ case 2: cfg.g_w = 1; cfg.g_h = 1;
+ case 3: cfg.g_w = 4; cfg.g_h = 4;
+ case 4: cfg.g_w = 16; cfg.g_h = 16;
+ default: cfg.g_w = 64; cfg.g_h = 48;
+ }
+ cfg.g_timebase.num = 1;
+ cfg.g_timebase.den = 30; // fps
+ cfg.rc_target_bitrate = 200;
+ cfg.g_error_resilient = 1;
+
+ if (vpx_codec_enc_init(&codec, VPXC_INTERFACE(ENCODER), &cfg, 0)) {
+ return 0;
+ }
+
+ if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, cfg.g_w, cfg.g_h, 1)) {
+ goto fail;
+ }
+
+ nalloc_start(data, size);
+ // We may want to add more config options (for more complex encoders as seen
+ // in the examples) in the future while still maintaining the same format (so
+ // that generated corpus is still valid). So we reserve FUZZ_HDR_SZ=32 bytes
+ // for this even if we just use one byte so far.
+ data += FUZZ_HDR_SZ;
+ size -= FUZZ_HDR_SZ;
+
+ // Encode frames.
+ while (1) {
+ int flags = 0;
+ size_t size_read = fuzz_vpx_img_read(&raw, data, size);
+ if (size_read == 0) break;
+ data += size_read;
+ size -= size_read;
+ if (keyframe_interval > 0 && frame_count % keyframe_interval == 0)
+ flags |= VPX_EFLAG_FORCE_KF;
+ encode_frame(&codec, &raw, frame_count++, flags, out, quality);
+ }
+
+ // Flush encoder.
+ while (encode_frame(&codec, NULL, -1, 0, out, quality)) {
+ }
+
+fail:
+ nalloc_end();
+ vpx_img_free(&raw);
+ vpx_codec_destroy(&codec);
+ fclose(out);
+ return 0;
+}
diff --git a/media/libvpx/libvpx/vp8/vp8_cx_iface.c b/media/libvpx/libvpx/vp8/vp8_cx_iface.c
@@ -1022,19 +1022,10 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
res = image2yuvconfig(img, &sd);
- if (sd.y_width != ctx->cfg.g_w || sd.y_height != ctx->cfg.g_h) {
- /* from vpx_encoder.h for g_w/g_h:
- "Note that the frames passed as input to the encoder must have this
- resolution"
- */
- ctx->base.err_detail = "Invalid input frame resolution";
- res = VPX_CODEC_INVALID_PARAM;
- } else {
- if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags,
- &sd, dst_time_stamp, dst_end_time_stamp)) {
- VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
- res = update_error_state(ctx, &cpi->common.error);
- }
+ if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, &sd,
+ dst_time_stamp, dst_end_time_stamp)) {
+ VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
+ res = update_error_state(ctx, &cpi->common.error);
}
/* reset for next frame */
diff --git a/media/libvpx/libvpx/vp9/vp9_cx_iface.c b/media/libvpx/libvpx/vp9/vp9_cx_iface.c
@@ -1478,22 +1478,13 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
timebase_units_to_ticks(timebase_in_ts, pts_end);
res = image2yuvconfig(img, &sd);
- if (sd.y_width != ctx->cfg.g_w || sd.y_height != ctx->cfg.g_h) {
- /* from vpx_encoder.h for g_w/g_h:
- "Note that the frames passed as input to the encoder must have this
- resolution"
- */
- ctx->base.err_detail = "Invalid input frame resolution";
- res = VPX_CODEC_INVALID_PARAM;
- } else {
- // Store the original flags in to the frame buffer. Will extract the
- // key frame flag when we actually encode this frame.
- if (vp9_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd,
+ // Store the original flags in to the frame buffer. Will extract the
+ // key frame flag when we actually encode this frame.
+ if (vp9_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd,
dst_time_stamp, dst_end_time_stamp)) {
- res = update_error_state(ctx, &cpi->common.error);
- }
- ctx->next_frame_flags = 0;
+ res = update_error_state(ctx, &cpi->common.error);
}
+ ctx->next_frame_flags = 0;
}
cx_data = ctx->cx_data;
diff --git a/media/libvpx/libvpx/vpx_dsp/arm/highbd_vpx_convolve8_sve2.c b/media/libvpx/libvpx/vpx_dsp/arm/highbd_vpx_convolve8_sve2.c
@@ -80,23 +80,12 @@ static INLINE void highbd_convolve8_8tap_vert_sve2(
const uint16_t *src, ptrdiff_t src_stride, uint16_t *dst,
ptrdiff_t dst_stride, int w, int h, const int16x8_t filter, int bd) {
assert(w >= 4 && h >= 4);
- uint16x8x3_t merge_tbl_idx = vld1q_u16_x3(kDotProdMergeBlockTbl);
- // Correct indices by the size of vector length.
- merge_tbl_idx.val[0] = vaddq_u16(
- merge_tbl_idx.val[0],
- vreinterpretq_u16_u64(vdupq_n_u64(svcnth() * 0x0001000000000000ULL)));
- merge_tbl_idx.val[1] = vaddq_u16(
- merge_tbl_idx.val[1],
- vreinterpretq_u16_u64(vdupq_n_u64(svcnth() * 0x0001000100000000ULL)));
- merge_tbl_idx.val[2] = vaddq_u16(
- merge_tbl_idx.val[2],
- vreinterpretq_u16_u64(vdupq_n_u64(svcnth() * 0x0001000100010000ULL)));
-
- if (w == 4) {
+ do {
const uint16x4_t max = vdup_n_u16((1 << bd) - 1);
const int16_t *s = (const int16_t *)src;
uint16_t *d = dst;
+ int height = h;
int16x4_t s0, s1, s2, s3, s4, s5, s6;
load_s16_4x7(s, src_stride, &s0, &s1, &s2, &s3, &s4, &s5, &s6);
@@ -114,12 +103,11 @@ static INLINE void highbd_convolve8_8tap_vert_sve2(
load_s16_4x4(s, src_stride, &s7, &s8, &s9, &sA);
int16x8_t s4567[2], s5678[2], s6789[2], s789A[2];
+ transpose_concat_s16_4x4(s4, s5, s6, s7, &s4567[0], &s4567[1]);
+ transpose_concat_s16_4x4(s5, s6, s7, s8, &s5678[0], &s5678[1]);
+ transpose_concat_s16_4x4(s6, s7, s8, s9, &s6789[0], &s6789[1]);
transpose_concat_s16_4x4(s7, s8, s9, sA, &s789A[0], &s789A[1]);
- vpx_tbl2x2_s16(s3456, s789A, s4567, merge_tbl_idx.val[0]);
- vpx_tbl2x2_s16(s3456, s789A, s5678, merge_tbl_idx.val[1]);
- vpx_tbl2x2_s16(s3456, s789A, s6789, merge_tbl_idx.val[2]);
-
uint16x4_t d0 = highbd_convolve8_4_v(s0123, s4567, filter, max);
uint16x4_t d1 = highbd_convolve8_4_v(s1234, s5678, filter, max);
uint16x4_t d2 = highbd_convolve8_4_v(s2345, s6789, filter, max);
@@ -136,77 +124,19 @@ static INLINE void highbd_convolve8_8tap_vert_sve2(
s3456[0] = s789A[0];
s3456[1] = s789A[1];
+ s4 = s8;
+ s5 = s9;
+ s6 = sA;
+
s += 4 * src_stride;
d += 4 * dst_stride;
- h -= 4;
- } while (h != 0);
- } else {
- const uint16x8_t max = vdupq_n_u16((1 << bd) - 1);
-
- do {
- const int16_t *s = (const int16_t *)src;
- uint16_t *d = dst;
- int height = h;
-
- int16x8_t s0, s1, s2, s3, s4, s5, s6;
- load_s16_8x7(s, src_stride, &s0, &s1, &s2, &s3, &s4, &s5, &s6);
- s += 7 * src_stride;
-
- int16x8_t s0123[4], s1234[4], s2345[4], s3456[4];
- transpose_concat_s16_8x4(s0, s1, s2, s3, &s0123[0], &s0123[1], &s0123[2],
- &s0123[3]);
- transpose_concat_s16_8x4(s1, s2, s3, s4, &s1234[0], &s1234[1], &s1234[2],
- &s1234[3]);
- transpose_concat_s16_8x4(s2, s3, s4, s5, &s2345[0], &s2345[1], &s2345[2],
- &s2345[3]);
- transpose_concat_s16_8x4(s3, s4, s5, s6, &s3456[0], &s3456[1], &s3456[2],
- &s3456[3]);
+ height -= 4;
+ } while (height != 0);
- do {
- int16x8_t s7, s8, s9, sA;
- load_s16_8x4(s, src_stride, &s7, &s8, &s9, &sA);
-
- int16x8_t s4567[4], s5678[5], s6789[4], s789A[4];
- transpose_concat_s16_8x4(s7, s8, s9, sA, &s789A[0], &s789A[1],
- &s789A[2], &s789A[3]);
-
- vpx_tbl2x4_s16(s3456, s789A, s4567, merge_tbl_idx.val[0]);
- vpx_tbl2x4_s16(s3456, s789A, s5678, merge_tbl_idx.val[1]);
- vpx_tbl2x4_s16(s3456, s789A, s6789, merge_tbl_idx.val[2]);
-
- uint16x8_t d0 = highbd_convolve8_8_v(s0123, s4567, filter, max);
- uint16x8_t d1 = highbd_convolve8_8_v(s1234, s5678, filter, max);
- uint16x8_t d2 = highbd_convolve8_8_v(s2345, s6789, filter, max);
- uint16x8_t d3 = highbd_convolve8_8_v(s3456, s789A, filter, max);
-
- store_u16_8x4(d, dst_stride, d0, d1, d2, d3);
-
- s0123[0] = s4567[0];
- s0123[1] = s4567[1];
- s0123[2] = s4567[2];
- s0123[3] = s4567[3];
- s1234[0] = s5678[0];
- s1234[1] = s5678[1];
- s1234[2] = s5678[2];
- s1234[3] = s5678[3];
- s2345[0] = s6789[0];
- s2345[1] = s6789[1];
- s2345[2] = s6789[2];
- s2345[3] = s6789[3];
- s3456[0] = s789A[0];
- s3456[1] = s789A[1];
- s3456[2] = s789A[2];
- s3456[3] = s789A[3];
-
- s += 4 * src_stride;
- d += 4 * dst_stride;
- height -= 4;
- } while (height != 0);
- src += 8;
- dst += 8;
- w -= 8;
- } while (w != 0);
- }
+ src += 4;
+ dst += 4;
+ w -= 4;
+ } while (w != 0);
}
void vpx_highbd_convolve8_vert_sve2(const uint16_t *src, ptrdiff_t src_stride,
diff --git a/media/libvpx/libvpx/vpx_ports/aarch64_cpudetect.c b/media/libvpx/libvpx/vpx_ports/aarch64_cpudetect.c
@@ -16,7 +16,7 @@
#include <sys/sysctl.h>
#endif
-#if !CONFIG_RUNTIME_CPU_DETECT || defined(__OpenBSD__)
+#if !CONFIG_RUNTIME_CPU_DETECT
static int arm_get_cpu_caps(void) {
// This function should actually be a no-op. There is no way to adjust any of
@@ -29,7 +29,7 @@ static int arm_get_cpu_caps(void) {
return flags;
}
-#elif defined(__APPLE__) // end !CONFIG_RUNTIME_CPU_DETECT || defined(__OpenBSD__)
+#elif defined(__APPLE__) // end !CONFIG_RUNTIME_CPU_DETECT
// sysctlbyname() parameter documentation for instruction set characteristics:
// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
diff --git a/media/libvpx/moz.yaml b/media/libvpx/moz.yaml
@@ -20,11 +20,11 @@ origin:
# Human-readable identifier for this version/release
# Generally "version NNN", "tag SSS", "bookmark SSS"
- release: 9a7674e1a83d1261a49776c8794b87c9bccc85d7 (Tue Nov 04 19:55:43 2025).
+ release: 98a119c2c67d41f6354281f2cb719c8229c30601 (Wed Dec 03 16:08:53 2025).
# Revision to pull in
# Must be a long or short commit SHA (long preferred)
- revision: 9a7674e1a83d1261a49776c8794b87c9bccc85d7
+ revision: 98a119c2c67d41f6354281f2cb719c8229c30601
# The package's license, where possible using the mnemonic from
# https://spdx.org/licenses/