diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/third_party/libvpx | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/libvpx')
32 files changed, 438 insertions, 137 deletions
diff --git a/chromium/third_party/libvpx/README.chromium b/chromium/third_party/libvpx/README.chromium index da2a7519f1f..770461309b8 100644 --- a/chromium/third_party/libvpx/README.chromium +++ b/chromium/third_party/libvpx/README.chromium @@ -6,9 +6,9 @@ License: BSD License File: source/libvpx/LICENSE Security Critical: yes -Date: Monday June 22 2020 -Branch: m84-4147 -Commit: b30184a6821e1d36db8294574022ff9c207acacc +Date: Thursday June 18 2020 +Branch: master +Commit: 769129fb29fc66720be2b01276a472c334757d2d Description: Contains the sources used to compile libvpx binaries used by Google Chrome and diff --git a/chromium/third_party/libvpx/source/config/vpx_version.h b/chromium/third_party/libvpx/source/config/vpx_version.h index 9bb16668ece..8c003eaf7da 100644 --- a/chromium/third_party/libvpx/source/config/vpx_version.h +++ b/chromium/third_party/libvpx/source/config/vpx_version.h @@ -2,8 +2,8 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 8 #define VERSION_PATCH 2 -#define VERSION_EXTRA "175-gb30184a68" +#define VERSION_EXTRA "202-g769129fb2" #define VERSION_PACKED \ ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.8.2-175-gb30184a68" -#define VERSION_STRING " v1.8.2-175-gb30184a68" +#define VERSION_STRING_NOSP "v1.8.2-202-g769129fb2" +#define VERSION_STRING " v1.8.2-202-g769129fb2" diff --git a/chromium/third_party/libvpx/source/libvpx/examples/decode_with_drops.c b/chromium/third_party/libvpx/source/libvpx/examples/decode_with_drops.c index e69e2a9f9b3..03c79a45616 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/decode_with_drops.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/decode_with_drops.c @@ -106,7 +106,7 @@ int main(int argc, char **argv) { printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface())); if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0)) - die_codec(&codec, "Failed to initialize decoder."); + die("Failed to initialize decoder."); while (vpx_video_reader_read_frame(reader)) { vpx_codec_iter_t iter = NULL; diff --git a/chromium/third_party/libvpx/source/libvpx/examples/postproc.c b/chromium/third_party/libvpx/source/libvpx/examples/postproc.c index 15713b946a9..be999b429e7 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/postproc.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/postproc.c @@ -86,9 +86,9 @@ int main(int argc, char **argv) { res = vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, VPX_CODEC_USE_POSTPROC); if (res == VPX_CODEC_INCAPABLE) - die_codec(&codec, "Postproc not supported by this decoder."); + die("Postproc not supported by this decoder."); - if (res) die_codec(&codec, "Failed to initialize decoder."); + if (res) die("Failed to initialize decoder."); while (vpx_video_reader_read_frame(reader)) { vpx_codec_iter_t iter = NULL; diff --git a/chromium/third_party/libvpx/source/libvpx/examples/set_maps.c b/chromium/third_party/libvpx/source/libvpx/examples/set_maps.c index c0c7d10e72a..867e473aea4 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/set_maps.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/set_maps.c @@ -209,7 +209,7 @@ int main(int argc, char **argv) { die("Failed to open %s for reading.", argv[4]); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) - die_codec(&codec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); // Encode frames. while (vpx_img_read(&raw, infile)) { diff --git a/chromium/third_party/libvpx/source/libvpx/examples/simple_decoder.c b/chromium/third_party/libvpx/source/libvpx/examples/simple_decoder.c index 2bb1a05245b..d089e826d5b 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/simple_decoder.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/simple_decoder.c @@ -118,7 +118,7 @@ int main(int argc, char **argv) { printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface())); if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0)) - die_codec(&codec, "Failed to initialize decoder."); + die("Failed to initialize decoder."); while (vpx_video_reader_read_frame(reader)) { vpx_codec_iter_t iter = NULL; diff --git a/chromium/third_party/libvpx/source/libvpx/examples/simple_encoder.c b/chromium/third_party/libvpx/source/libvpx/examples/simple_encoder.c index dde6344f8d6..dffdd6d7da3 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/simple_encoder.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/simple_encoder.c @@ -218,7 +218,7 @@ int main(int argc, char **argv) { die("Failed to open %s for reading.", infile_arg); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) - die_codec(&codec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); // Encode frames. while (vpx_img_read(&raw, infile)) { diff --git a/chromium/third_party/libvpx/source/libvpx/examples/twopass_encoder.c b/chromium/third_party/libvpx/source/libvpx/examples/twopass_encoder.c index 4e63a7a6c97..3d950b2c4b9 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/twopass_encoder.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/twopass_encoder.c @@ -128,7 +128,7 @@ static vpx_fixed_buf_t pass0(vpx_image_t *raw, FILE *infile, vpx_fixed_buf_t stats = { NULL, 0 }; if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0)) - die_codec(&codec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); // Calculate frame statistics. while (vpx_img_read(raw, infile)) { @@ -164,7 +164,7 @@ static void pass1(vpx_image_t *raw, FILE *infile, const char *outfile_name, if (!writer) die("Failed to open %s for writing", outfile_name); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0)) - die_codec(&codec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); // Encode frames. while (vpx_img_read(raw, infile)) { diff --git a/chromium/third_party/libvpx/source/libvpx/examples/vp8cx_set_ref.c b/chromium/third_party/libvpx/source/libvpx/examples/vp8cx_set_ref.c index 846477c61ef..ca528f9e90a 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/vp8cx_set_ref.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/vp8cx_set_ref.c @@ -155,7 +155,7 @@ int main(int argc, char **argv) { die("Failed to open %s for reading.", argv[3]); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) - die_codec(&codec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); // Encode frames. while (vpx_img_read(&raw, infile)) { diff --git a/chromium/third_party/libvpx/source/libvpx/examples/vp9_lossless_encoder.c b/chromium/third_party/libvpx/source/libvpx/examples/vp9_lossless_encoder.c index cb5ca6bfe0b..c4eb3a8b171 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/vp9_lossless_encoder.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/vp9_lossless_encoder.c @@ -110,7 +110,7 @@ int main(int argc, char **argv) { die("Failed to open %s for reading.", argv[3]); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) - die_codec(&codec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); if (vpx_codec_control_(&codec, VP9E_SET_LOSSLESS, 1)) die_codec(&codec, "Failed to use lossless mode"); diff --git a/chromium/third_party/libvpx/source/libvpx/examples/vp9cx_set_ref.c b/chromium/third_party/libvpx/source/libvpx/examples/vp9cx_set_ref.c index 911ad38630c..1a0823153bd 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/vp9cx_set_ref.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/vp9cx_set_ref.c @@ -251,7 +251,7 @@ int main(int argc, char **argv) { die("Failed to open %s for reading.", infile_arg); if (vpx_codec_enc_init(&ecodec, encoder->codec_interface(), &cfg, 0)) - die_codec(&ecodec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); // Disable alt_ref. if (vpx_codec_control(&ecodec, VP8E_SET_ENABLEAUTOALTREF, 0)) diff --git a/chromium/third_party/libvpx/source/libvpx/examples/vpx_temporal_svc_encoder.c b/chromium/third_party/libvpx/source/libvpx/examples/vpx_temporal_svc_encoder.c index 925043d1066..872751cefee 100644 --- a/chromium/third_party/libvpx/source/libvpx/examples/vpx_temporal_svc_encoder.c +++ b/chromium/third_party/libvpx/source/libvpx/examples/vpx_temporal_svc_encoder.c @@ -815,7 +815,7 @@ int main(int argc, char **argv) { #else if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) #endif // CONFIG_VP9_HIGHBITDEPTH - die_codec(&codec, "Failed to initialize encoder"); + die("Failed to initialize encoder"); if (strncmp(encoder->name, "vp8", 3) == 0) { vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed); diff --git a/chromium/third_party/libvpx/source/libvpx/tools_common.c b/chromium/third_party/libvpx/source/libvpx/tools_common.c index 59978b7f93a..cbecfbb4193 100644 --- a/chromium/third_party/libvpx/source/libvpx/tools_common.c +++ b/chromium/third_party/libvpx/source/libvpx/tools_common.c @@ -91,10 +91,13 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) { for (plane = 0; plane < 3; ++plane) { uint8_t *ptr; - const int w = vpx_img_plane_width(yuv_frame, plane); + int w = vpx_img_plane_width(yuv_frame, plane); const int h = vpx_img_plane_height(yuv_frame, plane); int r; - + // Assuming that for nv12 we read all chroma data at one time + if (yuv_frame->fmt == VPX_IMG_FMT_NV12 && plane > 1) break; + // Fixing NV12 chroma width it is odd + if (yuv_frame->fmt == VPX_IMG_FMT_NV12 && plane == 1) w = (w + 1) & ~1; /* Determine the correct plane based on the image format. The for-loop * always counts in Y,U,V order, but this may not match the order of * the data on disk. diff --git a/chromium/third_party/libvpx/source/libvpx/vp8/common/extend.c b/chromium/third_party/libvpx/source/libvpx/vp8/common/extend.c index f4dbce2cd53..b52e9fe93c7 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp8/common/extend.c +++ b/chromium/third_party/libvpx/source/libvpx/vp8/common/extend.c @@ -11,30 +11,40 @@ #include "extend.h" #include "vpx_mem/vpx_mem.h" -static void copy_and_extend_plane(unsigned char *s, /* source */ - int sp, /* source pitch */ - unsigned char *d, /* destination */ - int dp, /* destination pitch */ - int h, /* height */ - int w, /* width */ - int et, /* extend top border */ - int el, /* extend left border */ - int eb, /* extend bottom border */ - int er) { /* extend right border */ - int i; +static void copy_and_extend_plane( + unsigned char *s, /* source */ + int sp, /* source pitch */ + unsigned char *d, /* destination */ + int dp, /* destination pitch */ + int h, /* height */ + int w, /* width */ + int et, /* extend top border */ + int el, /* extend left border */ + int eb, /* extend bottom border */ + int er, /* extend right border */ + int interleave_step) { /* step between pixels of the current plane */ + int i, j; unsigned char *src_ptr1, *src_ptr2; unsigned char *dest_ptr1, *dest_ptr2; int linesize; + if (interleave_step < 1) interleave_step = 1; + /* copy the left and right most columns out */ src_ptr1 = s; - src_ptr2 = s + w - 1; + src_ptr2 = s + (w - 1) * interleave_step; dest_ptr1 = d - el; dest_ptr2 = d + w; for (i = 0; i < h; ++i) { memset(dest_ptr1, src_ptr1[0], el); - memcpy(dest_ptr1 + el, src_ptr1, w); + if (interleave_step == 1) { + memcpy(dest_ptr1 + el, src_ptr1, w); + } else { + for (j = 0; j < w; j++) { + dest_ptr1[el + j] = src_ptr1[interleave_step * j]; + } + } memset(dest_ptr2, src_ptr2[0], er); src_ptr1 += sp; src_ptr2 += sp; @@ -69,9 +79,12 @@ void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src, int eb = dst->border + dst->y_height - src->y_height; int er = dst->border + dst->y_width - src->y_width; + // detect nv12 colorspace + int chroma_step = src->v_buffer - src->u_buffer == 1 ? 2 : 1; + copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer, dst->y_stride, src->y_height, src->y_width, et, el, eb, - er); + er, 1); et = dst->border >> 1; el = dst->border >> 1; @@ -80,11 +93,11 @@ void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src, copy_and_extend_plane(src->u_buffer, src->uv_stride, dst->u_buffer, dst->uv_stride, src->uv_height, src->uv_width, et, el, - eb, er); + eb, er, chroma_step); copy_and_extend_plane(src->v_buffer, src->uv_stride, dst->v_buffer, dst->uv_stride, src->uv_height, src->uv_width, et, el, - eb, er); + eb, er, chroma_step); } void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src, @@ -98,6 +111,8 @@ void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src, int dst_y_offset = srcy * dst->y_stride + srcx; int src_uv_offset = ((srcy * src->uv_stride) >> 1) + (srcx >> 1); int dst_uv_offset = ((srcy * dst->uv_stride) >> 1) + (srcx >> 1); + // detect nv12 colorspace + int chroma_step = src->v_buffer - src->u_buffer == 1 ? 2 : 1; /* If the side is not touching the bounder then don't extend. */ if (srcy) et = 0; @@ -107,7 +122,7 @@ void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src, copy_and_extend_plane(src->y_buffer + src_y_offset, src->y_stride, dst->y_buffer + dst_y_offset, dst->y_stride, srch, srcw, - et, el, eb, er); + et, el, eb, er, 1); et = (et + 1) >> 1; el = (el + 1) >> 1; @@ -118,11 +133,11 @@ void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src, copy_and_extend_plane(src->u_buffer + src_uv_offset, src->uv_stride, dst->u_buffer + dst_uv_offset, dst->uv_stride, srch, - srcw, et, el, eb, er); + srcw, et, el, eb, er, chroma_step); copy_and_extend_plane(src->v_buffer + src_uv_offset, src->uv_stride, dst->v_buffer + dst_uv_offset, dst->uv_stride, srch, - srcw, et, el, eb, er); + srcw, et, el, eb, er, chroma_step); } /* note the extension is only for the last row, for intra prediction purpose */ diff --git a/chromium/third_party/libvpx/source/libvpx/vp8/encoder/onyx_if.c b/chromium/third_party/libvpx/source/libvpx/vp8/encoder/onyx_if.c index 3f5b9816d5d..dccc6ebb1ab 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp8/encoder/onyx_if.c +++ b/chromium/third_party/libvpx/source/libvpx/vp8/encoder/onyx_if.c @@ -4533,9 +4533,11 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, size_t *size, /* Actual bits spent */ cpi->total_actual_bits += cpi->projected_frame_size; +#if 0 && CONFIG_INTERNAL_STATS /* Debug stats */ cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size); +#endif cpi->buffer_level = cpi->bits_off_target; diff --git a/chromium/third_party/libvpx/source/libvpx/vp8/encoder/treewriter.h b/chromium/third_party/libvpx/source/libvpx/vp8/encoder/treewriter.h index c02683a58b7..4e9ed6af17c 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp8/encoder/treewriter.h +++ b/chromium/third_party/libvpx/source/libvpx/vp8/encoder/treewriter.h @@ -14,6 +14,8 @@ /* Trees map alphabets into huffman-like codes suitable for an arithmetic bit coder. Timothy S Murphy 11 October 2004 */ +#include <stdint.h> + #include "./vpx_config.h" #include "vp8/common/treecoder.h" @@ -48,7 +50,9 @@ static INLINE unsigned int vp8_cost_branch(const unsigned int ct[2], vp8_prob p) { /* Imitate existing calculation */ - return ((ct[0] * vp8_cost_zero(p)) + (ct[1] * vp8_cost_one(p))) >> 8; + return (unsigned int)(((((uint64_t)ct[0]) * vp8_cost_zero(p)) + + (((uint64_t)ct[1]) * vp8_cost_one(p))) >> + 8); } /* Small functions to write explicit values and tokens, as well as diff --git a/chromium/third_party/libvpx/source/libvpx/vp8/vp8_cx_iface.c b/chromium/third_party/libvpx/source/libvpx/vp8/vp8_cx_iface.c index 8f7617abf9c..1160f51d64a 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp8/vp8_cx_iface.c +++ b/chromium/third_party/libvpx/source/libvpx/vp8/vp8_cx_iface.c @@ -264,9 +264,12 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx, const vpx_image_t *img) { switch (img->fmt) { case VPX_IMG_FMT_YV12: - case VPX_IMG_FMT_I420: break; + case VPX_IMG_FMT_I420: + case VPX_IMG_FMT_NV12: break; default: - ERROR("Invalid image format. Only YV12 and I420 images are supported"); + ERROR( + "Invalid image format. Only YV12, I420 and NV12 images are " + "supported"); } if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h)) diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/decoder/vp9_decoder.c b/chromium/third_party/libvpx/source/libvpx/vp9/decoder/vp9_decoder.c index bcade52c4e4..7db8ed72d51 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/decoder/vp9_decoder.c +++ b/chromium/third_party/libvpx/source/libvpx/vp9/decoder/vp9_decoder.c @@ -153,6 +153,11 @@ static int vp9_dec_alloc_mi(VP9_COMMON *cm, int mi_size) { } static void vp9_dec_free_mi(VP9_COMMON *cm) { +#if CONFIG_VP9_POSTPROC + // MFQE allocates an additional mip and swaps it with cm->mip. + vpx_free(cm->postproc_state.prev_mip); + cm->postproc_state.prev_mip = NULL; +#endif vpx_free(cm->mip); cm->mip = NULL; vpx_free(cm->mi_grid_base); diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h index 1a25a496edc..7aa4bf7dcaf 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h +++ b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h @@ -532,24 +532,50 @@ typedef struct MOTION_VECTOR_INFO { int_mv mv[2]; } MOTION_VECTOR_INFO; +typedef struct GOP_COMMAND { + int use; // use this command to set gop or not. If not, use vp9's decision. + int show_frame_count; + int use_alt_ref; +} GOP_COMMAND; + +static INLINE void gop_command_on(GOP_COMMAND *gop_command, + int show_frame_count, int use_alt_ref) { + gop_command->use = 1; + gop_command->show_frame_count = show_frame_count; + gop_command->use_alt_ref = use_alt_ref; +} + +static INLINE void gop_command_off(GOP_COMMAND *gop_command) { + gop_command->use = 0; + gop_command->show_frame_count = 0; + gop_command->use_alt_ref = 0; +} + +static INLINE int gop_command_coding_frame_count( + const GOP_COMMAND *gop_command) { + if (gop_command->use == 0) { + assert(0); + return -1; + } + return gop_command->show_frame_count + gop_command->use_alt_ref; +} + typedef struct ENCODE_COMMAND { int use_external_quantize_index; int external_quantize_index; - // A list of binary flags set from the external controller. - // Each binary flag indicates whether the frame is an arf or not. - const int *external_arf_indexes; + GOP_COMMAND gop_command; } ENCODE_COMMAND; static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) { vp9_zero(*encode_command); encode_command->use_external_quantize_index = 0; encode_command->external_quantize_index = -1; - encode_command->external_arf_indexes = NULL; + gop_command_off(&encode_command->gop_command); } -static INLINE void encode_command_set_external_arf_indexes( - ENCODE_COMMAND *encode_command, const int *external_arf_indexes) { - encode_command->external_arf_indexes = external_arf_indexes; +static INLINE void encode_command_set_gop_command( + ENCODE_COMMAND *encode_command, GOP_COMMAND gop_command) { + encode_command->gop_command = gop_command; } static INLINE void encode_command_set_external_quantize_index( diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c index f8e24610aed..dcb62e8768a 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c +++ b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c @@ -18,18 +18,26 @@ static void copy_and_extend_plane(const uint8_t *src, int src_pitch, uint8_t *dst, int dst_pitch, int w, int h, int extend_top, int extend_left, - int extend_bottom, int extend_right) { - int i, linesize; + int extend_bottom, int extend_right, + int interleave_step) { + int i, j, linesize; + const int step = interleave_step < 1 ? 1 : interleave_step; // copy the left and right most columns out const uint8_t *src_ptr1 = src; - const uint8_t *src_ptr2 = src + w - 1; + const uint8_t *src_ptr2 = src + (w - 1) * step; uint8_t *dst_ptr1 = dst - extend_left; uint8_t *dst_ptr2 = dst + w; for (i = 0; i < h; i++) { memset(dst_ptr1, src_ptr1[0], extend_left); - memcpy(dst_ptr1 + extend_left, src_ptr1, w); + if (step == 1) { + memcpy(dst_ptr1 + extend_left, src_ptr1, w); + } else { + for (j = 0; j < w; j++) { + dst_ptr1[extend_left + j] = src_ptr1[step * j]; + } + } memset(dst_ptr2, src_ptr2[0], extend_right); src_ptr1 += src_pitch; src_ptr2 += src_pitch; @@ -122,6 +130,8 @@ void vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src, const int el_uv = el_y >> uv_width_subsampling; const int eb_uv = eb_y >> uv_height_subsampling; const int er_uv = er_y >> uv_width_subsampling; + // detect nv12 colorspace + const int chroma_step = src->v_buffer - src->u_buffer == 1 ? 2 : 1; #if CONFIG_VP9_HIGHBITDEPTH if (src->flags & YV12_FLAG_HIGHBITDEPTH) { @@ -142,15 +152,15 @@ void vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src, copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer, dst->y_stride, src->y_crop_width, src->y_crop_height, - et_y, el_y, eb_y, er_y); + et_y, el_y, eb_y, er_y, 1); copy_and_extend_plane(src->u_buffer, src->uv_stride, dst->u_buffer, dst->uv_stride, src->uv_crop_width, src->uv_crop_height, - et_uv, el_uv, eb_uv, er_uv); + et_uv, el_uv, eb_uv, er_uv, chroma_step); copy_and_extend_plane(src->v_buffer, src->uv_stride, dst->v_buffer, dst->uv_stride, src->uv_crop_width, src->uv_crop_height, - et_uv, el_uv, eb_uv, er_uv); + et_uv, el_uv, eb_uv, er_uv, chroma_step); } void vp9_copy_and_extend_frame_with_rect(const YV12_BUFFER_CONFIG *src, @@ -176,16 +186,18 @@ void vp9_copy_and_extend_frame_with_rect(const YV12_BUFFER_CONFIG *src, const int dst_uv_offset = ((srcy * dst->uv_stride) >> 1) + (srcx >> 1); const int srch_uv = ROUND_POWER_OF_TWO(srch, 1); const int srcw_uv = ROUND_POWER_OF_TWO(srcw, 1); + // detect nv12 colorspace + const int chroma_step = src->v_buffer - src->u_buffer == 1 ? 2 : 1; copy_and_extend_plane(src->y_buffer + src_y_offset, src->y_stride, dst->y_buffer + dst_y_offset, dst->y_stride, srcw, srch, - et_y, el_y, eb_y, er_y); + et_y, el_y, eb_y, er_y, 1); copy_and_extend_plane(src->u_buffer + src_uv_offset, src->uv_stride, dst->u_buffer + dst_uv_offset, dst->uv_stride, srcw_uv, - srch_uv, et_uv, el_uv, eb_uv, er_uv); + srch_uv, et_uv, el_uv, eb_uv, er_uv, chroma_step); copy_and_extend_plane(src->v_buffer + src_uv_offset, src->uv_stride, dst->v_buffer + dst_uv_offset, dst->uv_stride, srcw_uv, - srch_uv, et_uv, el_uv, eb_uv, er_uv); + srch_uv, et_uv, el_uv, eb_uv, er_uv, chroma_step); } diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.c b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.c index 0bda4b7d66c..45b003e1e80 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.c +++ b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.c @@ -389,6 +389,29 @@ static int get_search_range(const VP9_COMP *cpi) { return sr; } +// Reduce limits to keep the motion search within MV_MAX of ref_mv. Not doing +// this can be problematic for big videos (8K) and may cause assert failure +// (or memory violation) in mv_cost. Limits are only modified if they would +// be non-empty. Returns 1 if limits are non-empty. +static int intersect_limits_with_mv_max(MvLimits *mv_limits, const MV *ref_mv) { + const int row_min = + VPXMAX(mv_limits->row_min, (ref_mv->row + 7 - MV_MAX) >> 3); + const int row_max = + VPXMIN(mv_limits->row_max, (ref_mv->row - 1 + MV_MAX) >> 3); + const int col_min = + VPXMAX(mv_limits->col_min, (ref_mv->col + 7 - MV_MAX) >> 3); + const int col_max = + VPXMIN(mv_limits->col_max, (ref_mv->col - 1 + MV_MAX) >> 3); + if (row_min > row_max || col_min > col_max) { + return 0; + } + mv_limits->row_min = row_min; + mv_limits->row_max = row_max; + mv_limits->col_min = col_min; + mv_limits->col_max = col_max; + return 1; +} + static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, const MV *ref_mv, MV *best_mv, int *best_motion_err) { @@ -403,9 +426,14 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, int step_param = 3; int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param; const int sr = get_search_range(cpi); + const MvLimits tmp_mv_limits = x->mv_limits; step_param += sr; further_steps -= sr; + if (!intersect_limits_with_mv_max(&x->mv_limits, ref_mv)) { + return; + } + // Override the default variance function to use MSE. v_fn_ptr.vf = get_block_variance_fn(bsize); #if CONFIG_VP9_HIGHBITDEPTH @@ -451,6 +479,7 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, } } } + x->mv_limits = tmp_mv_limits; } static BLOCK_SIZE get_bsize(const VP9_COMMON *cm, int mb_row, int mb_col) { @@ -2479,9 +2508,6 @@ typedef struct RANGE { * structs. */ static int get_gop_coding_frame_num( -#if CONFIG_RATE_CTRL - const int *external_arf_indexes, -#endif int *use_alt_ref, const FRAME_INFO *frame_info, const FIRST_PASS_INFO *first_pass_info, const RATE_CONTROL *rc, int gf_start_show_idx, const RANGE *active_gf_interval, @@ -2497,24 +2523,6 @@ static int get_gop_coding_frame_num( (frame_info->frame_height + frame_info->frame_width) / 4.0; double zero_motion_accumulator = 1.0; int gop_coding_frames; -#if CONFIG_RATE_CTRL - (void)mv_ratio_accumulator_thresh; - (void)active_gf_interval; - (void)gop_intra_factor; - - if (external_arf_indexes != NULL && rc->frames_to_key > 1) { - // gop_coding_frames = 1 is necessary to filter out the overlay frame, - // since the arf is in this group of picture and its overlay is in the next. - gop_coding_frames = 1; - *use_alt_ref = 1; - while (gop_coding_frames < rc->frames_to_key) { - const int frame_index = gf_start_show_idx + gop_coding_frames; - ++gop_coding_frames; - if (external_arf_indexes[frame_index] == 1) break; - } - return gop_coding_frames; - } -#endif // CONFIG_RATE_CTRL *use_alt_ref = 1; gop_coding_frames = 0; @@ -2741,15 +2749,26 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { gop_intra_factor = 1.0; } - { - gop_coding_frames = get_gop_coding_frame_num( #if CONFIG_RATE_CTRL - cpi->encode_command.external_arf_indexes, -#endif - &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx, - &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames); - use_alt_ref &= allow_alt_ref; + { + const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command; + assert(allow_alt_ref == 1); + if (gop_command->use) { + gop_coding_frames = gop_command_coding_frame_count(gop_command); + use_alt_ref = gop_command->use_alt_ref; + } else { + gop_coding_frames = get_gop_coding_frame_num( + &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx, + &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames); + use_alt_ref &= allow_alt_ref; + } } +#else + gop_coding_frames = get_gop_coding_frame_num( + &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx, + &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames); + use_alt_ref &= allow_alt_ref; +#endif // Was the group length constrained by the requirement for a new KF? rc->constrained_gf_group = (gop_coding_frames >= rc->frames_to_key) ? 1 : 0; @@ -3675,6 +3694,7 @@ void vp9_get_next_group_of_picture(const VP9_COMP *cpi, int *first_is_key_frame, int *use_alt_ref, int *coding_frame_count, int *first_show_idx, int *last_gop_use_alt_ref) { + const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command; // We make a copy of rc here because we want to get information from the // encoder without changing its state. // TODO(angiebird): Avoid copying rc here. @@ -3697,14 +3717,19 @@ void vp9_get_next_group_of_picture(const VP9_COMP *cpi, int *first_is_key_frame, *first_is_key_frame = 1; } - *coding_frame_count = vp9_get_gop_coding_frame_count( - cpi->encode_command.external_arf_indexes, &cpi->oxcf, &cpi->frame_info, - &cpi->twopass.first_pass_info, &rc, *first_show_idx, multi_layer_arf, - allow_alt_ref, *first_is_key_frame, *last_gop_use_alt_ref, use_alt_ref); + if (gop_command->use) { + *coding_frame_count = gop_command_coding_frame_count(gop_command); + *use_alt_ref = gop_command->use_alt_ref; + assert(*coding_frame_count < rc.frames_to_key); + } else { + *coding_frame_count = vp9_get_gop_coding_frame_count( + &cpi->oxcf, &cpi->frame_info, &cpi->twopass.first_pass_info, &rc, + *first_show_idx, multi_layer_arf, allow_alt_ref, *first_is_key_frame, + *last_gop_use_alt_ref, use_alt_ref); + } } -int vp9_get_gop_coding_frame_count(const int *external_arf_indexes, - const VP9EncoderConfig *oxcf, +int vp9_get_gop_coding_frame_count(const VP9EncoderConfig *oxcf, const FRAME_INFO *frame_info, const FIRST_PASS_INFO *first_pass_info, const RATE_CONTROL *rc, int show_idx, @@ -3727,9 +3752,6 @@ int vp9_get_gop_coding_frame_count(const int *external_arf_indexes, } frame_count = get_gop_coding_frame_num( -#if CONFIG_RATE_CTRL - external_arf_indexes, -#endif use_alt_ref, frame_info, first_pass_info, rc, show_idx, &active_gf_interval, gop_intra_factor, oxcf->lag_in_frames); *use_alt_ref &= allow_alt_ref; @@ -3738,8 +3760,7 @@ int vp9_get_gop_coding_frame_count(const int *external_arf_indexes, // Under CONFIG_RATE_CTRL, once the first_pass_info is ready, the number of // coding frames (including show frame and alt ref) can be determined. -int vp9_get_coding_frame_num(const int *external_arf_indexes, - const VP9EncoderConfig *oxcf, +int vp9_get_coding_frame_num(const VP9EncoderConfig *oxcf, const FRAME_INFO *frame_info, const FIRST_PASS_INFO *first_pass_info, int multi_layer_arf, int allow_alt_ref) { @@ -3750,7 +3771,6 @@ int vp9_get_coding_frame_num(const int *external_arf_indexes, int show_idx = 0; int last_gop_use_alt_ref = 0; vp9_rc_init(oxcf, 1, &rc); - rc.static_scene_max_gf_interval = 250; while (show_idx < first_pass_info->num_frames) { int use_alt_ref; @@ -3763,9 +3783,8 @@ int vp9_get_coding_frame_num(const int *external_arf_indexes, } gop_coding_frame_count = vp9_get_gop_coding_frame_count( - external_arf_indexes, oxcf, frame_info, first_pass_info, &rc, show_idx, - multi_layer_arf, allow_alt_ref, first_is_key_frame, - last_gop_use_alt_ref, &use_alt_ref); + oxcf, frame_info, first_pass_info, &rc, show_idx, multi_layer_arf, + allow_alt_ref, first_is_key_frame, last_gop_use_alt_ref, &use_alt_ref); rc.source_alt_ref_active = use_alt_ref; last_gop_use_alt_ref = use_alt_ref; @@ -3777,6 +3796,30 @@ int vp9_get_coding_frame_num(const int *external_arf_indexes, } return coding_frame_num; } + +void vp9_get_key_frame_map(const VP9EncoderConfig *oxcf, + const FRAME_INFO *frame_info, + const FIRST_PASS_INFO *first_pass_info, + int *key_frame_map) { + int show_idx = 0; + RATE_CONTROL rc; + vp9_rc_init(oxcf, 1, &rc); + + // key_frame_map points to an int array with size equal to + // first_pass_info->num_frames, which is also the number of show frames in the + // video. + memset(key_frame_map, 0, + sizeof(*key_frame_map) * first_pass_info->num_frames); + while (show_idx < first_pass_info->num_frames) { + int key_frame_group_size; + key_frame_map[show_idx] = 1; + key_frame_group_size = vp9_get_frames_to_next_key( + oxcf, frame_info, first_pass_info, show_idx, rc.min_gf_interval); + assert(key_frame_group_size > 0); + show_idx += key_frame_group_size; + } + assert(show_idx == first_pass_info->num_frames); +} #endif // CONFIG_RATE_CTRL FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass) { diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h index dcaf2eec676..b1047eab226 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h +++ b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h @@ -264,7 +264,6 @@ void vp9_get_next_group_of_picture(const struct VP9_COMP *cpi, /*!\brief Call this function before coding a new group of pictures to get * information about it. - * \param[in] external_arf_indexes External arf indexs passed in * \param[in] oxcf Encoder config * \param[in] frame_info Frame info * \param[in] first_pass_info First pass stats @@ -279,8 +278,7 @@ void vp9_get_next_group_of_picture(const struct VP9_COMP *cpi, * * \return Returns coding frame count */ -int vp9_get_gop_coding_frame_count(const int *external_arf_indexes, - const struct VP9EncoderConfig *oxcf, +int vp9_get_gop_coding_frame_count(const struct VP9EncoderConfig *oxcf, const FRAME_INFO *frame_info, const FIRST_PASS_INFO *first_pass_info, const RATE_CONTROL *rc, int show_idx, @@ -288,11 +286,20 @@ int vp9_get_gop_coding_frame_count(const int *external_arf_indexes, int first_is_key_frame, int last_gop_use_alt_ref, int *use_alt_ref); -int vp9_get_coding_frame_num(const int *external_arf_indexes, - const struct VP9EncoderConfig *oxcf, +int vp9_get_coding_frame_num(const struct VP9EncoderConfig *oxcf, const FRAME_INFO *frame_info, const FIRST_PASS_INFO *first_pass_info, int multi_layer_arf, int allow_alt_ref); + +/*!\brief Compute a key frame binary map indicates whether key frames appear + * in the corresponding positions. The passed in key_frame_map must point to an + * integer array with length equal to first_pass_info->num_frames, which is the + * number of show frames in the video. + */ +void vp9_get_key_frame_map(const struct VP9EncoderConfig *oxcf, + const FRAME_INFO *frame_info, + const FIRST_PASS_INFO *first_pass_info, + int *key_frame_map); #endif // CONFIG_RATE_CTRL FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass); diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_ratectrl.c b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_ratectrl.c index 9debc01efd2..34dd618acf6 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_ratectrl.c +++ b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_ratectrl.c @@ -431,6 +431,11 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) { rc->max_gf_interval = vp9_rc_get_default_max_gf_interval( oxcf->init_framerate, rc->min_gf_interval); rc->baseline_gf_interval = (rc->min_gf_interval + rc->max_gf_interval) / 2; + if ((oxcf->pass == 0) && (oxcf->rc_mode == VPX_Q)) { + rc->static_scene_max_gf_interval = FIXED_GF_INTERVAL; + } else { + rc->static_scene_max_gf_interval = MAX_STATIC_GF_GROUP_LENGTH; + } rc->force_max_q = 0; rc->last_post_encode_dropped_scene_change = 0; @@ -2371,7 +2376,8 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) { if (cm->show_frame) update_buffer_level_svc_preencode(cpi); if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC && svc->single_layer_svc == 1 && - svc->spatial_layer_id == svc->first_spatial_layer_to_encode) { + svc->spatial_layer_id == svc->first_spatial_layer_to_encode && + svc->temporal_layer_id == 0) { LAYER_CONTEXT *lc = NULL; cpi->resize_pending = vp9_resize_one_pass_cbr(cpi); if (cpi->resize_pending) { @@ -2987,7 +2993,7 @@ void vp9_scene_detection_onepass(VP9_COMP *cpi) { int scene_cut_force_key_frame = 0; int num_zero_temp_sad = 0; uint64_t avg_sad_current = 0; - uint32_t min_thresh = 10000; + uint32_t min_thresh = 20000; // ~5 * 64 * 64 float thresh = 8.0f; uint32_t thresh_key = 140000; if (cpi->oxcf.speed <= 5) thresh_key = 240000; diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_svc_layercontext.c b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_svc_layercontext.c index cd77c08a808..27dc8ec50ff 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_svc_layercontext.c +++ b/chromium/third_party/libvpx/source/libvpx/vp9/encoder/vp9_svc_layercontext.c @@ -864,8 +864,9 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) { } } - // Reset the drop flags for all spatial layers, on the base layer. - if (svc->spatial_layer_id == 0) { + // Reset the drop flags for all spatial layers, on the + // first_spatial_layer_to_encode. + if (svc->spatial_layer_id == svc->first_spatial_layer_to_encode) { vp9_zero(svc->drop_spatial_layer); // TODO(jianj/marpan): Investigate why setting svc->lst/gld/alt_fb_idx // causes an issue with frame dropping and temporal layers, when the frame @@ -1259,7 +1260,7 @@ static void vp9_svc_update_ref_frame_bypass_mode(VP9_COMP *const cpi) { BufferPool *const pool = cm->buffer_pool; int i; for (i = 0; i < REF_FRAMES; i++) { - if (cm->frame_type == KEY_FRAME || + if ((cm->frame_type == KEY_FRAME && !svc->simulcast_mode) || svc->update_buffer_slot[svc->spatial_layer_id] & (1 << i)) { ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[i], cm->new_fb_idx); svc->fb_idx_spatial_layer_id[i] = svc->spatial_layer_id; diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.cc b/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.cc index c417a25890f..7bce91f7f0e 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.cc +++ b/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.cc @@ -612,6 +612,9 @@ static void SetGroupOfPicture(int first_is_key_frame, int use_alt_ref, group_of_picture->show_frame_count = coding_frame_count - use_alt_ref; group_of_picture->start_show_index = first_show_idx; group_of_picture->start_coding_index = start_coding_index; + group_of_picture->first_is_key_frame = first_is_key_frame; + group_of_picture->use_alt_ref = use_alt_ref; + group_of_picture->last_gop_use_alt_ref = last_gop_use_alt_ref; // We need to make a copy of start reference frame info because we // use it to simulate the ref frame update. @@ -776,6 +779,9 @@ void SimpleEncode::ComputeFirstPassStats() { free_encoder(cpi); rewind(in_file_); vpx_img_free(&img); + + // Generate key_frame_map based on impl_ptr_->first_pass_stats. + key_frame_map_ = ComputeKeyFrameMap(); } std::vector<std::vector<double>> SimpleEncode::ObserveFirstPassStats() { @@ -800,9 +806,39 @@ std::vector<std::vector<double>> SimpleEncode::ObserveFirstPassStats() { return output_stats; } -void SimpleEncode::SetExternalGroupOfPicture( - std::vector<int> external_arf_indexes) { - external_arf_indexes_ = external_arf_indexes; +void SimpleEncode::SetExternalGroupOfPicturesMap(int *gop_map, + int gop_map_size) { + for (int i = 0; i < gop_map_size; ++i) { + gop_map_.push_back(gop_map[i]); + } + // The following will check and modify gop_map_ to make sure the + // gop_map_ satisfies the constraints. + // 1) Each key frame position should be at the start of a gop. + // 2) The last gop should not use an alt ref. + assert(gop_map_.size() == key_frame_map_.size()); + int last_gop_start = 0; + for (int i = 0; static_cast<size_t>(i) < gop_map_.size(); ++i) { + if (key_frame_map_[i] == 1 && gop_map_[i] == 0) { + fprintf(stderr, "Add an extra gop start at show_idx %d\n", i); + // Insert a gop start at key frame location. + gop_map_[i] |= kGopMapFlagStart; + gop_map_[i] |= kGopMapFlagUseAltRef; + } + if (gop_map_[i] & kGopMapFlagStart) { + last_gop_start = i; + } + } + if (gop_map_[last_gop_start] & kGopMapFlagUseAltRef) { + fprintf(stderr, + "Last group of pictures starting at show_idx %d shouldn't use alt " + "ref\n", + last_gop_start); + gop_map_[last_gop_start] &= ~kGopMapFlagUseAltRef; + } +} + +std::vector<int> SimpleEncode::ObserveExternalGroupOfPicturesMap() { + return gop_map_; } template <typename T> @@ -813,6 +849,32 @@ T *GetVectorData(const std::vector<T> &v) { return const_cast<T *>(v.data()); } +static GOP_COMMAND GetGopCommand(const std::vector<int> &gop_map, + int start_show_index) { + GOP_COMMAND gop_command; + if (gop_map.size() > 0) { + assert(static_cast<size_t>(start_show_index) < gop_map.size()); + assert((gop_map[start_show_index] & kGopMapFlagStart) != 0); + int end_show_index = start_show_index + 1; + // gop_map[end_show_index] & kGopMapFlagStart == 0 means this is + // the start of a gop. + while (static_cast<size_t>(end_show_index) < gop_map.size() && + (gop_map[end_show_index] & kGopMapFlagStart) == 0) { + ++end_show_index; + } + const int show_frame_count = end_show_index - start_show_index; + int use_alt_ref = (gop_map[start_show_index] & kGopMapFlagUseAltRef) != 0; + if (static_cast<size_t>(end_show_index) == gop_map.size()) { + // This is the last gop group, there must be no altref. + use_alt_ref = 0; + } + gop_command_on(&gop_command, show_frame_count, use_alt_ref); + } else { + gop_command_off(&gop_command); + } + return gop_command; +} + void SimpleEncode::StartEncode() { assert(impl_ptr_->first_pass_stats.size() > 0); vpx_rational_t frame_rate = @@ -834,11 +896,10 @@ void SimpleEncode::StartEncode() { frame_coding_index_ = 0; show_frame_count_ = 0; - encode_command_set_external_arf_indexes(&impl_ptr_->cpi->encode_command, - GetVectorData(external_arf_indexes_)); - UpdateKeyFrameGroup(show_frame_count_); + const GOP_COMMAND gop_command = GetGopCommand(gop_map_, show_frame_count_); + encode_command_set_gop_command(&impl_ptr_->cpi->encode_command, gop_command); UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_, &group_of_picture_); rewind(in_file_); @@ -914,6 +975,9 @@ void SimpleEncode::PostUpdateState( IncreaseGroupOfPictureIndex(&group_of_picture_); if (IsGroupOfPictureFinished(group_of_picture_)) { + const GOP_COMMAND gop_command = GetGopCommand(gop_map_, show_frame_count_); + encode_command_set_gop_command(&impl_ptr_->cpi->encode_command, + gop_command); // This function needs to be called after ref_frame_info_ is updated // properly in PostUpdateRefFrameInfo() and UpdateKeyFrameGroup(). UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_, @@ -1002,8 +1066,24 @@ void SimpleEncode::EncodeFrameWithQuantizeIndex( encode_command_reset_external_quantize_index(&impl_ptr_->cpi->encode_command); } +static int GetCodingFrameNumFromGopMap(const std::vector<int> &gop_map) { + int start_show_index = 0; + int coding_frame_count = 0; + while (static_cast<size_t>(start_show_index) < gop_map.size()) { + const GOP_COMMAND gop_command = GetGopCommand(gop_map, start_show_index); + start_show_index += gop_command.show_frame_count; + coding_frame_count += gop_command_coding_frame_count(&gop_command); + } + assert(start_show_index == gop_map.size()); + return coding_frame_count; +} + int SimpleEncode::GetCodingFrameNum() const { - assert(impl_ptr_->first_pass_stats.size() - 1 > 0); + assert(impl_ptr_->first_pass_stats.size() > 0); + if (gop_map_.size() > 0) { + return GetCodingFrameNumFromGopMap(gop_map_); + } + // These are the default settings for now. const int multi_layer_arf = 0; const int allow_alt_ref = 1; @@ -1017,11 +1097,33 @@ int SimpleEncode::GetCodingFrameNum() const { fps_init_first_pass_info(&first_pass_info, GetVectorData(impl_ptr_->first_pass_stats), num_frames_); - return vp9_get_coding_frame_num(external_arf_indexes_.data(), &oxcf, - &frame_info, &first_pass_info, + return vp9_get_coding_frame_num(&oxcf, &frame_info, &first_pass_info, multi_layer_arf, allow_alt_ref); } +std::vector<int> SimpleEncode::ComputeKeyFrameMap() const { + // The last entry of first_pass_stats is the overall stats. + assert(impl_ptr_->first_pass_stats.size() == num_frames_ + 1); + vpx_rational_t frame_rate = + make_vpx_rational(frame_rate_num_, frame_rate_den_); + const VP9EncoderConfig oxcf = + vp9_get_encoder_config(frame_width_, frame_height_, frame_rate, + target_bitrate_, VPX_RC_LAST_PASS); + FRAME_INFO frame_info = vp9_get_frame_info(&oxcf); + FIRST_PASS_INFO first_pass_info; + fps_init_first_pass_info(&first_pass_info, + GetVectorData(impl_ptr_->first_pass_stats), + num_frames_); + std::vector<int> key_frame_map(num_frames_, 0); + vp9_get_key_frame_map(&oxcf, &frame_info, &first_pass_info, + GetVectorData(key_frame_map)); + return key_frame_map; +} + +std::vector<int> SimpleEncode::ObserveKeyFrameMap() const { + return key_frame_map_; +} + uint64_t SimpleEncode::GetFramePixelCount() const { assert(frame_width_ % 2 == 0); assert(frame_height_ % 2 == 0); diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.h b/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.h index 4221a70150c..b2173207016 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.h +++ b/chromium/third_party/libvpx/source/libvpx/vp9/simple_encode.h @@ -39,6 +39,14 @@ enum RefFrameType { kRefFrameTypeNone = -1, }; +enum GopMapFlag { + kGopMapFlagStart = + 1 << 0, // Indicate this location is the start of a group of pictures. + kGopMapFlagUseAltRef = + 1 << 1, // Indicate this group of pictures will use an alt ref. Only set + // this flag when kGopMapFlagStart is set. +}; + // The frame is split to 4x4 blocks. // This structure contains the information of each 4x4 block. struct PartitionInfo { @@ -255,6 +263,7 @@ struct GroupOfPicture { // triggered when the coded frame is the last one in the previous group of // pictures. std::vector<EncodeFrameInfo> encode_frame_list; + // Indicates the index of the next coding frame in encode_frame_list. // In other words, EncodeFrameInfo of the next coding frame can be // obtained with encode_frame_list[next_encode_frame_index]. @@ -263,13 +272,25 @@ struct GroupOfPicture { // will be increased after each EncodeFrame()/EncodeFrameWithQuantizeIndex() // call. int next_encode_frame_index; + // Number of show frames in this group of pictures. int show_frame_count; + // The show index/timestamp of the earliest show frame in the group of // pictures. int start_show_index; - // The coding index of the first coding frame in the group of picture. + + // The coding index of the first coding frame in the group of pictures. int start_coding_index; + + // Indicates whether this group of pictures starts with a key frame. + int first_is_key_frame; + + // Indicates whether this group of pictures uses an alt ref. + int use_alt_ref; + + // Indicates whether previous group of pictures used an alt ref. + int last_gop_use_alt_ref; }; class SimpleEncode { @@ -283,8 +304,9 @@ class SimpleEncode { SimpleEncode(SimpleEncode &) = delete; SimpleEncode &operator=(const SimpleEncode &) = delete; - // Makes encoder compute the first pass stats and store it internally for - // future encode. + // Makes encoder compute the first pass stats and store it at + // impl_ptr_->first_pass_stats. key_frame_map_ is also computed based on the + // first pass stats. void ComputeFirstPassStats(); // Outputs the first pass stats represented by a 2-D vector. @@ -293,13 +315,32 @@ class SimpleEncode { // values. For details, please check FIRSTPASS_STATS in vp9_firstpass.h std::vector<std::vector<double>> ObserveFirstPassStats(); - // Sets arf indexes for the video from external input. - // The arf index determines whether a frame is arf or not. - // Therefore it also determines the group of picture size. - // If set, VP9 will use the external arf index to make decision. + // Ouputs a copy of key_frame_map_, a binary vector with size equal to the + // number of show frames in the video. For each entry in the vector, 1 + // indicates the position is a key frame and 0 indicates it's not a key frame. + // This function should be called after ComputeFirstPassStats() + std::vector<int> ObserveKeyFrameMap() const; + + // Sets group of pictures map for coding the entire video. + // Each entry in the gop_map corresponds to a show frame in the video. + // Therefore, the size of gop_map should equal to the number of show frames in + // the entire video. + // If a given entry's kGopMapFlagStart is set, it means this is the start of a + // gop. Once kGopMapFlagStart is set, one can set kGopMapFlagUseAltRef to + // indicate whether this gop use altref. + // If a given entry is zero, it means it's in the middle of a gop. // This function should be called only once after ComputeFirstPassStats(), // before StartEncode(). - void SetExternalGroupOfPicture(std::vector<int> external_arf_indexes); + // This API will check and modify the gop_map to satisfy the following + // constraints. + // 1) Each key frame position should be at the start of a gop. + // 2) The last gop should not use an alt ref. + void SetExternalGroupOfPicturesMap(int *gop_map, int gop_map_size); + + // Observe the group of pictures map set through + // SetExternalGroupOfPicturesMap(). This function should be called after + // SetExternalGroupOfPicturesMap(). + std::vector<int> ObserveExternalGroupOfPicturesMap(); // Initializes the encoder for actual encoding. // This function should be called after ComputeFirstPassStats(). @@ -341,6 +382,12 @@ class SimpleEncode { uint64_t GetFramePixelCount() const; private: + // Compute the key frame locations of the video based on first pass stats. + // The results are returned as a binary vector with 1s indicating keyframes + // and 0s indicating non keyframes. + // It has to be called after impl_ptr_->first_pass_stats is computed. + std::vector<int> ComputeKeyFrameMap() const; + // Updates key_frame_group_size_, reset key_frame_group_index_ and init // ref_frame_info_. void UpdateKeyFrameGroup(int key_frame_show_index); @@ -363,7 +410,8 @@ class SimpleEncode { std::FILE *out_file_; std::unique_ptr<EncodeImpl> impl_ptr_; - std::vector<int> external_arf_indexes_; + std::vector<int> key_frame_map_; + std::vector<int> gop_map_; GroupOfPicture group_of_picture_; // The key frame group size includes one key frame plus the number of diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c b/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c index bd6b07a299d..15aa7e60f79 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c +++ b/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c @@ -355,13 +355,14 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx, switch (img->fmt) { case VPX_IMG_FMT_YV12: case VPX_IMG_FMT_I420: - case VPX_IMG_FMT_I42016: break; + case VPX_IMG_FMT_I42016: + case VPX_IMG_FMT_NV12: break; case VPX_IMG_FMT_I422: case VPX_IMG_FMT_I444: case VPX_IMG_FMT_I440: if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) { ERROR( - "Invalid image format. I422, I444, I440 images are " + "Invalid image format. I422, I444, I440, NV12 images are " "not supported in profile."); } break; @@ -391,6 +392,7 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx, static int get_image_bps(const vpx_image_t *img) { switch (img->fmt) { case VPX_IMG_FMT_YV12: + case VPX_IMG_FMT_NV12: case VPX_IMG_FMT_I420: return 12; case VPX_IMG_FMT_I422: return 16; case VPX_IMG_FMT_I444: return 24; diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/vp9_iface_common.c b/chromium/third_party/libvpx/source/libvpx/vp9/vp9_iface_common.c index 74d08a5873a..8d031694d8d 100644 --- a/chromium/third_party/libvpx/source/libvpx/vp9/vp9_iface_common.c +++ b/chromium/third_party/libvpx/source/libvpx/vp9/vp9_iface_common.c @@ -88,8 +88,9 @@ vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, yv12->y_width = img->d_w; yv12->y_height = img->d_h; - yv12->uv_width = - img->x_chroma_shift == 1 ? (1 + yv12->y_width) / 2 : yv12->y_width; + yv12->uv_width = img->x_chroma_shift == 1 || img->fmt == VPX_IMG_FMT_NV12 + ? (1 + yv12->y_width) / 2 + : yv12->y_width; yv12->uv_height = img->y_chroma_shift == 1 ? (1 + yv12->y_height) / 2 : yv12->y_height; yv12->uv_crop_width = yv12->uv_width; @@ -127,5 +128,9 @@ vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, #endif // CONFIG_VP9_HIGHBITDEPTH yv12->subsampling_x = img->x_chroma_shift; yv12->subsampling_y = img->y_chroma_shift; + // When reading the data, UV are in one plane for NV12 format, thus + // x_chroma_shift is 0. After converting, UV are in separate planes, and + // subsampling_x should be set to 1. + if (img->fmt == VPX_IMG_FMT_NV12) yv12->subsampling_x = 1; return VPX_CODEC_OK; } diff --git a/chromium/third_party/libvpx/source/libvpx/vpx/src/vpx_image.c b/chromium/third_party/libvpx/source/libvpx/vpx/src/vpx_image.c index a7c6ec0ceab..ff496b5d34f 100644 --- a/chromium/third_party/libvpx/source/libvpx/vpx/src/vpx_image.c +++ b/chromium/third_party/libvpx/source/libvpx/vpx/src/vpx_image.c @@ -39,7 +39,8 @@ static vpx_image_t *img_alloc_helper(vpx_image_t *img, vpx_img_fmt_t fmt, /* Get sample size for this format */ switch (fmt) { case VPX_IMG_FMT_I420: - case VPX_IMG_FMT_YV12: bps = 12; break; + case VPX_IMG_FMT_YV12: + case VPX_IMG_FMT_NV12: bps = 12; break; case VPX_IMG_FMT_I422: case VPX_IMG_FMT_I440: bps = 16; break; case VPX_IMG_FMT_I444: bps = 24; break; @@ -51,6 +52,8 @@ static vpx_image_t *img_alloc_helper(vpx_image_t *img, vpx_img_fmt_t fmt, } /* Get chroma shift values for this format */ + // For VPX_IMG_FMT_NV12, xcs needs to be 0 such that UV data is all read at + // one time. switch (fmt) { case VPX_IMG_FMT_I420: case VPX_IMG_FMT_YV12: @@ -62,6 +65,7 @@ static vpx_image_t *img_alloc_helper(vpx_image_t *img, vpx_img_fmt_t fmt, switch (fmt) { case VPX_IMG_FMT_I420: + case VPX_IMG_FMT_NV12: case VPX_IMG_FMT_I440: case VPX_IMG_FMT_YV12: case VPX_IMG_FMT_I42016: @@ -173,7 +177,12 @@ int vpx_img_set_rect(vpx_image_t *img, unsigned int x, unsigned int y, data + x * bytes_per_sample + y * img->stride[VPX_PLANE_Y]; data += img->h * img->stride[VPX_PLANE_Y]; - if (!(img->fmt & VPX_IMG_FMT_UV_FLIP)) { + if (img->fmt == VPX_IMG_FMT_NV12) { + img->planes[VPX_PLANE_U] = + data + (x >> img->x_chroma_shift) + + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U]; + img->planes[VPX_PLANE_V] = img->planes[VPX_PLANE_U] + 1; + } else if (!(img->fmt & VPX_IMG_FMT_UV_FLIP)) { img->planes[VPX_PLANE_U] = data + (x >> img->x_chroma_shift) * bytes_per_sample + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U]; diff --git a/chromium/third_party/libvpx/source/libvpx/vpx/vpx_image.h b/chromium/third_party/libvpx/source/libvpx/vpx/vpx_image.h index 98be5966a24..bc23be50c58 100644 --- a/chromium/third_party/libvpx/source/libvpx/vpx/vpx_image.h +++ b/chromium/third_party/libvpx/source/libvpx/vpx/vpx_image.h @@ -43,6 +43,7 @@ typedef enum vpx_img_fmt { VPX_IMG_FMT_I422 = VPX_IMG_FMT_PLANAR | 5, VPX_IMG_FMT_I444 = VPX_IMG_FMT_PLANAR | 6, VPX_IMG_FMT_I440 = VPX_IMG_FMT_PLANAR | 7, + VPX_IMG_FMT_NV12 = VPX_IMG_FMT_PLANAR | 9, VPX_IMG_FMT_I42016 = VPX_IMG_FMT_I420 | VPX_IMG_FMT_HIGHBITDEPTH, VPX_IMG_FMT_I42216 = VPX_IMG_FMT_I422 | VPX_IMG_FMT_HIGHBITDEPTH, VPX_IMG_FMT_I44416 = VPX_IMG_FMT_I444 | VPX_IMG_FMT_HIGHBITDEPTH, diff --git a/chromium/third_party/libvpx/source/libvpx/vpxenc.c b/chromium/third_party/libvpx/source/libvpx/vpxenc.c index 50c36bedd54..64288e83d28 100644 --- a/chromium/third_party/libvpx/source/libvpx/vpxenc.c +++ b/chromium/third_party/libvpx/source/libvpx/vpxenc.c @@ -95,6 +95,8 @@ static const arg_def_t debugmode = ARG_DEF("D", "debug", 0, "Debug mode (makes output deterministic)"); static const arg_def_t outputfile = ARG_DEF("o", "output", 1, "Output filename"); +static const arg_def_t use_nv12 = + ARG_DEF(NULL, "nv12", 0, "Input file is NV12 "); static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0, "Input file is YV12 "); static const arg_def_t use_i420 = @@ -220,7 +222,8 @@ static const arg_def_t error_resilient = static const arg_def_t lag_in_frames = ARG_DEF(NULL, "lag-in-frames", 1, "Max number of frames to lag"); -static const arg_def_t *global_args[] = { &use_yv12, +static const arg_def_t *global_args[] = { &use_nv12, + &use_yv12, &use_i420, &use_i422, &use_i444, @@ -696,6 +699,8 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) { global->deadline = VPX_DL_REALTIME; else if (arg_match(&arg, &use_yv12, argi)) global->color_type = YV12; + else if (arg_match(&arg, &use_nv12, argi)) + global->color_type = NV12; else if (arg_match(&arg, &use_i420, argi)) global->color_type = I420; else if (arg_match(&arg, &use_i422, argi)) @@ -1642,6 +1647,7 @@ int main(int argc, const char **argv_) { case I444: input.fmt = VPX_IMG_FMT_I444; break; case I440: input.fmt = VPX_IMG_FMT_I440; break; case YV12: input.fmt = VPX_IMG_FMT_YV12; break; + case NV12: input.fmt = VPX_IMG_FMT_NV12; break; } { diff --git a/chromium/third_party/libvpx/source/libvpx/vpxenc.h b/chromium/third_party/libvpx/source/libvpx/vpxenc.h index b780aedca69..be54840f7dd 100644 --- a/chromium/third_party/libvpx/source/libvpx/vpxenc.h +++ b/chromium/third_party/libvpx/source/libvpx/vpxenc.h @@ -28,6 +28,7 @@ typedef enum { I444, // 4:4:4 8+ bit-depth I440, // 4:4:0 8+ bit-depth YV12, // 4:2:0 with uv flipped, only 8-bit depth + NV12, // 4:2:0 with uv interleaved } ColorInputType; struct VpxInterface; |