encoder.Encode(false);
}
+// This is a test case from clusterfuzz: based on b/311394513.
+// Encode a few frames with multiple change config calls
+// with different frame sizes.
+TEST(EncodeAPI, Buganizer311394513) {
+ VP9Encoder encoder(-7);
+
+ // Set initial config.
+ encoder.Configure(0, 5, 9, VPX_VBR, VPX_DL_REALTIME);
+
+ // Encode first frame.
+ encoder.Encode(false);
+
+ // Change config.
+ encoder.Configure(5, 2, 1, VPX_VBR, VPX_DL_REALTIME);
+
+ // Encode 2nd frame with new config.
+ encoder.Encode(true);
+}
+
class EncodeApiGetTplStatsTest
: public ::libvpx_test::EncoderTest,
public ::testing::TestWithParam<const libvpx_test::CodecFactory *> {
#endif
#if CONFIG_VP9_HIGHBITDEPTH
-static void scale_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src,
- YV12_BUFFER_CONFIG *dst,
- int bd) {
+void vp9_scale_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src,
+ YV12_BUFFER_CONFIG *dst, int bd) {
#else
-static void scale_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src,
- YV12_BUFFER_CONFIG *dst) {
+void vp9_scale_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src,
+ YV12_BUFFER_CONFIG *dst) {
#endif // CONFIG_VP9_HIGHBITDEPTH
// TODO(dkovalev): replace YV12_BUFFER_CONFIG with vpx_image_t
int i;
const int src_h = src->y_crop_height;
const int dst_w = dst->y_crop_width;
const int dst_h = dst->y_crop_height;
+
+ // The issue b/311394513 reveals a corner case bug.
+ // For bd = 8, vpx_scaled_2d() requires both x_step_q4 and y_step_q4 are less
+ // than or equal to 64. For bd >= 10, vpx_highbd_convolve8() requires both
+ // x_step_q4 and y_step_q4 are less than or equal to 32. If this condition
+ // isn't met, it needs to call vp9_scale_and_extend_frame_nonnormative() that
+ // supports arbitrary scaling.
+ const int x_step_q4 = 16 * src_w / dst_w;
+ const int y_step_q4 = 16 * src_h / dst_h;
+ const int is_arbitrary_scaling =
+ (bd == 8 && (x_step_q4 > 64 || y_step_q4 > 64)) ||
+ (bd >= 10 && (x_step_q4 > 32 || y_step_q4 > 32));
+ if (is_arbitrary_scaling) {
+ vp9_scale_and_extend_frame_nonnormative(src, dst, bd);
+ return;
+ }
+
const uint8_t *const srcs[3] = { src->y_buffer, src->u_buffer,
src->v_buffer };
const int src_strides[3] = { src->y_stride, src->uv_stride, src->uv_stride };
scale_and_extend_frame(unscaled, scaled, (int)cm->bit_depth,
filter_type, phase_scaler);
else
- scale_and_extend_frame_nonnormative(unscaled, scaled, (int)cm->bit_depth);
+ vp9_scale_and_extend_frame_nonnormative(unscaled, scaled,
+ (int)cm->bit_depth);
#else
if (use_normative_scaler && unscaled->y_width <= (scaled->y_width << 1) &&
unscaled->y_height <= (scaled->y_height << 1))
vp9_scale_and_extend_frame(unscaled, scaled, filter_type, phase_scaler);
else
- scale_and_extend_frame_nonnormative(unscaled, scaled);
+ vp9_scale_and_extend_frame_nonnormative(unscaled, scaled);
#endif // CONFIG_VP9_HIGHBITDEPTH
return scaled;
} else {
void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv);
+#if CONFIG_VP9_HIGHBITDEPTH
+void vp9_scale_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src,
+ YV12_BUFFER_CONFIG *dst, int bd);
+#else
+void vp9_scale_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src,
+ YV12_BUFFER_CONFIG *dst);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
YV12_BUFFER_CONFIG *vp9_svc_twostage_scale(
VP9_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled,
YV12_BUFFER_CONFIG *scaled_temp, INTERP_FILTER filter_type,
#include "./vpx_dsp_rtcd.h"
#include "./vpx_scale_rtcd.h"
#include "vp9/common/vp9_blockd.h"
+#include "vp9/encoder/vp9_encoder.h"
#include "vpx_dsp/vpx_filter.h"
#include "vpx_scale/yv12config.h"
{
const int dst_w = dst->y_crop_width;
const int dst_h = dst->y_crop_height;
+
+ // The issue b/311394513 reveals a corner case bug. vpx_scaled_2d() requires
+ // both x_step_q4 and y_step_q4 are less than or equal to 64. Otherwise, it
+ // needs to call vp9_scale_and_extend_frame_nonnormative() that supports
+ // arbitrary scaling.
+ const int x_step_q4 = 16 * src_w / dst_w;
+ const int y_step_q4 = 16 * src_h / dst_h;
+ if (x_step_q4 > 64 || y_step_q4 > 64) {
+ // This funnction is only called while cm->bit_depth is VPX_BITS_8.
+#if CONFIG_VP9_HIGHBITDEPTH
+ vp9_scale_and_extend_frame_nonnormative(src, dst, (int)VPX_BITS_8);
+#else
+ vp9_scale_and_extend_frame_nonnormative(src, dst);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ return;
+ }
+
for (i = 0; i < MAX_MB_PLANE; ++i) {
const int factor = (i == 0 || i == 3 ? 1 : 2);
const int src_stride = src_strides[i];