Merge "Clamping active_{best, worst}_quality values."diff --git a/build/make/ads2gas.pl b/build/make/ads2gas.pl
index 9c41901..7272424 100755
--- a/build/make/ads2gas.pl
+++ b/build/make/ads2gas.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
diff --git a/build/make/ads2gas_apple.pl b/build/make/ads2gas_apple.pl
index befb3db..a82f3eb 100755
--- a/build/make/ads2gas_apple.pl
+++ b/build/make/ads2gas_apple.pl
@@ -75,16 +75,16 @@
s/:SHR:/ >> /g;
# Convert ELSE to .else
- s/ELSE/.else/g;
+ s/\bELSE\b/.else/g;
# Convert ENDIF to .endif
- s/ENDIF/.endif/g;
+ s/\bENDIF\b/.endif/g;
# Convert ELSEIF to .elseif
- s/ELSEIF/.elseif/g;
+ s/\bELSEIF\b/.elseif/g;
# Convert LTORG to .ltorg
- s/LTORG/.ltorg/g;
+ s/\bLTORG\b/.ltorg/g;
# Convert IF :DEF:to .if
# gcc doesn't have the ability to do a conditional
@@ -164,7 +164,7 @@
s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
# ALIGN directive
- s/ALIGN/.balign/g;
+ s/\bALIGN\b/.balign/g;
# Strip ARM
s/\sARM/@ ARM/g;
@@ -184,7 +184,7 @@
s/(.*)EQU(.*)/.set $1, $2/;
# Begin macro definition
- if (/MACRO/)
+ if (/\bMACRO\b/)
{
# Process next line down, which will be the macro definition
$_ = <STDIN>;
@@ -215,7 +215,7 @@
# For macros, use \ to reference formal params
# s/\$/\\/g; # End macro definition
- s/MEND/.endm/; # No need to tell it where to stop assembling
+ s/\bMEND\b/.endm/; # No need to tell it where to stop assembling
next if /^\s*END\s*$/;
# Clang used by Chromium differs slightly from clang in XCode in what it
diff --git a/build/make/gen_msvs_proj.sh b/build/make/gen_msvs_proj.sh
index fc5011b..7df0334 100755
--- a/build/make/gen_msvs_proj.sh
+++ b/build/make/gen_msvs_proj.sh
@@ -155,8 +155,8 @@
tag Tool \
Name="VCCustomBuildTool" \
Description="Assembling \$(InputFileName)" \
- CommandLine="$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)$objf" \
- Outputs="\$(IntDir)$objf" \
+ CommandLine="$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)\\$objf" \
+ Outputs="\$(IntDir)\\$objf" \
close_tag FileConfiguration
done
@@ -170,7 +170,7 @@
tag Tool \
Name="VCCLCompilerTool" \
- ObjectFile="\$(IntDir)$objf" \
+ ObjectFile="\$(IntDir)\\$objf" \
close_tag FileConfiguration
done
diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c
index 495e9d7..8c16957 100644
--- a/build/make/obj_int_extract.c
+++ b/build/make/obj_int_extract.c
@@ -21,6 +21,7 @@
OUTPUT_FMT_PLAIN,
OUTPUT_FMT_RVDS,
OUTPUT_FMT_GAS,
+ OUTPUT_FMT_C_HEADER,
} output_fmt_t;
int log_msg(const char *fmt, ...) {
@@ -43,9 +44,12 @@
case OUTPUT_FMT_RVDS:
printf("%-40s EQU %5d\n", name, val);
return 0;
- case OUTPUT_FMT_GAS:
+ case OUTPUT_FMT_GAS:
printf(".set %-40s, %5d\n", name, val);
return 0;
+ case OUTPUT_FMT_C_HEADER:
+ printf("#define %-40s %5d\n", name, val);
+ return 0;
default:
log_msg("Unsupported mode: %d", mode);
return 1;
@@ -491,6 +495,13 @@
sym.st_name),
val);
break;
+ case OUTPUT_FMT_C_HEADER:
+ printf("#define %-40s %5d\n",
+ parse_elf_string_table(&elf,
+ shdr.sh_link,
+ sym.st_name),
+ val);
+ break;
default:
printf("%s = %d\n",
parse_elf_string_table(&elf,
@@ -762,6 +773,7 @@
fprintf(stderr, "Output Formats:\n");
fprintf(stderr, " gas - compatible with GNU assembler\n");
fprintf(stderr, " rvds - compatible with armasm\n");
+ fprintf(stderr, " cheader - c/c++ header file\n");
goto bail;
}
@@ -771,6 +783,8 @@
mode = OUTPUT_FMT_RVDS;
else if (!strcmp(argv[1], "gas"))
mode = OUTPUT_FMT_GAS;
+ else if (!strcmp(argv[1], "cheader"))
+ mode = OUTPUT_FMT_C_HEADER;
else
f = argv[1];
diff --git a/examples.mk b/examples.mk
index a10ee52d..0b62df9 100644
--- a/examples.mk
+++ b/examples.mk
@@ -41,6 +41,7 @@
vpxenc.SRCS += args.c args.h y4minput.c y4minput.h vpxenc.h
vpxenc.SRCS += ivfdec.c ivfdec.h
vpxenc.SRCS += ivfenc.c ivfenc.h
+vpxenc.SRCS += rate_hist.c rate_hist.h
vpxenc.SRCS += tools_common.c tools_common.h
vpxenc.SRCS += warnings.c warnings.h
vpxenc.SRCS += webmenc.c webmenc.h
@@ -74,9 +75,13 @@
#example_xma.DESCRIPTION = External Memory Allocation mode usage
GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += simple_decoder.c
-simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
-simple_decoder.DESCRIPTION = Simplified decoder loop
+simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
+simple_decoder.SRCS += ivfdec.h ivfdec.c
+simple_decoder.SRCS += tools_common.h tools_common.c
+simple_decoder.DESCRIPTION = Simplified decoder loop
GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += postproc.c
+postproc.SRCS += ivfdec.h ivfdec.c
+postproc.SRCS += tools_common.h tools_common.c
postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
postproc.DESCRIPTION = Decoder postprocessor control
GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += decode_to_md5.c
@@ -97,6 +102,8 @@
force_keyframe.DESCRIPTION = Force generation of keyframes
ifeq ($(CONFIG_DECODERS),yes)
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += decode_with_drops.c
+decode_with_drops.SRCS += ivfdec.h ivfdec.c
+decode_with_drops.SRCS += tools_common.h tools_common.c
endif
decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
decode_with_drops.DESCRIPTION = Drops frames while decoding
diff --git a/examples/decode_to_md5.c b/examples/decode_to_md5.c
index 67cbd6c..bba2182 100644
--- a/examples/decode_to_md5.c
+++ b/examples/decode_to_md5.c
@@ -29,7 +29,6 @@
// is processed, then U, then V. It is important to honor the image's `stride`
// values.
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -44,28 +43,6 @@
#include "./tools_common.h"
#include "./vpx_config.h"
-#define VP8_FOURCC 0x30385056
-#define VP9_FOURCC 0x30395056
-
-static vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) {
- switch (fourcc) {
- case VP8_FOURCC:
- return vpx_codec_vp8_dx();
- case VP9_FOURCC:
- return vpx_codec_vp9_dx();
- }
- return NULL;
-}
-
-static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
- const char *detail = vpx_codec_error_detail(ctx);
-
- printf("%s: %s\n", s, vpx_codec_error(ctx));
- if(detail)
- printf(" %s\n",detail);
- exit(EXIT_FAILURE);
-}
-
static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) {
int plane, y;
MD5Context md5;
diff --git a/examples/decode_with_drops.c b/examples/decode_with_drops.c
index bfb6d3a..12686de 100644
--- a/examples/decode_with_drops.c
+++ b/examples/decode_with_drops.c
@@ -52,126 +52,103 @@
// The example decides whether to drop the frame based on the current
// frame number, immediately before decoding the frame.
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#include "./ivfdec.h"
+
#define VPX_CODEC_DISABLE_COMPAT 1
-#include "./vpx_config.h"
+
#include "vpx/vp8dx.h"
#include "vpx/vpx_decoder.h"
-#define interface (vpx_codec_vp8_dx())
+#include "./tools_common.h"
+#include "./vpx_config.h"
-#define IVF_FILE_HDR_SZ (32)
-#define IVF_FRAME_HDR_SZ (12)
+static const char *exec_name;
-static unsigned int mem_get_le32(const unsigned char *mem) {
- return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
+void usage_exit() {
+ fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name);
+ exit(EXIT_FAILURE);
}
-static void die(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- if(fmt[strlen(fmt)-1] != '\n')
- printf("\n");
- exit(EXIT_FAILURE);
-}
-
-static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
- const char *detail = vpx_codec_error_detail(ctx);
-
- printf("%s: %s\n", s, vpx_codec_error(ctx));
- if(detail)
- printf(" %s\n",detail);
- exit(EXIT_FAILURE);
-}
-
-
int main(int argc, char **argv) {
- FILE *infile, *outfile;
- vpx_codec_ctx_t codec;
- int flags = 0, frame_cnt = 0;
- unsigned char file_hdr[IVF_FILE_HDR_SZ];
- unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
- unsigned char frame[256*1024];
- vpx_codec_err_t res;
- int n, m, is_range;
+ FILE *infile, *outfile;
+ vpx_codec_ctx_t codec;
+ vpx_codec_iface_t *iface;
+ int flags = 0, frame_cnt = 0;
+ vpx_video_t *video;
+ int n, m, is_range;
+ char *nptr;
- (void)res;
- /* Open files */
- if(argc!=4)
- die("Usage: %s <infile> <outfile> <N-M|N/M>\n", argv[0]);
- {
- char *nptr;
- n = strtol(argv[3], &nptr, 0);
- m = strtol(nptr+1, NULL, 0);
- is_range = *nptr == '-';
- if(!n || !m || (*nptr != '-' && *nptr != '/'))
- die("Couldn't parse pattern %s\n", argv[3]);
+ exec_name = argv[0];
+
+ if (argc != 4)
+ die("Invalid number of arguments");
+
+ if (!(infile = fopen(argv[1], "rb")))
+ die("Failed to open %s for reading", argv[1]);
+
+ if (!(outfile = fopen(argv[2], "wb")))
+ die("Failed to open %s for writing", argv[2]);
+
+ n = strtol(argv[3], &nptr, 0);
+ m = strtol(nptr + 1, NULL, 0);
+ is_range = (*nptr == '-');
+ if (!n || !m || (*nptr != '-' && *nptr != '/'))
+ die("Couldn't parse pattern %s\n", argv[3]);
+
+ video = vpx_video_open_file(infile);
+ if (!video)
+ die("%s is not a supported input file.", argv[1]);
+
+ iface = get_codec_interface(vpx_video_get_fourcc(video));
+ if (!iface)
+ die("Unknown FOURCC code.");
+
+ printf("Using %s\n", vpx_codec_iface_name(iface));
+
+ if (vpx_codec_dec_init(&codec, iface, NULL, flags))
+ die_codec(&codec, "Failed to initialize decoder");
+
+ while (vpx_video_read_frame(video)) {
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t *img = NULL;
+ size_t frame_size = 0;
+ int skip;
+ const unsigned char *frame = vpx_video_get_frame(video, &frame_size);
+ if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0))
+ die_codec(&codec, "Failed to decode frame");
+
+ ++frame_cnt;
+
+ skip = (is_range && frame_cnt >= n && frame_cnt <= m) ||
+ (!is_range && m - (frame_cnt - 1) % m <= n);
+
+ if (!skip) {
+ putc('.', stdout);
+
+ while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL)
+ vpx_img_write(img, outfile);
+ } else {
+ putc('X', stdout);
}
- if(!(infile = fopen(argv[1], "rb")))
- die("Failed to open %s for reading", argv[1]);
- if(!(outfile = fopen(argv[2], "wb")))
- die("Failed to open %s for writing", argv[2]);
- /* Read file header */
- if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
- && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
- && file_hdr[3]=='F'))
- die("%s is not an IVF file.", argv[1]);
+ fflush(stdout);
+ }
- printf("Using %s\n",vpx_codec_iface_name(interface));
- /* Initialize codec */
- if(vpx_codec_dec_init(&codec, interface, NULL, flags))
- die_codec(&codec, "Failed to initialize decoder");
+ printf("Processed %d frames.\n", frame_cnt);
+ if (vpx_codec_destroy(&codec))
+ die_codec(&codec, "Failed to destroy codec");
- /* Read each frame */
- while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
- int frame_sz = mem_get_le32(frame_hdr);
- vpx_codec_iter_t iter = NULL;
- vpx_image_t *img;
+ printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
+ vpx_video_get_width(video), vpx_video_get_height(video), argv[2]);
+ vpx_video_close(video);
- frame_cnt++;
- if(frame_sz > sizeof(frame))
- die("Frame %d data too big for example code buffer", frame_sz);
- if(fread(frame, 1, frame_sz, infile) != frame_sz)
- die("Frame %d failed to read complete frame", frame_cnt);
+ fclose(outfile);
+ fclose(infile);
- if((is_range && frame_cnt >= n && frame_cnt <= m)
- ||(!is_range && m - (frame_cnt-1)%m <= n)) {
- putc('X', stdout);
- continue;
- }
- putc('.', stdout);
- fflush(stdout);
- /* Decode the frame */
- if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
- die_codec(&codec, "Failed to decode frame");
-
- /* Write decoded data to disk */
- while((img = vpx_codec_get_frame(&codec, &iter))) {
- unsigned int plane, y;
-
- for(plane=0; plane < 3; plane++) {
- unsigned char *buf =img->planes[plane];
-
- for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
- (void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
- outfile);
- buf += img->stride[plane];
- }
- }
- }
- }
- printf("Processed %d frames.\n",frame_cnt);
- if(vpx_codec_destroy(&codec))
- die_codec(&codec, "Failed to destroy codec");
-
- fclose(outfile);
- fclose(infile);
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
diff --git a/examples/example_xma.c b/examples/example_xma.c
index 0e33ff4..c960c28 100644
--- a/examples/example_xma.c
+++ b/examples/example_xma.c
@@ -27,7 +27,7 @@
static const struct {
const char *name;
- const vpx_codec_iface_t *iface;
+ vpx_codec_iface_t *iface;
} ifaces[] = {
#if CONFIG_VP9_DECODER
{"vp9", &vpx_codec_vp8_dx_algo},
diff --git a/examples/postproc.c b/examples/postproc.c
index 0d0d6b5..4ec2d1f 100644
--- a/examples/postproc.c
+++ b/examples/postproc.c
@@ -39,130 +39,105 @@
// postprocessors. VP8 is one example. The following sample code toggles
// postprocessing on and off every 15 frames.
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#include "./ivfdec.h"
+
#define VPX_CODEC_DISABLE_COMPAT 1
-#include "./vpx_config.h"
+
#include "vpx/vp8dx.h"
#include "vpx/vpx_decoder.h"
-#define interface (vpx_codec_vp8_dx())
+#include "./tools_common.h"
+#include "./vpx_config.h"
-#define IVF_FILE_HDR_SZ (32)
-#define IVF_FRAME_HDR_SZ (12)
+static const char *exec_name;
-static unsigned int mem_get_le32(const unsigned char *mem) {
- return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
+void usage_exit() {
+ fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
+ exit(EXIT_FAILURE);
}
-static void die(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- if(fmt[strlen(fmt)-1] != '\n')
- printf("\n");
- exit(EXIT_FAILURE);
-}
-
-static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
- const char *detail = vpx_codec_error_detail(ctx);
-
- printf("%s: %s\n", s, vpx_codec_error(ctx));
- if(detail)
- printf(" %s\n",detail);
- exit(EXIT_FAILURE);
-}
-
-
int main(int argc, char **argv) {
- FILE *infile, *outfile;
- vpx_codec_ctx_t codec;
- int flags = 0, frame_cnt = 0;
- unsigned char file_hdr[IVF_FILE_HDR_SZ];
- unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
- unsigned char frame[256*1024];
- vpx_codec_err_t res;
+ FILE *infile, *outfile;
+ vpx_codec_ctx_t codec;
+ vpx_codec_iface_t *iface;
+ int frame_cnt = 0;
+ vpx_video_t *video;
+ vpx_codec_err_t res;
- (void)res;
- /* Open files */
- if(argc!=3)
- die("Usage: %s <infile> <outfile>\n", argv[0]);
- if(!(infile = fopen(argv[1], "rb")))
- die("Failed to open %s for reading", argv[1]);
- if(!(outfile = fopen(argv[2], "wb")))
- die("Failed to open %s for writing", argv[2]);
+ exec_name = argv[0];
- /* Read file header */
- if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
- && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
- && file_hdr[3]=='F'))
- die("%s is not an IVF file.", argv[1]);
+ if (argc != 3)
+ die("Invalid number of arguments");
- printf("Using %s\n",vpx_codec_iface_name(interface));
- /* Initialize codec */
- res = vpx_codec_dec_init(&codec, interface, NULL,
- VPX_CODEC_USE_POSTPROC);
- if(res == VPX_CODEC_INCAPABLE) {
- printf("NOTICE: Postproc not supported by %s\n",
- vpx_codec_iface_name(interface));
- res = vpx_codec_dec_init(&codec, interface, NULL, flags);
+ if (!(infile = fopen(argv[1], "rb")))
+ die("Failed to open %s for reading", argv[1]);
+
+ if (!(outfile = fopen(argv[2], "wb")))
+ die("Failed to open %s for writing", argv[2]);
+
+ video = vpx_video_open_file(infile);
+ if (!video)
+ die("%s is not a supported input file.", argv[1]);
+
+ iface = get_codec_interface(vpx_video_get_fourcc(video));
+ if (!iface)
+ die("Unknown FOURCC code.");
+
+ printf("Using %s\n", vpx_codec_iface_name(iface));
+
+
+ res = vpx_codec_dec_init(&codec, iface, NULL, VPX_CODEC_USE_POSTPROC);
+ if (res == VPX_CODEC_INCAPABLE) {
+ printf("NOTICE: Postproc not supported.\n");
+ res = vpx_codec_dec_init(&codec, iface, NULL, 0);
+ }
+
+ if (res)
+ die_codec(&codec, "Failed to initialize decoder");
+
+ while (vpx_video_read_frame(video)) {
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t *img = NULL;
+ size_t frame_size = 0;
+ const unsigned char *frame = vpx_video_get_frame(video, &frame_size);
+
+ ++frame_cnt;
+
+ if (frame_cnt % 30 == 1) {
+ vp8_postproc_cfg_t pp = {0, 0, 0};
+
+ if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
+ die_codec(&codec, "Failed to turn off postproc");
+ } else if (frame_cnt % 30 == 16) {
+ vp8_postproc_cfg_t pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE,
+ 4, 0};
+ if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
+ die_codec(&codec, "Failed to turn on postproc");
+ };
+
+ // Decode the frame with 15ms deadline
+ if (vpx_codec_decode(&codec, frame, frame_size, NULL, 15000))
+ die_codec(&codec, "Failed to decode frame");
+
+ while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
+ vpx_img_write(img, outfile);
}
- if(res)
- die_codec(&codec, "Failed to initialize decoder");
+ }
- /* Read each frame */
- while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
- int frame_sz = mem_get_le32(frame_hdr);
- vpx_codec_iter_t iter = NULL;
- vpx_image_t *img;
+ printf("Processed %d frames.\n", frame_cnt);
+ if (vpx_codec_destroy(&codec))
+ die_codec(&codec, "Failed to destroy codec");
+ printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
+ vpx_video_get_width(video), vpx_video_get_height(video), argv[2]);
- frame_cnt++;
- if(frame_sz > sizeof(frame))
- die("Frame %d data too big for example code buffer", frame_sz);
- if(fread(frame, 1, frame_sz, infile) != frame_sz)
- die("Frame %d failed to read complete frame", frame_cnt);
+ vpx_video_close(video);
- #if CONFIG_VP9_DECODER
- if(frame_cnt%30 == 1) {
- vp8_postproc_cfg_t pp = {0, 0, 0};
-
- if(vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
- die_codec(&codec, "Failed to turn off postproc");
- } else if(frame_cnt%30 == 16) {
- vp8_postproc_cfg_t pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE, 4, 0};
-
- if(vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
- die_codec(&codec, "Failed to turn on postproc");
- };
- #endif
- /* Decode the frame with 15ms deadline */
- if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 15000))
- die_codec(&codec, "Failed to decode frame");
-
- /* Write decoded data to disk */
- while((img = vpx_codec_get_frame(&codec, &iter))) {
- unsigned int plane, y;
-
- for(plane=0; plane < 3; plane++) {
- unsigned char *buf =img->planes[plane];
-
- for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
- (void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
- outfile);
- buf += img->stride[plane];
- }
- }
- }
- }
- printf("Processed %d frames.\n",frame_cnt);
- if(vpx_codec_destroy(&codec))
- die_codec(&codec, "Failed to destroy codec");
-
- fclose(outfile);
- fclose(infile);
- return EXIT_SUCCESS;
+ fclose(outfile);
+ fclose(infile);
+ return EXIT_SUCCESS;
}
diff --git a/examples/simple_decoder.c b/examples/simple_decoder.c
index 17a5987..23399f4 100644
--- a/examples/simple_decoder.c
+++ b/examples/simple_decoder.c
@@ -77,110 +77,82 @@
// few exeptions, vpx_codec functions return an enumerated error status,
// with the value `0` indicating success.
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#define VPX_CODEC_DISABLE_COMPAT 1
-#include "./vpx_config.h"
+
#include "vpx/vp8dx.h"
#include "vpx/vpx_decoder.h"
-#define interface (vpx_codec_vp8_dx())
+#include "./ivfdec.h"
+#include "./tools_common.h"
+#include "./vpx_config.h"
-#define IVF_FILE_HDR_SZ (32)
-#define IVF_FRAME_HDR_SZ (12)
+static const char *exec_name;
-static unsigned int mem_get_le32(const unsigned char *mem) {
- return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
+void usage_exit() {
+ fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
+ exit(EXIT_FAILURE);
}
-static void die(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- if(fmt[strlen(fmt)-1] != '\n')
- printf("\n");
- exit(EXIT_FAILURE);
-}
-
-static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
- const char *detail = vpx_codec_error_detail(ctx);
-
- printf("%s: %s\n", s, vpx_codec_error(ctx));
- if(detail)
- printf(" %s\n",detail);
- exit(EXIT_FAILURE);
-}
-
-
int main(int argc, char **argv) {
- FILE *infile, *outfile;
- vpx_codec_ctx_t codec;
- int flags = 0, frame_cnt = 0;
- unsigned char file_hdr[IVF_FILE_HDR_SZ];
- unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
- unsigned char frame[256*1024];
- vpx_codec_err_t res;
+ FILE *infile, *outfile;
+ vpx_codec_ctx_t codec;
+ vpx_codec_iface_t *iface;
+ int flags = 0, frame_cnt = 0;
+ vpx_video_t *video;
- (void)res;
- /* Open files */
- if(argc!=3)
- die("Usage: %s <infile> <outfile>\n", argv[0]);
- if(!(infile = fopen(argv[1], "rb")))
- die("Failed to open %s for reading", argv[1]);
- if(!(outfile = fopen(argv[2], "wb")))
- die("Failed to open %s for writing", argv[2]);
+ exec_name = argv[0];
- /* Read file header */
- if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
- && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
- && file_hdr[3]=='F'))
- die("%s is not an IVF file.", argv[1]);
+ if (argc != 3)
+ die("Invalid number of arguments");
- printf("Using %s\n",vpx_codec_iface_name(interface));
- /* Initialize codec */
- if(vpx_codec_dec_init(&codec, interface, NULL, flags))
- die_codec(&codec, "Failed to initialize decoder");
+ if (!(infile = fopen(argv[1], "rb")))
+ die("Failed to open %s for reading", argv[1]);
- /* Read each frame */
- while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
- int frame_sz = mem_get_le32(frame_hdr);
- vpx_codec_iter_t iter = NULL;
- vpx_image_t *img;
+ if (!(outfile = fopen(argv[2], "wb")))
+ die("Failed to open %s for writing", argv[2]);
+ video = vpx_video_open_file(infile);
+ if (!video)
+ die("%s is not an IVF file.", argv[1]);
- frame_cnt++;
- if(frame_sz > sizeof(frame))
- die("Frame %d data too big for example code buffer", frame_sz);
- if(fread(frame, 1, frame_sz, infile) != frame_sz)
- die("Frame %d failed to read complete frame", frame_cnt);
+ iface = get_codec_interface(vpx_video_get_fourcc(video));
+ if (!iface)
+ die("Unknown FOURCC code.");
- /* Decode the frame */
- if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
- die_codec(&codec, "Failed to decode frame");
+ printf("Using %s\n", vpx_codec_iface_name(iface));
- /* Write decoded data to disk */
- while((img = vpx_codec_get_frame(&codec, &iter))) {
- unsigned int plane, y;
+ if (vpx_codec_dec_init(&codec, iface, NULL, flags))
+ die_codec(&codec, "Failed to initialize decoder");
- for(plane=0; plane < 3; plane++) {
- unsigned char *buf =img->planes[plane];
+ while (vpx_video_read_frame(video)) {
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t *img = NULL;
+ size_t frame_size = 0;
+ const unsigned char *frame = vpx_video_get_frame(video, &frame_size);
+ if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0))
+ die_codec(&codec, "Failed to decode frame");
- for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
- (void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
- outfile);
- buf += img->stride[plane];
- }
- }
- }
+ while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
+ vpx_img_write(img, outfile);
+ ++frame_cnt;
}
- printf("Processed %d frames.\n",frame_cnt);
- if(vpx_codec_destroy(&codec))
- die_codec(&codec, "Failed to destroy codec");
+ }
- fclose(outfile);
- fclose(infile);
- return EXIT_SUCCESS;
+ printf("Processed %d frames.\n", frame_cnt);
+ if (vpx_codec_destroy(&codec))
+ die_codec(&codec, "Failed to destroy codec");
+
+ printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
+ vpx_video_get_width(video), vpx_video_get_height(video), argv[2]);
+
+ vpx_video_close(video);
+
+ fclose(outfile);
+ fclose(infile);
+
+ return EXIT_SUCCESS;
}
diff --git a/ivfenc.c b/ivfenc.c
index 0041ff0..4a97c42 100644
--- a/ivfenc.c
+++ b/ivfenc.c
@@ -10,7 +10,6 @@
#include "./ivfenc.h"
-#include "./tools_common.h"
#include "vpx/vpx_encoder.h"
#include "vpx_ports/mem_ops.h"
@@ -24,33 +23,31 @@
header[1] = 'K';
header[2] = 'I';
header[3] = 'F';
- mem_put_le16(header + 4, 0); /* version */
- mem_put_le16(header + 6, 32); /* headersize */
- mem_put_le32(header + 8, fourcc); /* four CC */
- mem_put_le16(header + 12, cfg->g_w); /* width */
- mem_put_le16(header + 14, cfg->g_h); /* height */
- mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
- mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
- mem_put_le32(header + 24, frame_cnt); /* length */
- mem_put_le32(header + 28, 0); /* unused */
+ mem_put_le16(header + 4, 0); // version
+ mem_put_le16(header + 6, 32); // header size
+ mem_put_le32(header + 8, fourcc); // fourcc
+ mem_put_le16(header + 12, cfg->g_w); // width
+ mem_put_le16(header + 14, cfg->g_h); // height
+ mem_put_le32(header + 16, cfg->g_timebase.den); // rate
+ mem_put_le32(header + 20, cfg->g_timebase.num); // scale
+ mem_put_le32(header + 24, frame_cnt); // length
+ mem_put_le32(header + 28, 0); // unused
- (void) fwrite(header, 1, 32, outfile);
+ fwrite(header, 1, 32, outfile);
}
-void ivf_write_frame_header(FILE *outfile, const struct vpx_codec_cx_pkt *pkt) {
+void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) {
char header[12];
- vpx_codec_pts_t pts;
- pts = pkt->data.frame.pts;
- mem_put_le32(header, (int)pkt->data.frame.sz);
- mem_put_le32(header + 4, pts & 0xFFFFFFFF);
- mem_put_le32(header + 8, pts >> 32);
-
- (void) fwrite(header, 1, 12, outfile);
+ mem_put_le32(header, (int)frame_size);
+ mem_put_le32(header + 4, (int)(pts & 0xFFFFFFFF));
+ mem_put_le32(header + 8, (int)(pts >> 32));
+ fwrite(header, 1, 12, outfile);
}
-void ivf_write_frame_size(FILE *outfile, size_t size) {
+void ivf_write_frame_size(FILE *outfile, size_t frame_size) {
char header[4];
- mem_put_le32(header, (int)size);
- (void) fwrite(header, 1, 4, outfile);
+
+ mem_put_le32(header, (int)frame_size);
+ fwrite(header, 1, 4, outfile);
}
diff --git a/ivfenc.h b/ivfenc.h
index b486bc8..6623687 100644
--- a/ivfenc.h
+++ b/ivfenc.h
@@ -23,8 +23,10 @@
const struct vpx_codec_enc_cfg *cfg,
uint32_t fourcc,
int frame_cnt);
-void ivf_write_frame_header(FILE *outfile, const struct vpx_codec_cx_pkt *pkt);
-void ivf_write_frame_size(FILE *outfile, size_t size);
+
+void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size);
+
+void ivf_write_frame_size(FILE *outfile, size_t frame_size);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/libs.mk b/libs.mk
index 470066a..cc40451 100644
--- a/libs.mk
+++ b/libs.mk
@@ -214,8 +214,11 @@
ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
ifeq ($(CONFIG_MSVS),yes)
+obj_int_extract.bat: $(SRC_PATH_BARE)/build/$(MSVS_ARCH_DIR)/obj_int_extract.bat
+ @cp $^ $@
+
+obj_int_extract.$(VCPROJ_SFX): obj_int_extract.bat
obj_int_extract.$(VCPROJ_SFX): $(SRC_PATH_BARE)/build/make/obj_int_extract.c
- @cp $(SRC_PATH_BARE)/build/$(MSVS_ARCH_DIR)/obj_int_extract.bat .
@echo " [CREATE] $@"
$(qexec)$(GEN_VCPROJ) \
--exe \
diff --git a/rate_hist.c b/rate_hist.c
new file mode 100644
index 0000000..1cef19b
--- /dev/null
+++ b/rate_hist.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "./rate_hist.h"
+
+#define RATE_BINS 100
+#define HIST_BAR_MAX 40
+
+struct hist_bucket {
+ int low;
+ int high;
+ int count;
+};
+
+struct rate_hist {
+ int64_t *pts;
+ int *sz;
+ int samples;
+ int frames;
+ struct hist_bucket bucket[RATE_BINS];
+ int total;
+};
+
+struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
+ const vpx_rational_t *fps) {
+ int i;
+ struct rate_hist *hist = malloc(sizeof(*hist));
+
+ // Determine the number of samples in the buffer. Use the file's framerate
+ // to determine the number of frames in rc_buf_sz milliseconds, with an
+ // adjustment (5/4) to account for alt-refs
+ hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
+
+ // prevent division by zero
+ if (hist->samples == 0)
+ hist->samples = 1;
+
+ hist->frames = 0;
+ hist->total = 0;
+
+ hist->pts = calloc(hist->samples, sizeof(*hist->pts));
+ hist->sz = calloc(hist->samples, sizeof(*hist->sz));
+ for (i = 0; i < RATE_BINS; i++) {
+ hist->bucket[i].low = INT_MAX;
+ hist->bucket[i].high = 0;
+ hist->bucket[i].count = 0;
+ }
+
+ return hist;
+}
+
+void destroy_rate_histogram(struct rate_hist *hist) {
+ if (hist) {
+ free(hist->pts);
+ free(hist->sz);
+ free(hist);
+ }
+}
+
+void update_rate_histogram(struct rate_hist *hist,
+ const vpx_codec_enc_cfg_t *cfg,
+ const vpx_codec_cx_pkt_t *pkt) {
+ int i;
+ int64_t then = 0;
+ int64_t avg_bitrate = 0;
+ int64_t sum_sz = 0;
+ const int64_t now = pkt->data.frame.pts * 1000 *
+ (uint64_t)cfg->g_timebase.num /
+ (uint64_t)cfg->g_timebase.den;
+
+ int idx = hist->frames++ % hist->samples;
+ hist->pts[idx] = now;
+ hist->sz[idx] = (int)pkt->data.frame.sz;
+
+ if (now < cfg->rc_buf_initial_sz)
+ return;
+
+ then = now;
+
+ /* Sum the size over the past rc_buf_sz ms */
+ for (i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--) {
+ const int i_idx = (i - 1) % hist->samples;
+
+ then = hist->pts[i_idx];
+ if (now - then > cfg->rc_buf_sz)
+ break;
+ sum_sz += hist->sz[i_idx];
+ }
+
+ if (now == then)
+ return;
+
+ avg_bitrate = sum_sz * 8 * 1000 / (now - then);
+ idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000));
+ if (idx < 0)
+ idx = 0;
+ if (idx > RATE_BINS - 1)
+ idx = RATE_BINS - 1;
+ if (hist->bucket[idx].low > avg_bitrate)
+ hist->bucket[idx].low = (int)avg_bitrate;
+ if (hist->bucket[idx].high < avg_bitrate)
+ hist->bucket[idx].high = (int)avg_bitrate;
+ hist->bucket[idx].count++;
+ hist->total++;
+}
+
+static int merge_hist_buckets(struct hist_bucket *bucket,
+ int max_buckets, int *num_buckets) {
+ int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
+ int buckets = *num_buckets;
+ int i;
+
+ /* Find the extrema for this list of buckets */
+ big_bucket = small_bucket = 0;
+ for (i = 0; i < buckets; i++) {
+ if (bucket[i].count < bucket[small_bucket].count)
+ small_bucket = i;
+ if (bucket[i].count > bucket[big_bucket].count)
+ big_bucket = i;
+ }
+
+ /* If we have too many buckets, merge the smallest with an adjacent
+ * bucket.
+ */
+ while (buckets > max_buckets) {
+ int last_bucket = buckets - 1;
+
+ /* merge the small bucket with an adjacent one. */
+ if (small_bucket == 0)
+ merge_bucket = 1;
+ else if (small_bucket == last_bucket)
+ merge_bucket = last_bucket - 1;
+ else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
+ merge_bucket = small_bucket - 1;
+ else
+ merge_bucket = small_bucket + 1;
+
+ assert(abs(merge_bucket - small_bucket) <= 1);
+ assert(small_bucket < buckets);
+ assert(big_bucket < buckets);
+ assert(merge_bucket < buckets);
+
+ if (merge_bucket < small_bucket) {
+ bucket[merge_bucket].high = bucket[small_bucket].high;
+ bucket[merge_bucket].count += bucket[small_bucket].count;
+ } else {
+ bucket[small_bucket].high = bucket[merge_bucket].high;
+ bucket[small_bucket].count += bucket[merge_bucket].count;
+ merge_bucket = small_bucket;
+ }
+
+ assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
+
+ buckets--;
+
+ /* Remove the merge_bucket from the list, and find the new small
+ * and big buckets while we're at it
+ */
+ big_bucket = small_bucket = 0;
+ for (i = 0; i < buckets; i++) {
+ if (i > merge_bucket)
+ bucket[i] = bucket[i + 1];
+
+ if (bucket[i].count < bucket[small_bucket].count)
+ small_bucket = i;
+ if (bucket[i].count > bucket[big_bucket].count)
+ big_bucket = i;
+ }
+ }
+
+ *num_buckets = buckets;
+ return bucket[big_bucket].count;
+}
+
+static void show_histogram(const struct hist_bucket *bucket,
+ int buckets, int total, int scale) {
+ const char *pat1, *pat2;
+ int i;
+
+ switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) {
+ case 1:
+ case 2:
+ pat1 = "%4d %2s: ";
+ pat2 = "%4d-%2d: ";
+ break;
+ case 3:
+ pat1 = "%5d %3s: ";
+ pat2 = "%5d-%3d: ";
+ break;
+ case 4:
+ pat1 = "%6d %4s: ";
+ pat2 = "%6d-%4d: ";
+ break;
+ case 5:
+ pat1 = "%7d %5s: ";
+ pat2 = "%7d-%5d: ";
+ break;
+ case 6:
+ pat1 = "%8d %6s: ";
+ pat2 = "%8d-%6d: ";
+ break;
+ case 7:
+ pat1 = "%9d %7s: ";
+ pat2 = "%9d-%7d: ";
+ break;
+ default:
+ pat1 = "%12d %10s: ";
+ pat2 = "%12d-%10d: ";
+ break;
+ }
+
+ for (i = 0; i < buckets; i++) {
+ int len;
+ int j;
+ float pct;
+
+ pct = (float)(100.0 * bucket[i].count / total);
+ len = HIST_BAR_MAX * bucket[i].count / scale;
+ if (len < 1)
+ len = 1;
+ assert(len <= HIST_BAR_MAX);
+
+ if (bucket[i].low == bucket[i].high)
+ fprintf(stderr, pat1, bucket[i].low, "");
+ else
+ fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
+
+ for (j = 0; j < HIST_BAR_MAX; j++)
+ fprintf(stderr, j < len ? "=" : " ");
+ fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
+ }
+}
+
+void show_q_histogram(const int counts[64], int max_buckets) {
+ struct hist_bucket bucket[64];
+ int buckets = 0;
+ int total = 0;
+ int scale;
+ int i;
+
+ for (i = 0; i < 64; i++) {
+ if (counts[i]) {
+ bucket[buckets].low = bucket[buckets].high = i;
+ bucket[buckets].count = counts[i];
+ buckets++;
+ total += counts[i];
+ }
+ }
+
+ fprintf(stderr, "\nQuantizer Selection:\n");
+ scale = merge_hist_buckets(bucket, max_buckets, &buckets);
+ show_histogram(bucket, buckets, total, scale);
+}
+
+void show_rate_histogram(struct rate_hist *hist,
+ const vpx_codec_enc_cfg_t *cfg, int max_buckets) {
+ int i, scale;
+ int buckets = 0;
+
+ for (i = 0; i < RATE_BINS; i++) {
+ if (hist->bucket[i].low == INT_MAX)
+ continue;
+ hist->bucket[buckets++] = hist->bucket[i];
+ }
+
+ fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
+ scale = merge_hist_buckets(hist->bucket, max_buckets, &buckets);
+ show_histogram(hist->bucket, buckets, hist->total, scale);
+}
diff --git a/rate_hist.h b/rate_hist.h
new file mode 100644
index 0000000..00a1676
--- /dev/null
+++ b/rate_hist.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#ifndef RATE_HIST_H_
+#define RATE_HIST_H_
+
+#include "vpx/vpx_encoder.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rate_hist;
+
+struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
+ const vpx_rational_t *fps);
+
+void destroy_rate_histogram(struct rate_hist *hist);
+
+void update_rate_histogram(struct rate_hist *hist,
+ const vpx_codec_enc_cfg_t *cfg,
+ const vpx_codec_cx_pkt_t *pkt);
+
+void show_q_histogram(const int counts[64], int max_buckets);
+
+void show_rate_histogram(struct rate_hist *hist, const vpx_codec_enc_cfg_t *cfg,
+ int max_buckets);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // RATE_HIST_H_
diff --git a/test/codec_factory.h b/test/codec_factory.h
index 38c4d29..80e87c8 100644
--- a/test/codec_factory.h
+++ b/test/codec_factory.h
@@ -71,7 +71,7 @@
: Decoder(cfg, deadline) {}
protected:
- virtual const vpx_codec_iface_t* CodecInterface() const {
+ virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP8_DECODER
return &vpx_codec_vp8_dx_algo;
#else
@@ -87,7 +87,7 @@
: Encoder(cfg, deadline, init_flags, stats) {}
protected:
- virtual const vpx_codec_iface_t* CodecInterface() const {
+ virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP8_ENCODER
return &vpx_codec_vp8_cx_algo;
#else
@@ -153,7 +153,7 @@
: Decoder(cfg, deadline) {}
protected:
- virtual const vpx_codec_iface_t* CodecInterface() const {
+ virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP9_DECODER
return &vpx_codec_vp9_dx_algo;
#else
@@ -169,7 +169,7 @@
: Encoder(cfg, deadline, init_flags, stats) {}
protected:
- virtual const vpx_codec_iface_t* CodecInterface() const {
+ virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP9_ENCODER
return &vpx_codec_vp9_cx_algo;
#else
diff --git a/test/decode_test_driver.h b/test/decode_test_driver.h
index ddaed9f..3e8ff72 100644
--- a/test/decode_test_driver.h
+++ b/test/decode_test_driver.h
@@ -77,7 +77,7 @@
}
protected:
- virtual const vpx_codec_iface_t* CodecInterface() const = 0;
+ virtual vpx_codec_iface_t* CodecInterface() const = 0;
void InitOnce() {
if (!init_done_) {
diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h
index dbdc33c..4dabcd5 100644
--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -128,7 +128,7 @@
}
protected:
- virtual const vpx_codec_iface_t* CodecInterface() const = 0;
+ virtual vpx_codec_iface_t* CodecInterface() const = 0;
const char *EncoderError() {
const char *detail = vpx_codec_error_detail(&encoder_);
diff --git a/test/i420_video_source.h b/test/i420_video_source.h
index 2bf2a03..c3315f9 100644
--- a/test/i420_video_source.h
+++ b/test/i420_video_source.h
@@ -52,7 +52,7 @@
ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
<< file_name_;
if (start_) {
- fseek(input_file_, raw_sz_ * start_, SEEK_SET);
+ fseek(input_file_, static_cast<unsigned>(raw_sz_) * start_, SEEK_SET);
}
frame_ = start_;
diff --git a/test/resize_test.cc b/test/resize_test.cc
index 1963453..8d08f1e 100644
--- a/test/resize_test.cc
+++ b/test/resize_test.cc
@@ -146,16 +146,16 @@
ResizingVideoSource video;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- for (std::vector<FrameInfo>::iterator info = frame_info_list_.begin();
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) {
- const vpx_codec_pts_t pts = info->pts;
- const unsigned int expected_w = ScaleForFrameNumber(pts, kInitialWidth);
- const unsigned int expected_h = ScaleForFrameNumber(pts, kInitialHeight);
+ const unsigned int frame = static_cast<unsigned>(info->pts);
+ const unsigned int expected_w = ScaleForFrameNumber(frame, kInitialWidth);
+ const unsigned int expected_h = ScaleForFrameNumber(frame, kInitialHeight);
EXPECT_EQ(expected_w, info->w)
- << "Frame " << pts << "had unexpected width";
+ << "Frame " << frame << "had unexpected width";
EXPECT_EQ(expected_h, info->h)
- << "Frame " << pts << "had unexpected height";
+ << "Frame " << frame << "had unexpected height";
}
}
@@ -247,7 +247,7 @@
cfg_.g_lag_in_frames = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- for (std::vector<FrameInfo>::iterator info = frame_info_list_.begin();
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) {
const vpx_codec_pts_t pts = info->pts;
if (pts >= kStepDownFrame && pts < kStepUpFrame) {
diff --git a/test/subtract_test.cc b/test/subtract_test.cc
index 3211c5c..9e242a2 100644
--- a/test/subtract_test.cc
+++ b/test/subtract_test.cc
@@ -59,7 +59,7 @@
int16_t *src_diff = be.src_diff;
for (int r = 0; r < kBlockHeight; ++r) {
for (int c = 0; c < kBlockWidth; ++c) {
- src_diff[c] = static_cast<int16_t>(0xa5a5);
+ src_diff[c] = static_cast<int16_t>(0xa5a5u);
}
src_diff += kDiffPredStride;
}
diff --git a/test/svc_test.cc b/test/svc_test.cc
index 3ddd9c1..75659d5 100644
--- a/test/svc_test.cc
+++ b/test/svc_test.cc
@@ -234,7 +234,7 @@
video.Begin();
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
- video.duration(), VPX_DL_REALTIME);
+ video.duration(), VPX_DL_GOOD_QUALITY);
EXPECT_EQ(VPX_CODEC_OK, res);
const vpx_codec_err_t res_dec = decoder_->DecodeFrame(
@@ -262,7 +262,7 @@
video.Begin();
// This frame is a keyframe.
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
- video.duration(), VPX_DL_REALTIME);
+ video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
@@ -275,7 +275,7 @@
video.Next();
// This is a P-frame.
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
- video.duration(), VPX_DL_REALTIME);
+ video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
@@ -288,7 +288,7 @@
video.Next();
// This is a P-frame.
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
- video.duration(), VPX_DL_REALTIME);
+ video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
diff --git a/test/test-data.sha1 b/test/test-data.sha1
index 6daf69e..a287731 100644
--- a/test/test-data.sha1
+++ b/test/test-data.sha1
@@ -574,3 +574,5 @@
84c1599298aac78f2fc05ae2274575d10569dfa0 vp90-2-09-aq2.webm.md5
55fc55ed73d578ed60fad05692579873f8bad758 vp90-2-09-lf_deltas.webm
54638c38009198c38c8f3b25c182b709b6c1fd2e vp90-2-09-lf_deltas.webm.md5
+510d95f3beb3b51c572611fdaeeece12277dac30 vp90-2-10-show-existing-frame.webm
+14d631096f4bfa2d71f7f739aec1448fb3c33bad vp90-2-10-show-existing-frame.webm.md5
diff --git a/test/test.mk b/test/test.mk
index cb62615..a65decf 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -676,6 +676,8 @@
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm.md5
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yv444.webm
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yv444.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm.md5
ifeq ($(CONFIG_DECODE_PERF_TESTS),yes)
# BBB VP9 streams
diff --git a/test/test_vector_test.cc b/test/test_vector_test.cc
index 4adf9af..53b7636 100644
--- a/test/test_vector_test.cc
+++ b/test/test_vector_test.cc
@@ -35,7 +35,7 @@
void OpenMD5File(const std::string& md5_file_name_) {
md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
- ASSERT_TRUE(md5_file_) << "Md5 file open failed. Filename: "
+ ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: "
<< md5_file_name_;
}
diff --git a/test/test_vectors.cc b/test/test_vectors.cc
index 16298d0..3227f52 100644
--- a/test/test_vectors.cc
+++ b/test/test_vectors.cc
@@ -160,6 +160,7 @@
"vp90-2-02-size-lf-1920x1080.webm",
"vp90-2-09-aq2.webm",
"vp90-2-09-lf_deltas.webm",
+ "vp90-2-10-show-existing-frame.webm",
#if CONFIG_NON420
"vp91-2-04-yv444.webm"
#endif
diff --git a/test/test_vectors.h b/test/test_vectors.h
index 5f62e99..eb592de 100644
--- a/test/test_vectors.h
+++ b/test/test_vectors.h
@@ -22,9 +22,9 @@
#if CONFIG_VP9_DECODER
#if CONFIG_NON420
-const int kNumVp9TestVectors = 216;
+const int kNumVp9TestVectors = 217;
#else
-const int kNumVp9TestVectors = 215;
+const int kNumVp9TestVectors = 216;
#endif
extern const char *kVP9TestVectors[kNumVp9TestVectors];
diff --git a/test/vp8_boolcoder_test.cc b/test/vp8_boolcoder_test.cc
index fa7ee6e..7c6c601 100644
--- a/test/vp8_boolcoder_test.cc
+++ b/test/vp8_boolcoder_test.cc
@@ -43,7 +43,7 @@
void test_decrypt_cb(void *decrypt_state, const uint8_t *input,
uint8_t *output, int count) {
- int offset = input - reinterpret_cast<uint8_t *>(decrypt_state);
+ const size_t offset = input - reinterpret_cast<uint8_t*>(decrypt_state);
for (int i = 0; i < count; i++) {
output[i] = input[i] ^ secret_key[(offset + i) & 15];
}
diff --git a/third_party/libmkv/EbmlBufferWriter.c b/third_party/libmkv/EbmlBufferWriter.c
index 574e478..116cbc4 100644
--- a/third_party/libmkv/EbmlBufferWriter.c
+++ b/third_party/libmkv/EbmlBufferWriter.c
@@ -18,8 +18,6 @@
static void _Serialize(EbmlGlobal *glob, const unsigned char *p, const unsigned char *q) {
while (q != p) {
--q;
-
- unsigned long cbWritten;
memcpy(&(glob->buf[glob->offset]), q, 1);
glob->offset++;
}
diff --git a/third_party/libmkv/WebMElement.c b/third_party/libmkv/WebMElement.c
index 2f79a3c..6c3670a 100644
--- a/third_party/libmkv/WebMElement.c
+++ b/third_party/libmkv/WebMElement.c
@@ -11,6 +11,7 @@
#include "EbmlIDs.h"
#include "WebMElement.h"
#include <stdio.h>
+#include "vpx/vpx_integer.h"
#define kVorbisPrivateMaxSize 4000
@@ -43,22 +44,23 @@
Ebml_Write(glob, data, dataLength);
}
-static UInt64 generateTrackID(unsigned int trackNumber) {
- UInt64 t = time(NULL) * trackNumber;
- UInt64 r = rand();
+static uint64_t generateTrackID(unsigned int trackNumber) {
+ uint64_t t = time(NULL) * trackNumber;
+ uint64_t r = rand();
r = r << 32;
r += rand();
- UInt64 rval = t ^ r;
+ uint64_t rval = t ^ r;
return rval;
}
-void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
- char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber,
+ int flagLacing, const char *codecId,
+ unsigned int pixelWidth, unsigned int pixelHeight,
double frameRate) {
EbmlLoc start;
Ebml_StartSubElement(glob, &start, TrackEntry);
Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
- UInt64 trackID = generateTrackID(trackNumber);
+ uint64_t trackID = generateTrackID(trackNumber);
Ebml_SerializeUnsigned(glob, TrackUID, trackID);
Ebml_SerializeString(glob, CodecName, "VP8"); // TODO shouldn't be fixed
@@ -74,13 +76,14 @@
}
Ebml_EndSubElement(glob, &start); // Track Entry
}
-void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
- char *codecId, double samplingFrequency, unsigned int channels,
+void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber,
+ int flagLacing, const char *codecId,
+ double samplingFrequency, unsigned int channels,
unsigned char *private, unsigned long privateSize) {
EbmlLoc start;
Ebml_StartSubElement(glob, &start, TrackEntry);
Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
- UInt64 trackID = generateTrackID(trackNumber);
+ uint64_t trackID = generateTrackID(trackNumber);
Ebml_SerializeUnsigned(glob, TrackUID, trackID);
Ebml_SerializeUnsigned(glob, TrackType, 2); // audio is always 2
// I am using defaults for thesed required fields
diff --git a/third_party/libmkv/WebMElement.h b/third_party/libmkv/WebMElement.h
index d9ad0a0..0e5ec20 100644
--- a/third_party/libmkv/WebMElement.h
+++ b/third_party/libmkv/WebMElement.h
@@ -10,26 +10,23 @@
#ifndef MKV_CONTEXT_HPP
#define MKV_CONTEXT_HPP 1
-void writeSimpleBock(EbmlGlobal *ebml, unsigned char trackNumber, unsigned short timeCode,
- int isKeyframe, unsigned char lacingFlag, int discardable,
- unsigned char *data, unsigned long dataLength);
-
-
// these are helper functions
void writeHeader(EbmlGlobal *ebml);
-void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long timeCodeScale, double duration);
+void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo,
+ unsigned long timeCodeScale, double duration);
// this function is a helper only, it assumes a lot of defaults
-void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
- char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber,
+ int flagLacing, const char *codecId,
+ unsigned int pixelWidth, unsigned int pixelHeight,
double frameRate);
-void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
- char *codecId, double samplingFrequency, unsigned int channels,
+void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber,
+ int flagLacing, const char *codecId,
+ double samplingFrequency, unsigned int channels,
unsigned char *private, unsigned long privateSize);
-void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
- int isKeyframe, unsigned char lacingFlag, int discardable,
+void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber,
+ short timeCode, int isKeyframe,
+ unsigned char lacingFlag, int discardable,
unsigned char *data, unsigned long dataLength);
-
-
-#endif
\ No newline at end of file
+#endif
diff --git a/tools/diff.py b/tools/diff.py
index a42a4dc..a96c7db 100644
--- a/tools/diff.py
+++ b/tools/diff.py
@@ -56,6 +56,9 @@
elif line[0] == " ":
self.left.Append(line)
self.right.Append(line)
+ elif line[0] == "\\":
+ # Ignore newline messages from git diff.
+ pass
else:
assert False, ("Unrecognized character at start of diff line "
"%r" % line[0])
diff --git a/tools_common.c b/tools_common.c
index 9c24983..85bedc9 100644
--- a/tools_common.c
+++ b/tools_common.c
@@ -15,6 +15,10 @@
#include <stdlib.h>
#include <string.h>
+#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
+#include "vpx/vp8dx.h"
+#endif
+
#if defined(_WIN32) || defined(__OS2__)
#include <io.h>
#include <fcntl.h>
@@ -60,6 +64,15 @@
LOG_ERROR("Warning");
}
+void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
+ const char *detail = vpx_codec_error_detail(ctx);
+
+ printf("%s: %s\n", s, vpx_codec_error(ctx));
+ if (detail)
+ printf(" %s\n", detail);
+ exit(EXIT_FAILURE);
+}
+
uint16_t mem_get_le16(const void *data) {
uint16_t val;
const uint8_t *mem = (const uint8_t*)data;
@@ -130,3 +143,34 @@
return shortread;
}
+
+vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) {
+ switch (fourcc) {
+#if CONFIG_VP8_DECODER
+ case VP8_FOURCC:
+ return vpx_codec_vp8_dx();
+#endif
+#if CONFIG_VP9_DECODER
+ case VP9_FOURCC:
+ return vpx_codec_vp9_dx();
+#endif
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
+void vpx_img_write(const vpx_image_t *img, FILE *file) {
+ int plane, y;
+
+ for (plane = 0; plane < 3; ++plane) {
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = plane ? (img->d_w + 1) >> 1 : img->d_w;
+ const int h = plane ? (img->d_h + 1) >> 1 : img->d_h;
+ for (y = 0; y < h; ++y) {
+ fwrite(buf, 1, w, file);
+ buf += stride;
+ }
+ }
+}
diff --git a/tools_common.h b/tools_common.h
index 1d70ab5..967b7a1 100644
--- a/tools_common.h
+++ b/tools_common.h
@@ -13,6 +13,7 @@
#include <stdio.h>
#include "./vpx_config.h"
+#include "vpx/vpx_codec.h"
#include "vpx/vpx_image.h"
#include "vpx/vpx_integer.h"
@@ -112,6 +113,8 @@
void fatal(const char *fmt, ...);
void warn(const char *fmt, ...);
+void die_codec(vpx_codec_ctx_t *ctx, const char *s);
+
/* The tool including this file must define usage_exit() */
void usage_exit();
@@ -120,6 +123,12 @@
int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame);
+vpx_codec_iface_t *get_codec_interface(unsigned int fourcc);
+
+// TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
+// of vpx_image_t support
+void vpx_img_write(const vpx_image_t *img, FILE *file);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
index 19e9d270..ce789e2 100644
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -414,7 +414,6 @@
printf("Sharpness: %d\n", oxcf->Sharpness);
printf("cpu_used: %d\n", oxcf->cpu_used);
printf("Mode: %d\n", oxcf->Mode);
- printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file);
printf("auto_key: %d\n", oxcf->auto_key);
printf("key_freq: %d\n", oxcf->key_freq);
printf("end_usage: %d\n", oxcf->end_usage);
@@ -751,9 +750,6 @@
if (!ctx->cfg.rc_target_bitrate)
return res;
- if (!ctx->cfg.rc_target_bitrate)
- return res;
-
if (img)
res = validate_img(ctx, img);
@@ -1266,7 +1262,6 @@
128, /* kf_max_dist */
#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
- 1, /* g_delete_first_pass_file */
"vp8.fpf" /* first pass filename */
#endif
VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
diff --git a/vp9/common/arm/neon/vp9_short_idct16x16_1_add_neon.asm b/vp9/common/arm/neon/vp9_idct16x16_1_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct16x16_1_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct16x16_1_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_idct16x16_add_neon.asm b/vp9/common/arm/neon/vp9_idct16x16_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct16x16_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct16x16_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_idct32x32_1_add_neon.asm b/vp9/common/arm/neon/vp9_idct32x32_1_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct32x32_1_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct32x32_1_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_idct32x32_add_neon.asm b/vp9/common/arm/neon/vp9_idct32x32_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct32x32_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct32x32_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_idct4x4_1_add_neon.asm b/vp9/common/arm/neon/vp9_idct4x4_1_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct4x4_1_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct4x4_1_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_idct4x4_add_neon.asm b/vp9/common/arm/neon/vp9_idct4x4_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct4x4_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct4x4_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_idct8x8_1_add_neon.asm b/vp9/common/arm/neon/vp9_idct8x8_1_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct8x8_1_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct8x8_1_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_idct8x8_add_neon.asm b/vp9/common/arm/neon/vp9_idct8x8_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_idct8x8_add_neon.asm
rename to vp9/common/arm/neon/vp9_idct8x8_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_iht4x4_add_neon.asm b/vp9/common/arm/neon/vp9_iht4x4_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_iht4x4_add_neon.asm
rename to vp9/common/arm/neon/vp9_iht4x4_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_short_iht8x8_add_neon.asm b/vp9/common/arm/neon/vp9_iht8x8_add_neon.asm
similarity index 100%
rename from vp9/common/arm/neon/vp9_short_iht8x8_add_neon.asm
rename to vp9/common/arm/neon/vp9_iht8x8_add_neon.asm
diff --git a/vp9/common/arm/neon/vp9_reconintra_neon.asm b/vp9/common/arm/neon/vp9_reconintra_neon.asm
index baa943b..4a49964 100644
--- a/vp9/common/arm/neon/vp9_reconintra_neon.asm
+++ b/vp9/common/arm/neon/vp9_reconintra_neon.asm
@@ -19,6 +19,7 @@
EXPORT |vp9_tm_predictor_4x4_neon|
EXPORT |vp9_tm_predictor_8x8_neon|
EXPORT |vp9_tm_predictor_16x16_neon|
+ EXPORT |vp9_tm_predictor_32x32_neon|
ARM
REQUIRE8
PRESERVE8
@@ -348,7 +349,7 @@
vdup.u8 d0, r12
; preload 8 left
- vld1.8 d30, [r3]
+ vld1.8 {d30}, [r3]
; Load above 8 pixels
vld1.64 {d2}, [r2]
@@ -421,10 +422,10 @@
vdup.u8 q0, r12
; Load above 8 pixels
- vld1.8 q1, [r2]
+ vld1.8 {q1}, [r2]
; preload 8 left into r12
- vld1.8 d18, [r3]!
+ vld1.8 {d18}, [r3]!
; Compute above - ytop_left
vsubl.u8 q2, d2, d0
@@ -491,7 +492,7 @@
vqshrun.s16 d23, q8, #0
vdup.16 q0, d20[2]
vdup.16 q8, d20[3]
- vld1.8 d18, [r3]! ; preload 8 left into r12
+ vld1.8 {d18}, [r3]! ; preload 8 left into r12
vmovl.u8 q10, d18
vst1.64 {d2,d3}, [r0], r1
vst1.64 {d22,d23}, [r0], r1
@@ -502,4 +503,134 @@
bx lr
ENDP ; |vp9_tm_predictor_16x16_neon|
+;void vp9_tm_predictor_32x32_neon (uint8_t *dst, ptrdiff_t y_stride,
+; const uint8_t *above,
+; const uint8_t *left)
+; r0 uint8_t *dst
+; r1 ptrdiff_t y_stride
+; r2 const uint8_t *above
+; r3 const uint8_t *left
+
+|vp9_tm_predictor_32x32_neon| PROC
+ ; Load ytop_left = above[-1];
+ sub r12, r2, #1
+ ldrb r12, [r12]
+ vdup.u8 q0, r12
+
+ ; Load above 32 pixels
+ vld1.8 {q1}, [r2]!
+ vld1.8 {q2}, [r2]
+
+ ; preload 8 left pixels
+ vld1.8 {d26}, [r3]!
+
+ ; Compute above - ytop_left
+ vsubl.u8 q8, d2, d0
+ vsubl.u8 q9, d3, d1
+ vsubl.u8 q10, d4, d0
+ vsubl.u8 q11, d5, d1
+
+ vmovl.u8 q3, d26
+
+ ; Load left row by row and compute left + (above - ytop_left)
+ ; Process 8 rows in each single loop and loop 4 times to process 32 rows.
+ mov r2, #4
+
+loop_32x32_neon
+ ; Process two rows.
+ vdup.16 q0, d6[0]
+ vdup.16 q2, d6[1]
+ vadd.s16 q12, q0, q8
+ vadd.s16 q13, q0, q9
+ vadd.s16 q14, q0, q10
+ vadd.s16 q15, q0, q11
+ vqshrun.s16 d0, q12, #0
+ vqshrun.s16 d1, q13, #0
+ vadd.s16 q12, q2, q8
+ vadd.s16 q13, q2, q9
+ vqshrun.s16 d2, q14, #0
+ vqshrun.s16 d3, q15, #0
+ vadd.s16 q14, q2, q10
+ vadd.s16 q15, q2, q11
+ vst1.64 {d0-d3}, [r0], r1
+ vqshrun.s16 d24, q12, #0
+ vqshrun.s16 d25, q13, #0
+ vqshrun.s16 d26, q14, #0
+ vqshrun.s16 d27, q15, #0
+ vdup.16 q1, d6[2]
+ vdup.16 q2, d6[3]
+ vst1.64 {d24-d27}, [r0], r1
+
+ ; Process two rows.
+ vadd.s16 q12, q1, q8
+ vadd.s16 q13, q1, q9
+ vadd.s16 q14, q1, q10
+ vadd.s16 q15, q1, q11
+ vqshrun.s16 d0, q12, #0
+ vqshrun.s16 d1, q13, #0
+ vadd.s16 q12, q2, q8
+ vadd.s16 q13, q2, q9
+ vqshrun.s16 d2, q14, #0
+ vqshrun.s16 d3, q15, #0
+ vadd.s16 q14, q2, q10
+ vadd.s16 q15, q2, q11
+ vst1.64 {d0-d3}, [r0], r1
+ vqshrun.s16 d24, q12, #0
+ vqshrun.s16 d25, q13, #0
+ vqshrun.s16 d26, q14, #0
+ vqshrun.s16 d27, q15, #0
+ vdup.16 q0, d7[0]
+ vdup.16 q2, d7[1]
+ vst1.64 {d24-d27}, [r0], r1
+
+ ; Process two rows.
+ vadd.s16 q12, q0, q8
+ vadd.s16 q13, q0, q9
+ vadd.s16 q14, q0, q10
+ vadd.s16 q15, q0, q11
+ vqshrun.s16 d0, q12, #0
+ vqshrun.s16 d1, q13, #0
+ vadd.s16 q12, q2, q8
+ vadd.s16 q13, q2, q9
+ vqshrun.s16 d2, q14, #0
+ vqshrun.s16 d3, q15, #0
+ vadd.s16 q14, q2, q10
+ vadd.s16 q15, q2, q11
+ vst1.64 {d0-d3}, [r0], r1
+ vqshrun.s16 d24, q12, #0
+ vqshrun.s16 d25, q13, #0
+ vqshrun.s16 d26, q14, #0
+ vqshrun.s16 d27, q15, #0
+ vdup.16 q0, d7[2]
+ vdup.16 q2, d7[3]
+ vst1.64 {d24-d27}, [r0], r1
+
+ ; Process two rows.
+ vadd.s16 q12, q0, q8
+ vadd.s16 q13, q0, q9
+ vadd.s16 q14, q0, q10
+ vadd.s16 q15, q0, q11
+ vqshrun.s16 d0, q12, #0
+ vqshrun.s16 d1, q13, #0
+ vadd.s16 q12, q2, q8
+ vadd.s16 q13, q2, q9
+ vqshrun.s16 d2, q14, #0
+ vqshrun.s16 d3, q15, #0
+ vadd.s16 q14, q2, q10
+ vadd.s16 q15, q2, q11
+ vst1.64 {d0-d3}, [r0], r1
+ vqshrun.s16 d24, q12, #0
+ vqshrun.s16 d25, q13, #0
+ vld1.8 {d0}, [r3]! ; preload 8 left pixels
+ vqshrun.s16 d26, q14, #0
+ vqshrun.s16 d27, q15, #0
+ vmovl.u8 q3, d0
+ vst1.64 {d24-d27}, [r0], r1
+
+ subs r2, r2, #1
+ bgt loop_32x32_neon
+
+ bx lr
+ ENDP ; |vp9_tm_predictor_32x32_neon|
+
END
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index ada7c6c..e033fbb 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -34,7 +34,7 @@
int i;
for (i = 0; i < FRAME_BUFFERS; i++)
- vp9_free_frame_buffer(&cm->yv12_fb[i]);
+ vp9_free_frame_buffer(&cm->frame_bufs[i].buf);
vp9_free_frame_buffer(&cm->post_proc_buffer);
@@ -140,18 +140,18 @@
vp9_free_frame_buffers(cm);
for (i = 0; i < FRAME_BUFFERS; i++) {
- cm->fb_idx_ref_cnt[i] = 0;
- if (vp9_alloc_frame_buffer(&cm->yv12_fb[i], width, height, ss_x, ss_y,
- VP9_ENC_BORDER_IN_PIXELS) < 0)
+ cm->frame_bufs[i].ref_count = 0;
+ if (vp9_alloc_frame_buffer(&cm->frame_bufs[i].buf, width, height,
+ ss_x, ss_y, VP9_ENC_BORDER_IN_PIXELS) < 0)
goto fail;
}
cm->new_fb_idx = FRAME_BUFFERS - 1;
- cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1;
+ cm->frame_bufs[cm->new_fb_idx].ref_count = 1;
for (i = 0; i < REF_FRAMES; i++) {
cm->ref_frame_map[i] = i;
- cm->fb_idx_ref_cnt[i] = 1;
+ cm->frame_bufs[i].ref_count = 1;
}
if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
diff --git a/vp9/common/vp9_blockd.c b/vp9/common/vp9_blockd.c
new file mode 100644
index 0000000..8cc6571
--- /dev/null
+++ b/vp9/common/vp9_blockd.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#include "vp9/common/vp9_blockd.h"
+
+MB_PREDICTION_MODE vp9_left_block_mode(const MODE_INFO *cur_mi,
+ const MODE_INFO *left_mi, int b) {
+ if (b == 0 || b == 2) {
+ if (!left_mi || is_inter_block(&left_mi->mbmi))
+ return DC_PRED;
+
+ return left_mi->mbmi.sb_type < BLOCK_8X8 ? left_mi->bmi[b + 1].as_mode
+ : left_mi->mbmi.mode;
+ } else {
+ assert(b == 1 || b == 3);
+ return cur_mi->bmi[b - 1].as_mode;
+ }
+}
+
+MB_PREDICTION_MODE vp9_above_block_mode(const MODE_INFO *cur_mi,
+ const MODE_INFO *above_mi, int b) {
+ if (b == 0 || b == 1) {
+ if (!above_mi || is_inter_block(&above_mi->mbmi))
+ return DC_PRED;
+
+ return above_mi->mbmi.sb_type < BLOCK_8X8 ? above_mi->bmi[b + 2].as_mode
+ : above_mi->mbmi.mode;
+ } else {
+ assert(b == 2 || b == 3);
+ return cur_mi->bmi[b - 2].as_mode;
+ }
+}
+
+void vp9_foreach_transformed_block_in_plane(
+ const MACROBLOCKD *const xd, BLOCK_SIZE bsize, int plane,
+ foreach_transformed_block_visitor visit, void *arg) {
+ const struct macroblockd_plane *const pd = &xd->plane[plane];
+ const MB_MODE_INFO* mbmi = &xd->mi_8x8[0]->mbmi;
+ // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
+ // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
+ // transform size varies per plane, look it up in a common way.
+ const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi)
+ : mbmi->tx_size;
+ const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
+ const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
+ const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
+ const int step = 1 << (tx_size << 1);
+ int i;
+
+ // If mb_to_right_edge is < 0 we are in a situation in which
+ // the current block size extends into the UMV and we won't
+ // visit the sub blocks that are wholly within the UMV.
+ if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
+ int r, c;
+
+ int max_blocks_wide = num_4x4_w;
+ int max_blocks_high = num_4x4_h;
+
+ // xd->mb_to_right_edge is in units of pixels * 8. This converts
+ // it to 4x4 block sizes.
+ if (xd->mb_to_right_edge < 0)
+ max_blocks_wide += (xd->mb_to_right_edge >> (5 + pd->subsampling_x));
+
+ if (xd->mb_to_bottom_edge < 0)
+ max_blocks_high += (xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
+
+ i = 0;
+ // Unlike the normal case - in here we have to keep track of the
+ // row and column of the blocks we use so that we know if we are in
+ // the unrestricted motion border.
+ for (r = 0; r < num_4x4_h; r += (1 << tx_size)) {
+ for (c = 0; c < num_4x4_w; c += (1 << tx_size)) {
+ if (r < max_blocks_high && c < max_blocks_wide)
+ visit(plane, i, plane_bsize, tx_size, arg);
+ i += step;
+ }
+ }
+ } else {
+ for (i = 0; i < num_4x4_w * num_4x4_h; i += step)
+ visit(plane, i, plane_bsize, tx_size, arg);
+ }
+}
+
+void vp9_foreach_transformed_block(const MACROBLOCKD* const xd,
+ BLOCK_SIZE bsize,
+ foreach_transformed_block_visitor visit,
+ void *arg) {
+ int plane;
+
+ for (plane = 0; plane < MAX_MB_PLANE; plane++)
+ vp9_foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
+}
+
+void vp9_foreach_transformed_block_uv(const MACROBLOCKD* const xd,
+ BLOCK_SIZE bsize,
+ foreach_transformed_block_visitor visit,
+ void *arg) {
+ int plane;
+
+ for (plane = 1; plane < MAX_MB_PLANE; plane++)
+ vp9_foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
+}
+
+void vp9_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
+ BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int has_eob,
+ int aoff, int loff) {
+ ENTROPY_CONTEXT *const a = pd->above_context + aoff;
+ ENTROPY_CONTEXT *const l = pd->left_context + loff;
+ const int tx_size_in_blocks = 1 << tx_size;
+
+ // above
+ if (has_eob && xd->mb_to_right_edge < 0) {
+ int i;
+ const int blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize] +
+ (xd->mb_to_right_edge >> (5 + pd->subsampling_x));
+ int above_contexts = tx_size_in_blocks;
+ if (above_contexts + aoff > blocks_wide)
+ above_contexts = blocks_wide - aoff;
+
+ for (i = 0; i < above_contexts; ++i)
+ a[i] = has_eob;
+ for (i = above_contexts; i < tx_size_in_blocks; ++i)
+ a[i] = 0;
+ } else {
+ vpx_memset(a, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
+ }
+
+ // left
+ if (has_eob && xd->mb_to_bottom_edge < 0) {
+ int i;
+ const int blocks_high = num_4x4_blocks_high_lookup[plane_bsize] +
+ (xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
+ int left_contexts = tx_size_in_blocks;
+ if (left_contexts + loff > blocks_high)
+ left_contexts = blocks_high - loff;
+
+ for (i = 0; i < left_contexts; ++i)
+ l[i] = has_eob;
+ for (i = left_contexts; i < tx_size_in_blocks; ++i)
+ l[i] = 0;
+ } else {
+ vpx_memset(l, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
+ }
+}
+
+void vp9_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y) {
+ int i;
+
+ for (i = 0; i < MAX_MB_PLANE; i++) {
+ xd->plane[i].plane_type = i ? PLANE_TYPE_UV : PLANE_TYPE_Y;
+ xd->plane[i].subsampling_x = i ? ss_x : 0;
+ xd->plane[i].subsampling_y = i ? ss_y : 0;
+ }
+#if CONFIG_ALPHA
+ // TODO(jkoleszar): Using the Y w/h for now
+ xd->plane[3].plane_type = PLANE_TYPE_Y;
+ xd->plane[3].subsampling_x = 0;
+ xd->plane[3].subsampling_y = 0;
+#endif
+}
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 9e16d8f..70b8ffa 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -30,7 +30,7 @@
#endif
#define BLOCK_SIZE_GROUPS 4
-#define MBSKIP_CONTEXTS 3
+#define SKIP_CONTEXTS 3
#define INTER_MODE_CONTEXTS 7
/* Segment Feature Masks */
@@ -153,33 +153,11 @@
return mbmi->ref_frame[1] > INTRA_FRAME;
}
-static MB_PREDICTION_MODE left_block_mode(const MODE_INFO *cur_mi,
- const MODE_INFO *left_mi, int b) {
- if (b == 0 || b == 2) {
- if (!left_mi || is_inter_block(&left_mi->mbmi))
- return DC_PRED;
+MB_PREDICTION_MODE vp9_left_block_mode(const MODE_INFO *cur_mi,
+ const MODE_INFO *left_mi, int b);
- return left_mi->mbmi.sb_type < BLOCK_8X8 ? left_mi->bmi[b + 1].as_mode
- : left_mi->mbmi.mode;
- } else {
- assert(b == 1 || b == 3);
- return cur_mi->bmi[b - 1].as_mode;
- }
-}
-
-static MB_PREDICTION_MODE above_block_mode(const MODE_INFO *cur_mi,
- const MODE_INFO *above_mi, int b) {
- if (b == 0 || b == 1) {
- if (!above_mi || is_inter_block(&above_mi->mbmi))
- return DC_PRED;
-
- return above_mi->mbmi.sb_type < BLOCK_8X8 ? above_mi->bmi[b + 2].as_mode
- : above_mi->mbmi.mode;
- } else {
- assert(b == 2 || b == 3);
- return cur_mi->bmi[b - 2].as_mode;
- }
-}
+MB_PREDICTION_MODE vp9_above_block_mode(const MODE_INFO *cur_mi,
+ const MODE_INFO *above_mi, int b);
enum mv_precision {
MV_PRECISION_Q3,
@@ -252,7 +230,7 @@
/* Inverse transform function pointers. */
void (*itxm_add)(const int16_t *input, uint8_t *dest, int stride, int eob);
- const interp_kernel *interp_kernel;
+ const InterpKernel *interp_kernel;
int corrupted;
@@ -266,7 +244,8 @@
-static BLOCK_SIZE get_subsize(BLOCK_SIZE bsize, PARTITION_TYPE partition) {
+static INLINE BLOCK_SIZE get_subsize(BLOCK_SIZE bsize,
+ PARTITION_TYPE partition) {
const BLOCK_SIZE subsize = subsize_lookup[partition][bsize];
assert(subsize < BLOCK_SIZES);
return subsize;
@@ -298,23 +277,9 @@
: DCT_DCT;
}
-static void setup_block_dptrs(MACROBLOCKD *xd, int ss_x, int ss_y) {
- int i;
+void vp9_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y);
- for (i = 0; i < MAX_MB_PLANE; i++) {
- xd->plane[i].plane_type = i ? PLANE_TYPE_UV : PLANE_TYPE_Y;
- xd->plane[i].subsampling_x = i ? ss_x : 0;
- xd->plane[i].subsampling_y = i ? ss_y : 0;
- }
-#if CONFIG_ALPHA
- // TODO(jkoleszar): Using the Y w/h for now
- xd->plane[3].plane_type = PLANE_TYPE_Y;
- xd->plane[3].subsampling_x = 0;
- xd->plane[3].subsampling_y = 0;
-#endif
-}
-
-static TX_SIZE get_uv_tx_size_impl(TX_SIZE y_tx_size, BLOCK_SIZE bsize) {
+static INLINE TX_SIZE get_uv_tx_size_impl(TX_SIZE y_tx_size, BLOCK_SIZE bsize) {
if (bsize < BLOCK_8X8) {
return TX_4X4;
} else {
@@ -324,12 +289,12 @@
}
}
-static TX_SIZE get_uv_tx_size(const MB_MODE_INFO *mbmi) {
+static INLINE TX_SIZE get_uv_tx_size(const MB_MODE_INFO *mbmi) {
return get_uv_tx_size_impl(mbmi->tx_size, mbmi->sb_type);
}
-static BLOCK_SIZE get_plane_block_size(BLOCK_SIZE bsize,
- const struct macroblockd_plane *pd) {
+static INLINE BLOCK_SIZE get_plane_block_size(BLOCK_SIZE bsize,
+ const struct macroblockd_plane *pd) {
BLOCK_SIZE bs = ss_size_lookup[bsize][pd->subsampling_x][pd->subsampling_y];
assert(bs < BLOCK_SIZES);
return bs;
@@ -340,77 +305,23 @@
TX_SIZE tx_size,
void *arg);
-static INLINE void foreach_transformed_block_in_plane(
+void vp9_foreach_transformed_block_in_plane(
const MACROBLOCKD *const xd, BLOCK_SIZE bsize, int plane,
- foreach_transformed_block_visitor visit, void *arg) {
- const struct macroblockd_plane *const pd = &xd->plane[plane];
- const MB_MODE_INFO* mbmi = &xd->mi_8x8[0]->mbmi;
- // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
- // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
- // transform size varies per plane, look it up in a common way.
- const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi)
- : mbmi->tx_size;
- const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
- const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
- const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
- const int step = 1 << (tx_size << 1);
- int i;
+ foreach_transformed_block_visitor visit, void *arg);
- // If mb_to_right_edge is < 0 we are in a situation in which
- // the current block size extends into the UMV and we won't
- // visit the sub blocks that are wholly within the UMV.
- if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
- int r, c;
- int max_blocks_wide = num_4x4_w;
- int max_blocks_high = num_4x4_h;
-
- // xd->mb_to_right_edge is in units of pixels * 8. This converts
- // it to 4x4 block sizes.
- if (xd->mb_to_right_edge < 0)
- max_blocks_wide += (xd->mb_to_right_edge >> (5 + pd->subsampling_x));
-
- if (xd->mb_to_bottom_edge < 0)
- max_blocks_high += (xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
-
- i = 0;
- // Unlike the normal case - in here we have to keep track of the
- // row and column of the blocks we use so that we know if we are in
- // the unrestricted motion border.
- for (r = 0; r < num_4x4_h; r += (1 << tx_size)) {
- for (c = 0; c < num_4x4_w; c += (1 << tx_size)) {
- if (r < max_blocks_high && c < max_blocks_wide)
- visit(plane, i, plane_bsize, tx_size, arg);
- i += step;
- }
- }
- } else {
- for (i = 0; i < num_4x4_w * num_4x4_h; i += step)
- visit(plane, i, plane_bsize, tx_size, arg);
- }
-}
-
-static INLINE void foreach_transformed_block(
+void vp9_foreach_transformed_block(
const MACROBLOCKD* const xd, BLOCK_SIZE bsize,
- foreach_transformed_block_visitor visit, void *arg) {
- int plane;
+ foreach_transformed_block_visitor visit, void *arg);
- for (plane = 0; plane < MAX_MB_PLANE; plane++)
- foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
-}
-static INLINE void foreach_transformed_block_uv(
+void vp9_foreach_transformed_block_uv(
const MACROBLOCKD* const xd, BLOCK_SIZE bsize,
- foreach_transformed_block_visitor visit, void *arg) {
- int plane;
+ foreach_transformed_block_visitor visit, void *arg);
- for (plane = 1; plane < MAX_MB_PLANE; plane++)
- foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
-}
-
-static void txfrm_block_to_raster_xy(BLOCK_SIZE plane_bsize,
- TX_SIZE tx_size, int block,
- int *x, int *y) {
+static INLINE void txfrm_block_to_raster_xy(BLOCK_SIZE plane_bsize,
+ TX_SIZE tx_size, int block,
+ int *x, int *y) {
const int bwl = b_width_log2(plane_bsize);
const int tx_cols_log2 = bwl - tx_size;
const int tx_cols = 1 << tx_cols_log2;
@@ -419,50 +330,13 @@
*y = (raster_mb >> tx_cols_log2) << tx_size;
}
-static void set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
- BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
- int has_eob, int aoff, int loff) {
- ENTROPY_CONTEXT *const a = pd->above_context + aoff;
- ENTROPY_CONTEXT *const l = pd->left_context + loff;
- const int tx_size_in_blocks = 1 << tx_size;
+void vp9_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
+ BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int has_eob,
+ int aoff, int loff);
- // above
- if (has_eob && xd->mb_to_right_edge < 0) {
- int i;
- const int blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize] +
- (xd->mb_to_right_edge >> (5 + pd->subsampling_x));
- int above_contexts = tx_size_in_blocks;
- if (above_contexts + aoff > blocks_wide)
- above_contexts = blocks_wide - aoff;
- for (i = 0; i < above_contexts; ++i)
- a[i] = has_eob;
- for (i = above_contexts; i < tx_size_in_blocks; ++i)
- a[i] = 0;
- } else {
- vpx_memset(a, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
- }
-
- // left
- if (has_eob && xd->mb_to_bottom_edge < 0) {
- int i;
- const int blocks_high = num_4x4_blocks_high_lookup[plane_bsize] +
- (xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
- int left_contexts = tx_size_in_blocks;
- if (left_contexts + loff > blocks_high)
- left_contexts = blocks_high - loff;
-
- for (i = 0; i < left_contexts; ++i)
- l[i] = has_eob;
- for (i = left_contexts; i < tx_size_in_blocks; ++i)
- l[i] = 0;
- } else {
- vpx_memset(l, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
- }
-}
-
-static int get_tx_eob(const struct segmentation *seg, int segment_id,
- TX_SIZE tx_size) {
+static INLINE int get_tx_eob(const struct segmentation *seg, int segment_id,
+ TX_SIZE tx_size) {
const int eob_max = 16 << (tx_size << 1);
return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
}
diff --git a/vp9/common/vp9_common.h b/vp9/common/vp9_common.h
index 69964da..2dccb70 100644
--- a/vp9/common/vp9_common.h
+++ b/vp9/common/vp9_common.h
@@ -18,6 +18,7 @@
#include "./vpx_config.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx/vpx_integer.h"
+#include "vp9/common/vp9_systemdependent.h"
#ifdef __cplusplus
extern "C" {
@@ -59,16 +60,8 @@
return value < low ? low : (value > high ? high : value);
}
-static int get_unsigned_bits(unsigned int num_values) {
- int cat = 0;
- if (num_values <= 1)
- return 0;
- num_values--;
- while (num_values > 0) {
- cat++;
- num_values >>= 1;
- }
- return cat;
+static INLINE int get_unsigned_bits(unsigned int num_values) {
+ return num_values > 0 ? get_msb(num_values) + 1 : 0;
}
#if CONFIG_DEBUG
diff --git a/vp9/common/vp9_convolve.c b/vp9/common/vp9_convolve.c
index b105a57..3807ccc 100644
--- a/vp9/common/vp9_convolve.c
+++ b/vp9/common/vp9_convolve.c
@@ -20,7 +20,7 @@
static void convolve_horiz(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
- const interp_kernel *x_filters,
+ const InterpKernel *x_filters,
int x0_q4, int x_step_q4, int w, int h) {
int x, y;
src -= SUBPEL_TAPS / 2 - 1;
@@ -42,7 +42,7 @@
static void convolve_avg_horiz(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
- const interp_kernel *x_filters,
+ const InterpKernel *x_filters,
int x0_q4, int x_step_q4, int w, int h) {
int x, y;
src -= SUBPEL_TAPS / 2 - 1;
@@ -65,7 +65,7 @@
static void convolve_vert(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
- const interp_kernel *y_filters,
+ const InterpKernel *y_filters,
int y0_q4, int y_step_q4, int w, int h) {
int x, y;
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
@@ -88,7 +88,7 @@
static void convolve_avg_vert(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
- const interp_kernel *y_filters,
+ const InterpKernel *y_filters,
int y0_q4, int y_step_q4, int w, int h) {
int x, y;
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
@@ -112,9 +112,9 @@
static void convolve(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
- const interp_kernel *const x_filters,
+ const InterpKernel *const x_filters,
int x0_q4, int x_step_q4,
- const interp_kernel *const y_filters,
+ const InterpKernel *const y_filters,
int y0_q4, int y_step_q4,
int w, int h) {
// Fixed size intermediate buffer places limits on parameters.
@@ -138,14 +138,14 @@
y_filters, y0_q4, y_step_q4, w, h);
}
-static const interp_kernel *get_filter_base(const int16_t *filter) {
+static const InterpKernel *get_filter_base(const int16_t *filter) {
// NOTE: This assumes that the filter table is 256-byte aligned.
// TODO(agrange) Modify to make independent of table alignment.
- return (const interp_kernel *)(((intptr_t)filter) & ~((intptr_t)0xFF));
+ return (const InterpKernel *)(((intptr_t)filter) & ~((intptr_t)0xFF));
}
-static int get_filter_offset(const int16_t *f, const interp_kernel *base) {
- return (const interp_kernel *)(intptr_t)f - base;
+static int get_filter_offset(const int16_t *f, const InterpKernel *base) {
+ return (const InterpKernel *)(intptr_t)f - base;
}
void vp9_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
@@ -153,7 +153,7 @@
const int16_t *filter_x, int x_step_q4,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
- const interp_kernel *const filters_x = get_filter_base(filter_x);
+ const InterpKernel *const filters_x = get_filter_base(filter_x);
const int x0_q4 = get_filter_offset(filter_x, filters_x);
convolve_horiz(src, src_stride, dst, dst_stride, filters_x,
@@ -165,7 +165,7 @@
const int16_t *filter_x, int x_step_q4,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
- const interp_kernel *const filters_x = get_filter_base(filter_x);
+ const InterpKernel *const filters_x = get_filter_base(filter_x);
const int x0_q4 = get_filter_offset(filter_x, filters_x);
convolve_avg_horiz(src, src_stride, dst, dst_stride, filters_x,
@@ -177,7 +177,7 @@
const int16_t *filter_x, int x_step_q4,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
- const interp_kernel *const filters_y = get_filter_base(filter_y);
+ const InterpKernel *const filters_y = get_filter_base(filter_y);
const int y0_q4 = get_filter_offset(filter_y, filters_y);
convolve_vert(src, src_stride, dst, dst_stride, filters_y,
y0_q4, y_step_q4, w, h);
@@ -188,7 +188,7 @@
const int16_t *filter_x, int x_step_q4,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
- const interp_kernel *const filters_y = get_filter_base(filter_y);
+ const InterpKernel *const filters_y = get_filter_base(filter_y);
const int y0_q4 = get_filter_offset(filter_y, filters_y);
convolve_avg_vert(src, src_stride, dst, dst_stride, filters_y,
y0_q4, y_step_q4, w, h);
@@ -199,10 +199,10 @@
const int16_t *filter_x, int x_step_q4,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
- const interp_kernel *const filters_x = get_filter_base(filter_x);
+ const InterpKernel *const filters_x = get_filter_base(filter_x);
const int x0_q4 = get_filter_offset(filter_x, filters_x);
- const interp_kernel *const filters_y = get_filter_base(filter_y);
+ const InterpKernel *const filters_y = get_filter_base(filter_y);
const int y0_q4 = get_filter_offset(filter_y, filters_y);
convolve(src, src_stride, dst, dst_stride,
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index 77b8de0..6def3c8 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -303,7 +303,7 @@
ct_8x8p[0][1] = tx_count_8x8p[TX_8X8];
}
-static const vp9_prob default_mbskip_probs[MBSKIP_CONTEXTS] = {
+static const vp9_prob default_skip_probs[SKIP_CONTEXTS] = {
192, 128, 64
};
@@ -325,7 +325,7 @@
vp9_copy(cm->fc.comp_ref_prob, default_comp_ref_p);
vp9_copy(cm->fc.single_ref_prob, default_single_ref_p);
cm->fc.tx_probs = default_tx_probs;
- vp9_copy(cm->fc.mbskip_probs, default_mbskip_probs);
+ vp9_copy(cm->fc.skip_probs, default_skip_probs);
vp9_copy(cm->fc.inter_mode_probs, default_inter_mode_probs);
}
@@ -415,9 +415,8 @@
}
}
- for (i = 0; i < MBSKIP_CONTEXTS; ++i)
- fc->mbskip_probs[i] = adapt_prob(pre_fc->mbskip_probs[i],
- counts->mbskip[i]);
+ for (i = 0; i < SKIP_CONTEXTS; ++i)
+ fc->skip_probs[i] = adapt_prob(pre_fc->skip_probs[i], counts->skip[i]);
}
static void set_default_lf_deltas(struct loopfilter *lf) {
diff --git a/vp9/common/vp9_filter.c b/vp9/common/vp9_filter.c
index 9f400e9..546f603 100644
--- a/vp9/common/vp9_filter.c
+++ b/vp9/common/vp9_filter.c
@@ -14,7 +14,7 @@
#include "vp9/common/vp9_filter.h"
-DECLARE_ALIGNED(256, const interp_kernel,
+DECLARE_ALIGNED(256, const InterpKernel,
vp9_bilinear_filters[SUBPEL_SHIFTS]) = {
{ 0, 0, 0, 128, 0, 0, 0, 0 },
{ 0, 0, 0, 120, 8, 0, 0, 0 },
@@ -35,7 +35,7 @@
};
// Lagrangian interpolation filter
-DECLARE_ALIGNED(256, const interp_kernel,
+DECLARE_ALIGNED(256, const InterpKernel,
vp9_sub_pel_filters_8[SUBPEL_SHIFTS]) = {
{ 0, 0, 0, 128, 0, 0, 0, 0},
{ 0, 1, -5, 126, 8, -3, 1, 0},
@@ -56,7 +56,7 @@
};
// DCT based filter
-DECLARE_ALIGNED(256, const interp_kernel,
+DECLARE_ALIGNED(256, const InterpKernel,
vp9_sub_pel_filters_8s[SUBPEL_SHIFTS]) = {
{0, 0, 0, 128, 0, 0, 0, 0},
{-1, 3, -7, 127, 8, -3, 1, 0},
@@ -77,7 +77,7 @@
};
// freqmultiplier = 0.5
-DECLARE_ALIGNED(256, const interp_kernel,
+DECLARE_ALIGNED(256, const InterpKernel,
vp9_sub_pel_filters_8lp[SUBPEL_SHIFTS]) = {
{ 0, 0, 0, 128, 0, 0, 0, 0},
{-3, -1, 32, 64, 38, 1, -3, 0},
@@ -98,14 +98,15 @@
};
-static const interp_kernel* vp9_filter_kernels[4] = {
+static const InterpKernel* vp9_filter_kernels[4] = {
vp9_sub_pel_filters_8,
vp9_sub_pel_filters_8lp,
vp9_sub_pel_filters_8s,
vp9_bilinear_filters
};
-const interp_kernel *vp9_get_interp_kernel(INTERP_FILTER filter) {
+const InterpKernel *vp9_get_interp_kernel(INTERP_FILTER filter) {
+ assert(filter != SWITCHABLE);
return vp9_filter_kernels[filter];
}
diff --git a/vp9/common/vp9_filter.h b/vp9/common/vp9_filter.h
index b611e30..15610d7 100644
--- a/vp9/common/vp9_filter.h
+++ b/vp9/common/vp9_filter.h
@@ -33,14 +33,14 @@
SWITCHABLE = 4 /* should be the last one */
} INTERP_FILTER;
-typedef int16_t interp_kernel[SUBPEL_TAPS];
+typedef int16_t InterpKernel[SUBPEL_TAPS];
-const interp_kernel *vp9_get_interp_kernel(INTERP_FILTER filter);
+const InterpKernel *vp9_get_interp_kernel(INTERP_FILTER filter);
-extern const interp_kernel vp9_bilinear_filters[SUBPEL_SHIFTS];
-extern const interp_kernel vp9_sub_pel_filters_8[SUBPEL_SHIFTS];
-extern const interp_kernel vp9_sub_pel_filters_8s[SUBPEL_SHIFTS];
-extern const interp_kernel vp9_sub_pel_filters_8lp[SUBPEL_SHIFTS];
+extern const InterpKernel vp9_bilinear_filters[SUBPEL_SHIFTS];
+extern const InterpKernel vp9_sub_pel_filters_8[SUBPEL_SHIFTS];
+extern const InterpKernel vp9_sub_pel_filters_8s[SUBPEL_SHIFTS];
+extern const InterpKernel vp9_sub_pel_filters_8lp[SUBPEL_SHIFTS];
// The VP9_BILINEAR_FILTERS_2TAP macro returns a pointer to the bilinear
// filter kernel as a 2 tap filter.
diff --git a/vp9/common/vp9_idct.c b/vp9/common/vp9_idct.c
index 533f7f3..20b78bf 100644
--- a/vp9/common/vp9_idct.c
+++ b/vp9/common/vp9_idct.c
@@ -96,7 +96,7 @@
}
}
-static void idct4_1d(const int16_t *input, int16_t *output) {
+static void idct4(const int16_t *input, int16_t *output) {
int16_t step[4];
int temp1, temp2;
// stage 1
@@ -124,7 +124,7 @@
// Rows
for (i = 0; i < 4; ++i) {
- idct4_1d(input, outptr);
+ idct4(input, outptr);
input += 4;
outptr += 4;
}
@@ -133,7 +133,7 @@
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j)
temp_in[j] = out[j * 4 + i];
- idct4_1d(temp_in, temp_out);
+ idct4(temp_in, temp_out);
for (j = 0; j < 4; ++j)
dest[j * stride + i] = clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 4)
+ dest[j * stride + i]);
@@ -156,7 +156,7 @@
}
}
-static void idct8_1d(const int16_t *input, int16_t *output) {
+static void idct8(const int16_t *input, int16_t *output) {
int16_t step1[8], step2[8];
int temp1, temp2;
// stage 1
@@ -174,7 +174,7 @@
step1[6] = dct_const_round_shift(temp2);
// stage 2 & stage 3 - even half
- idct4_1d(step1, step1);
+ idct4(step1, step1);
// stage 2 - odd half
step2[4] = step1[4] + step1[5];
@@ -209,7 +209,7 @@
// First transform rows
for (i = 0; i < 8; ++i) {
- idct8_1d(input, outptr);
+ idct8(input, outptr);
input += 8;
outptr += 8;
}
@@ -218,7 +218,7 @@
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j)
temp_in[j] = out[j * 8 + i];
- idct8_1d(temp_in, temp_out);
+ idct8(temp_in, temp_out);
for (j = 0; j < 8; ++j)
dest[j * stride + i] = clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 5)
+ dest[j * stride + i]);
@@ -238,7 +238,7 @@
}
}
-static void iadst4_1d(const int16_t *input, int16_t *output) {
+static void iadst4(const int16_t *input, int16_t *output) {
int s0, s1, s2, s3, s4, s5, s6, s7;
int x0 = input[0];
@@ -283,10 +283,10 @@
void vp9_iht4x4_16_add_c(const int16_t *input, uint8_t *dest, int stride,
int tx_type) {
const transform_2d IHT_4[] = {
- { idct4_1d, idct4_1d }, // DCT_DCT = 0
- { iadst4_1d, idct4_1d }, // ADST_DCT = 1
- { idct4_1d, iadst4_1d }, // DCT_ADST = 2
- { iadst4_1d, iadst4_1d } // ADST_ADST = 3
+ { idct4, idct4 }, // DCT_DCT = 0
+ { iadst4, idct4 }, // ADST_DCT = 1
+ { idct4, iadst4 }, // DCT_ADST = 2
+ { iadst4, iadst4 } // ADST_ADST = 3
};
int i, j;
@@ -311,7 +311,7 @@
+ dest[j * stride + i]);
}
}
-static void iadst8_1d(const int16_t *input, int16_t *output) {
+static void iadst8(const int16_t *input, int16_t *output) {
int s0, s1, s2, s3, s4, s5, s6, s7;
int x0 = input[7];
@@ -389,10 +389,10 @@
}
static const transform_2d IHT_8[] = {
- { idct8_1d, idct8_1d }, // DCT_DCT = 0
- { iadst8_1d, idct8_1d }, // ADST_DCT = 1
- { idct8_1d, iadst8_1d }, // DCT_ADST = 2
- { iadst8_1d, iadst8_1d } // ADST_ADST = 3
+ { idct8, idct8 }, // DCT_DCT = 0
+ { iadst8, idct8 }, // ADST_DCT = 1
+ { idct8, iadst8 }, // DCT_ADST = 2
+ { iadst8, iadst8 } // ADST_ADST = 3
};
void vp9_iht8x8_64_add_c(const int16_t *input, uint8_t *dest, int stride,
@@ -430,7 +430,7 @@
// First transform rows
// only first 4 row has non-zero coefs
for (i = 0; i < 4; ++i) {
- idct8_1d(input, outptr);
+ idct8(input, outptr);
input += 8;
outptr += 8;
}
@@ -439,14 +439,14 @@
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j)
temp_in[j] = out[j * 8 + i];
- idct8_1d(temp_in, temp_out);
+ idct8(temp_in, temp_out);
for (j = 0; j < 8; ++j)
dest[j * stride + i] = clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 5)
+ dest[j * stride + i]);
}
}
-static void idct16_1d(const int16_t *input, int16_t *output) {
+static void idct16(const int16_t *input, int16_t *output) {
int16_t step1[16], step2[16];
int temp1, temp2;
@@ -619,7 +619,7 @@
// First transform rows
for (i = 0; i < 16; ++i) {
- idct16_1d(input, outptr);
+ idct16(input, outptr);
input += 16;
outptr += 16;
}
@@ -628,14 +628,14 @@
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j)
temp_in[j] = out[j * 16 + i];
- idct16_1d(temp_in, temp_out);
+ idct16(temp_in, temp_out);
for (j = 0; j < 16; ++j)
dest[j * stride + i] = clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 6)
+ dest[j * stride + i]);
}
}
-static void iadst16_1d(const int16_t *input, int16_t *output) {
+static void iadst16(const int16_t *input, int16_t *output) {
int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15;
int x0 = input[15];
@@ -807,10 +807,10 @@
}
static const transform_2d IHT_16[] = {
- { idct16_1d, idct16_1d }, // DCT_DCT = 0
- { iadst16_1d, idct16_1d }, // ADST_DCT = 1
- { idct16_1d, iadst16_1d }, // DCT_ADST = 2
- { iadst16_1d, iadst16_1d } // ADST_ADST = 3
+ { idct16, idct16 }, // DCT_DCT = 0
+ { iadst16, idct16 }, // ADST_DCT = 1
+ { idct16, iadst16 }, // DCT_ADST = 2
+ { iadst16, iadst16 } // ADST_ADST = 3
};
void vp9_iht16x16_256_add_c(const int16_t *input, uint8_t *dest, int stride,
@@ -848,7 +848,7 @@
// First transform rows. Since all non-zero dct coefficients are in
// upper-left 4x4 area, we only need to calculate first 4 rows here.
for (i = 0; i < 4; ++i) {
- idct16_1d(input, outptr);
+ idct16(input, outptr);
input += 16;
outptr += 16;
}
@@ -857,7 +857,7 @@
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j)
temp_in[j] = out[j*16 + i];
- idct16_1d(temp_in, temp_out);
+ idct16(temp_in, temp_out);
for (j = 0; j < 16; ++j)
dest[j * stride + i] = clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 6)
+ dest[j * stride + i]);
@@ -877,7 +877,7 @@
}
}
-static void idct32_1d(const int16_t *input, int16_t *output) {
+static void idct32(const int16_t *input, int16_t *output) {
int16_t step1[32], step2[32];
int temp1, temp2;
@@ -1263,7 +1263,7 @@
zero_coeff[j] = zero_coeff[2 * j] | zero_coeff[2 * j + 1];
if (zero_coeff[0] | zero_coeff[1])
- idct32_1d(input, outptr);
+ idct32(input, outptr);
else
vpx_memset(outptr, 0, sizeof(int16_t) * 32);
input += 32;
@@ -1274,7 +1274,7 @@
for (i = 0; i < 32; ++i) {
for (j = 0; j < 32; ++j)
temp_in[j] = out[j * 32 + i];
- idct32_1d(temp_in, temp_out);
+ idct32(temp_in, temp_out);
for (j = 0; j < 32; ++j)
dest[j * stride + i] = clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 6)
+ dest[j * stride + i]);
@@ -1290,7 +1290,7 @@
// Rows
// only upper-left 8x8 has non-zero coeff
for (i = 0; i < 8; ++i) {
- idct32_1d(input, outptr);
+ idct32(input, outptr);
input += 32;
outptr += 32;
}
@@ -1299,7 +1299,7 @@
for (i = 0; i < 32; ++i) {
for (j = 0; j < 32; ++j)
temp_in[j] = out[j * 32 + i];
- idct32_1d(temp_in, temp_out);
+ idct32(temp_in, temp_out);
for (j = 0; j < 32; ++j)
dest[j * stride + i] = clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 6)
+ dest[j * stride + i]);
diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c
index 2266e0e..07d7a92 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -16,26 +16,6 @@
#include "vp9/common/vp9_seg_common.h"
-// This structure holds bit masks for all 8x8 blocks in a 64x64 region.
-// Each 1 bit represents a position in which we want to apply the loop filter.
-// Left_ entries refer to whether we apply a filter on the border to the
-// left of the block. Above_ entries refer to whether or not to apply a
-// filter on the above border. Int_ entries refer to whether or not to
-// apply borders on the 4x4 edges within the 8x8 block that each bit
-// represents.
-// Since each transform is accompanied by a potentially different type of
-// loop filter there is a different entry in the array for each transform size.
-typedef struct {
- uint64_t left_y[TX_SIZES];
- uint64_t above_y[TX_SIZES];
- uint64_t int_4x4_y;
- uint16_t left_uv[TX_SIZES];
- uint16_t above_uv[TX_SIZES];
- uint16_t int_4x4_uv;
- uint8_t lfl_y[64];
- uint8_t lfl_uv[16];
-} LOOP_FILTER_MASK;
-
// 64 bit masks for left transform size. Each 1 represents a position where
// we should apply a loop filter across the left border of an 8x8 block
// boundary.
@@ -638,9 +618,9 @@
// This function sets up the bit masks for the entire 64x64 region represented
// by mi_row, mi_col.
// TODO(JBB): This function only works for yv12.
-static void setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
- MODE_INFO **mi_8x8, const int mode_info_stride,
- LOOP_FILTER_MASK *lfm) {
+void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
+ MODE_INFO **mi_8x8, const int mode_info_stride,
+ LOOP_FILTER_MASK *lfm) {
int idx_32, idx_16, idx_8;
const loop_filter_info_n *const lfi_n = &cm->lf_info;
MODE_INFO **mip = mi_8x8;
@@ -1069,10 +1049,10 @@
}
#endif
-static void filter_block_plane(VP9_COMMON *const cm,
- struct macroblockd_plane *const plane,
- int mi_row,
- LOOP_FILTER_MASK *lfm) {
+void vp9_filter_block_plane(VP9_COMMON *const cm,
+ struct macroblockd_plane *const plane,
+ int mi_row,
+ LOOP_FILTER_MASK *lfm) {
struct buf_2d *const dst = &plane->dst;
uint8_t* const dst0 = dst->buf;
int r, c;
@@ -1244,14 +1224,14 @@
#if CONFIG_NON420
if (use_420)
#endif
- setup_mask(cm, mi_row, mi_col, mi_8x8 + mi_col, cm->mode_info_stride,
- &lfm);
+ vp9_setup_mask(cm, mi_row, mi_col, mi_8x8 + mi_col,
+ cm->mode_info_stride, &lfm);
for (plane = 0; plane < num_planes; ++plane) {
#if CONFIG_NON420
if (use_420)
#endif
- filter_block_plane(cm, &xd->plane[plane], mi_row, &lfm);
+ vp9_filter_block_plane(cm, &xd->plane[plane], mi_row, &lfm);
#if CONFIG_NON420
else
filter_block_plane_non420(cm, &xd->plane[plane], mi_8x8 + mi_col,
@@ -1264,12 +1244,12 @@
void vp9_loop_filter_frame(VP9_COMMON *cm, MACROBLOCKD *xd,
int frame_filter_level,
- int y_only, int partial) {
+ int y_only, int partial_frame) {
int start_mi_row, end_mi_row, mi_rows_to_filter;
if (!frame_filter_level) return;
start_mi_row = 0;
mi_rows_to_filter = cm->mi_rows;
- if (partial && cm->mi_rows > 8) {
+ if (partial_frame && cm->mi_rows > 8) {
start_mi_row = cm->mi_rows >> 1;
start_mi_row &= 0xfffffff8;
mi_rows_to_filter = MAX(cm->mi_rows / 8, 8);
diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h
index 43373f4..97ae9d2 100644
--- a/vp9/common/vp9_loopfilter.h
+++ b/vp9/common/vp9_loopfilter.h
@@ -60,9 +60,42 @@
uint8_t lvl[MAX_SEGMENTS][MAX_REF_FRAMES][MAX_MODE_LF_DELTAS];
} loop_filter_info_n;
+// This structure holds bit masks for all 8x8 blocks in a 64x64 region.
+// Each 1 bit represents a position in which we want to apply the loop filter.
+// Left_ entries refer to whether we apply a filter on the border to the
+// left of the block. Above_ entries refer to whether or not to apply a
+// filter on the above border. Int_ entries refer to whether or not to
+// apply borders on the 4x4 edges within the 8x8 block that each bit
+// represents.
+// Since each transform is accompanied by a potentially different type of
+// loop filter there is a different entry in the array for each transform size.
+typedef struct {
+ uint64_t left_y[TX_SIZES];
+ uint64_t above_y[TX_SIZES];
+ uint64_t int_4x4_y;
+ uint16_t left_uv[TX_SIZES];
+ uint16_t above_uv[TX_SIZES];
+ uint16_t int_4x4_uv;
+ uint8_t lfl_y[64];
+ uint8_t lfl_uv[16];
+} LOOP_FILTER_MASK;
+
/* assorted loopfilter functions which get used elsewhere */
struct VP9Common;
struct macroblockd;
+struct VP9LfSyncData;
+
+// This function sets up the bit masks for the entire 64x64 region represented
+// by mi_row, mi_col.
+void vp9_setup_mask(struct VP9Common *const cm,
+ const int mi_row, const int mi_col,
+ MODE_INFO **mi_8x8, const int mode_info_stride,
+ LOOP_FILTER_MASK *lfm);
+
+void vp9_filter_block_plane(struct VP9Common *const cm,
+ struct macroblockd_plane *const plane,
+ int mi_row,
+ LOOP_FILTER_MASK *lfm);
void vp9_loop_filter_init(struct VP9Common *cm);
@@ -74,7 +107,7 @@
void vp9_loop_filter_frame(struct VP9Common *cm,
struct macroblockd *mbd,
int filter_level,
- int y_only, int partial);
+ int y_only, int partial_frame);
// Apply the loop filter to [start, stop) macro block rows in frame_buffer.
void vp9_loop_filter_rows(const YV12_BUFFER_CONFIG *frame_buffer,
@@ -90,6 +123,9 @@
int start;
int stop;
int y_only;
+
+ struct VP9LfSyncData *lf_sync;
+ int num_lf_workers;
} LFWorkerData;
// Operates on the rows described by LFWorkerData passed as 'arg1'.
diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h
index 9df76de..564e419 100644
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -55,6 +55,7 @@
MODE_FIRSTPASS = 0x3,
MODE_SECONDPASS = 0x4,
MODE_SECONDPASS_BEST = 0x5,
+ MODE_REALTIME = 0x6,
} MODE;
typedef enum {
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 894134a..d92a25b 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -60,7 +60,7 @@
vp9_prob single_ref_prob[REF_CONTEXTS][2];
vp9_prob comp_ref_prob[REF_CONTEXTS];
struct tx_probs tx_probs;
- vp9_prob mbskip_probs[MBSKIP_CONTEXTS];
+ vp9_prob skip_probs[SKIP_CONTEXTS];
nmv_context nmvc;
} FRAME_CONTEXT;
@@ -79,7 +79,7 @@
unsigned int single_ref[REF_CONTEXTS][2][2];
unsigned int comp_ref[REF_CONTEXTS][2];
struct tx_counts tx;
- unsigned int mbskip[MBSKIP_CONTEXTS][2];
+ unsigned int skip[SKIP_CONTEXTS][2];
nmv_context_counts mv;
} FRAME_COUNTS;
@@ -91,6 +91,12 @@
REFERENCE_MODES = 3,
} REFERENCE_MODE;
+
+typedef struct {
+ int ref_count;
+ YV12_BUFFER_CONFIG buf;
+} RefCntBuffer;
+
typedef struct VP9Common {
struct vpx_internal_error_info error;
@@ -117,8 +123,8 @@
YV12_BUFFER_CONFIG *frame_to_show;
- YV12_BUFFER_CONFIG yv12_fb[FRAME_BUFFERS];
- int fb_idx_ref_cnt[FRAME_BUFFERS]; /* reference counts */
+ RefCntBuffer frame_bufs[FRAME_BUFFERS];
+
int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */
// TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and
@@ -220,29 +226,29 @@
} VP9_COMMON;
static YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
- return &cm->yv12_fb[cm->new_fb_idx];
+ return &cm->frame_bufs[cm->new_fb_idx].buf;
}
static int get_free_fb(VP9_COMMON *cm) {
int i;
for (i = 0; i < FRAME_BUFFERS; i++)
- if (cm->fb_idx_ref_cnt[i] == 0)
+ if (cm->frame_bufs[i].ref_count == 0)
break;
assert(i < FRAME_BUFFERS);
- cm->fb_idx_ref_cnt[i] = 1;
+ cm->frame_bufs[i].ref_count = 1;
return i;
}
-static void ref_cnt_fb(int *buf, int *idx, int new_idx) {
+static void ref_cnt_fb(RefCntBuffer *bufs, int *idx, int new_idx) {
const int ref_index = *idx;
- if (ref_index >= 0 && buf[ref_index] > 0)
- buf[ref_index]--;
+ if (ref_index >= 0 && bufs[ref_index].ref_count > 0)
+ bufs[ref_index].ref_count--;
*idx = new_idx;
- buf[new_idx]++;
+ bufs[new_idx].ref_count++;
}
static int mi_cols_aligned_to_sb(int n_mis) {
diff --git a/vp9/common/vp9_pred_common.c b/vp9/common/vp9_pred_common.c
index 11b6d93..d5c27a5 100644
--- a/vp9/common/vp9_pred_common.c
+++ b/vp9/common/vp9_pred_common.c
@@ -291,23 +291,23 @@
} else { // inter/inter
const int above_has_second = has_second_ref(above_mbmi);
const int left_has_second = has_second_ref(left_mbmi);
+ const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
+ const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
if (above_has_second && left_has_second) {
- if (above_mbmi->ref_frame[0] == left_mbmi->ref_frame[0] &&
- above_mbmi->ref_frame[1] == left_mbmi->ref_frame[1])
- pred_context = 3 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME ||
- above_mbmi->ref_frame[1] == GOLDEN_FRAME ||
- left_mbmi->ref_frame[0] == GOLDEN_FRAME ||
- left_mbmi->ref_frame[1] == GOLDEN_FRAME);
+ if (above0 == left0 && above1 == left1)
+ pred_context = 3 * (above0 == GOLDEN_FRAME ||
+ above1 == GOLDEN_FRAME ||
+ left0 == GOLDEN_FRAME ||
+ left1 == GOLDEN_FRAME);
else
pred_context = 2;
} else if (above_has_second || left_has_second) {
- const MV_REFERENCE_FRAME rfs = !above_has_second ?
- above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
- const MV_REFERENCE_FRAME crf1 = above_has_second ?
- above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
- const MV_REFERENCE_FRAME crf2 = above_has_second ?
- above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
+ const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
if (rfs == GOLDEN_FRAME)
pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
@@ -316,17 +316,15 @@
else
pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
} else {
- if (above_mbmi->ref_frame[0] == LAST_FRAME &&
- left_mbmi->ref_frame[0] == LAST_FRAME) {
+ if (above0 == LAST_FRAME && left0 == LAST_FRAME) {
pred_context = 3;
- } else if (above_mbmi->ref_frame[0] == LAST_FRAME ||
- left_mbmi->ref_frame[0] == LAST_FRAME) {
- const MB_MODE_INFO *edge_mbmi =
- above_mbmi->ref_frame[0] == LAST_FRAME ? left_mbmi : above_mbmi;
- pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
+ } else if (above0 == LAST_FRAME || left0 == LAST_FRAME) {
+ const MV_REFERENCE_FRAME edge0 = (above0 == LAST_FRAME) ? left0
+ : above0;
+ pred_context = 4 * (edge0 == GOLDEN_FRAME);
} else {
- pred_context = 2 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME) +
- 2 * (left_mbmi->ref_frame[0] == GOLDEN_FRAME);
+ pred_context = 2 * (above0 == GOLDEN_FRAME) +
+ 2 * (left0 == GOLDEN_FRAME);
}
}
}
diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h
index 26edf78..0acee32 100644
--- a/vp9/common/vp9_pred_common.h
+++ b/vp9/common/vp9_pred_common.h
@@ -54,7 +54,7 @@
static INLINE vp9_prob vp9_get_skip_prob(const VP9_COMMON *cm,
const MACROBLOCKD *xd) {
- return cm->fc.mbskip_probs[vp9_get_skip_context(xd)];
+ return cm->fc.skip_probs[vp9_get_skip_context(xd)];
}
int vp9_get_pred_context_switchable_interp(const MACROBLOCKD *xd);
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index d554cc0..7576e7b 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -69,7 +69,7 @@
const int subpel_y,
const struct scale_factors *sf,
int w, int h, int ref,
- const interp_kernel *kernel,
+ const InterpKernel *kernel,
int xs, int ys) {
sf->predict[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
@@ -81,7 +81,7 @@
const MV *src_mv,
const struct scale_factors *sf,
int w, int h, int ref,
- const interp_kernel *kernel,
+ const InterpKernel *kernel,
enum mv_precision precision,
int x, int y) {
const int is_q4 = precision == MV_PRECISION_Q4;
@@ -269,21 +269,15 @@
? (plane == 0 ? mi->bmi[block].as_mv[ref].as_mv
: mi_mv_pred_q4(mi, ref))
: mi->mbmi.mv[ref].as_mv;
-
- // TODO(jkoleszar): This clamping is done in the incorrect place for the
- // scaling case. It needs to be done on the scaled MV, not the pre-scaling
- // MV. Note however that it performs the subsampling aware scaling so
- // that the result is always q4.
- // mv_precision precision is MV_PRECISION_Q4.
- const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, &mv, bw, bh,
- pd->subsampling_x,
- pd->subsampling_y);
-
MV32 scaled_mv;
- int xs, ys, x0, y0, x0_16, y0_16, x1, y1, frame_width,
- frame_height, subpel_x, subpel_y, buf_stride;
+ int xs, ys, x0, y0, x0_16, y0_16, frame_width, frame_height, buf_stride,
+ subpel_x, subpel_y;
uint8_t *ref_frame, *buf_ptr;
const YV12_BUFFER_CONFIG *ref_buf = xd->block_refs[ref]->buf;
+ const MV mv_q4 = {
+ mv.row * (1 << (1 - pd->subsampling_y)),
+ mv.col * (1 << (1 - pd->subsampling_x))
+ };
// Get reference frame pointer, width and height.
if (plane == 0) {
@@ -327,10 +321,6 @@
x0_16 += scaled_mv.col;
y0_16 += scaled_mv.row;
- // Get reference block bottom right coordinate.
- x1 = ((x0_16 + (w - 1) * xs) >> SUBPEL_BITS) + 1;
- y1 = ((y0_16 + (h - 1) * ys) >> SUBPEL_BITS) + 1;
-
// Get reference block pointer.
buf_ptr = ref_frame + y0 * pre_buf->stride + x0;
buf_stride = pre_buf->stride;
@@ -339,6 +329,9 @@
// width/height is not a multiple of 8 pixels.
if (scaled_mv.col || scaled_mv.row ||
(frame_width & 0x7) || (frame_height & 0x7)) {
+ // Get reference block bottom right coordinate.
+ int x1 = ((x0_16 + (w - 1) * xs) >> SUBPEL_BITS) + 1;
+ int y1 = ((y0_16 + (h - 1) * ys) >> SUBPEL_BITS) + 1;
int x_pad = 0, y_pad = 0;
if (subpel_x || (sf->x_step_q4 & SUBPEL_MASK)) {
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index 10e1658..bf738c2 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -35,7 +35,7 @@
const MV *mv_q3,
const struct scale_factors *sf,
int w, int h, int do_avg,
- const interp_kernel *kernel,
+ const InterpKernel *kernel,
enum mv_precision precision,
int x, int y);
@@ -93,11 +93,6 @@
}
}
-static void set_ref_ptrs(VP9_COMMON *cm, MACROBLOCKD *xd, int ref0, int ref1) {
- xd->block_refs[0] = &cm->frame_refs[ref0 >= 0 ? ref0 : 0];
- xd->block_refs[1] = &cm->frame_refs[ref1 >= 0 ? ref1 : 0];
-}
-
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index 8fd6db8..04a40bd 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -174,7 +174,7 @@
specialize vp9_v_predictor_32x32 $sse2_x86inc neon
prototype void vp9_tm_predictor_32x32 "uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left"
-specialize vp9_tm_predictor_32x32 $sse2_x86_64
+specialize vp9_tm_predictor_32x32 $sse2_x86_64 neon
prototype void vp9_dc_predictor_32x32 "uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left"
specialize vp9_dc_predictor_32x32 $sse2_x86inc
@@ -737,7 +737,7 @@
#
# Motion search
#
-prototype int vp9_full_search_sad "struct macroblock *x, struct mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv, int n"
+prototype int vp9_full_search_sad "const struct macroblock *x, struct mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv, int n"
specialize vp9_full_search_sad sse3 sse4_1
vp9_full_search_sad_sse3=vp9_full_search_sadx3
vp9_full_search_sad_sse4_1=vp9_full_search_sadx8
@@ -746,11 +746,11 @@
specialize vp9_refining_search_sad sse3
vp9_refining_search_sad_sse3=vp9_refining_search_sadx4
-prototype int vp9_diamond_search_sad "struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
+prototype int vp9_diamond_search_sad "const struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
specialize vp9_diamond_search_sad sse3
vp9_diamond_search_sad_sse3=vp9_diamond_search_sadx4
-prototype int vp9_full_range_search "struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
+prototype int vp9_full_range_search "const struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
specialize vp9_full_range_search
prototype void vp9_temporal_filter_apply "uint8_t *frame1, unsigned int stride, uint8_t *frame2, unsigned int block_size, int strength, int filter_weight, unsigned int *accumulator, uint16_t *count"
diff --git a/vp9/common/vp9_systemdependent.h b/vp9/common/vp9_systemdependent.h
index ee9a4823b..fb8626c 100644
--- a/vp9/common/vp9_systemdependent.h
+++ b/vp9/common/vp9_systemdependent.h
@@ -11,13 +11,17 @@
#ifndef VP9_COMMON_VP9_SYSTEMDEPENDENT_H_
#define VP9_COMMON_VP9_SYSTEMDEPENDENT_H_
-#ifdef __cplusplus
-extern "C" {
+#ifdef _MSC_VER
+# if _MSC_VER > 1310 && (defined(_M_X64) || defined(_M_IX86))
+# include <intrin.h>
+# define USE_MSC_INTRIN
+# endif
+# include <math.h>
+# define snprintf _snprintf
#endif
-#ifdef _MSC_VER
-#include <math.h>
-#define snprintf _snprintf
+#ifdef __cplusplus
+extern "C" {
#endif
#include "./vpx_config.h"
@@ -44,9 +48,7 @@
static INLINE int get_msb(unsigned int n) {
return 31 ^ __builtin_clz(n);
}
-#elif defined(_MSC_VER) && _MSC_VER > 1310 && \
- (defined(_M_X64) || defined(_M_IX86))
-#include <intrin.h>
+#elif defined(USE_MSC_INTRIN)
#pragma intrinsic(_BitScanReverse)
static INLINE int get_msb(unsigned int n) {
@@ -54,6 +56,7 @@
_BitScanReverse(&first_set_bit, n);
return first_set_bit;
}
+#undef USE_MSC_INTRIN
#else
// Returns (int)floor(log2(n)). n must be > 0.
static INLINE int get_msb(unsigned int n) {
diff --git a/vp9/common/x86/vp9_asm_stubs.c b/vp9/common/x86/vp9_asm_stubs.c
index f954236..8ab5fb1 100644
--- a/vp9/common/x86/vp9_asm_stubs.c
+++ b/vp9/common/x86/vp9_asm_stubs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ * Copyright (c) 2014 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
@@ -23,6 +23,105 @@
const short *filter
);
+#define FUN_CONV_1D(name, step_q4, filter, dir, src_start, avg, opt1, opt2) \
+void vp9_convolve8_##name##_##opt1(const uint8_t *src, ptrdiff_t src_stride, \
+ uint8_t *dst, ptrdiff_t dst_stride, \
+ const int16_t *filter_x, int x_step_q4, \
+ const int16_t *filter_y, int y_step_q4, \
+ int w, int h) { \
+ if (step_q4 == 16 && filter[3] != 128) { \
+ if (filter[0] || filter[1] || filter[2]) { \
+ while (w >= 16) { \
+ vp9_filter_block1d16_##dir##8_##avg##opt1(src_start, src_stride, \
+ dst, dst_stride, \
+ h, filter); \
+ src += 16; \
+ dst += 16; \
+ w -= 16; \
+ } \
+ while (w >= 8) { \
+ vp9_filter_block1d8_##dir##8_##avg##opt1(src_start, src_stride, \
+ dst, dst_stride, \
+ h, filter); \
+ src += 8; \
+ dst += 8; \
+ w -= 8; \
+ } \
+ while (w >= 4) { \
+ vp9_filter_block1d4_##dir##8_##avg##opt1(src_start, src_stride, \
+ dst, dst_stride, \
+ h, filter); \
+ src += 4; \
+ dst += 4; \
+ w -= 4; \
+ } \
+ } else { \
+ while (w >= 16) { \
+ vp9_filter_block1d16_##dir##2_##avg##opt2(src, src_stride, \
+ dst, dst_stride, \
+ h, filter); \
+ src += 16; \
+ dst += 16; \
+ w -= 16; \
+ } \
+ while (w >= 8) { \
+ vp9_filter_block1d8_##dir##2_##avg##opt2(src, src_stride, \
+ dst, dst_stride, \
+ h, filter); \
+ src += 8; \
+ dst += 8; \
+ w -= 8; \
+ } \
+ while (w >= 4) { \
+ vp9_filter_block1d4_##dir##2_##avg##opt2(src, src_stride, \
+ dst, dst_stride, \
+ h, filter); \
+ src += 4; \
+ dst += 4; \
+ w -= 4; \
+ } \
+ } \
+ } \
+ if (w) { \
+ vp9_convolve8_##name##_c(src, src_stride, dst, dst_stride, \
+ filter_x, x_step_q4, filter_y, y_step_q4, \
+ w, h); \
+ } \
+}
+
+#define FUN_CONV_2D(avg, opt) \
+void vp9_convolve8_##avg##opt(const uint8_t *src, ptrdiff_t src_stride, \
+ uint8_t *dst, ptrdiff_t dst_stride, \
+ const int16_t *filter_x, int x_step_q4, \
+ const int16_t *filter_y, int y_step_q4, \
+ int w, int h) { \
+ assert(w <= 64); \
+ assert(h <= 64); \
+ if (x_step_q4 == 16 && y_step_q4 == 16) { \
+ if (filter_x[0] || filter_x[1] || filter_x[2] || filter_x[3] == 128 || \
+ filter_y[0] || filter_y[1] || filter_y[2] || filter_y[3] == 128) { \
+ DECLARE_ALIGNED_ARRAY(16, unsigned char, fdata2, 64 * 71); \
+ vp9_convolve8_horiz_##opt(src - 3 * src_stride, src_stride, fdata2, 64, \
+ filter_x, x_step_q4, filter_y, y_step_q4, \
+ w, h + 7); \
+ vp9_convolve8_##avg##vert_##opt(fdata2 + 3 * 64, 64, dst, dst_stride, \
+ filter_x, x_step_q4, filter_y, \
+ y_step_q4, w, h); \
+ } else { \
+ DECLARE_ALIGNED_ARRAY(16, unsigned char, fdata2, 64 * 65); \
+ vp9_convolve8_horiz_##opt(src, src_stride, fdata2, 64, \
+ filter_x, x_step_q4, filter_y, y_step_q4, \
+ w, h + 1); \
+ vp9_convolve8_##avg##vert_##opt(fdata2, 64, dst, dst_stride, \
+ filter_x, x_step_q4, filter_y, \
+ y_step_q4, w, h); \
+ } \
+ } else { \
+ vp9_convolve8_##avg##c(src, src_stride, dst, dst_stride, \
+ filter_x, x_step_q4, filter_y, y_step_q4, w, h); \
+ } \
+}
+
#if HAVE_SSSE3
filter8_1dfunction vp9_filter_block1d16_v8_ssse3;
filter8_1dfunction vp9_filter_block1d16_h8_ssse3;
@@ -37,201 +136,57 @@
filter8_1dfunction vp9_filter_block1d4_v8_avg_ssse3;
filter8_1dfunction vp9_filter_block1d4_h8_avg_ssse3;
-void vp9_convolve8_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- /* Ensure the filter can be compressed to int16_t. */
- if (x_step_q4 == 16 && filter_x[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_h8_ssse3(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_h8_ssse3(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_h8_ssse3(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_horiz_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
+filter8_1dfunction vp9_filter_block1d16_v2_sse2;
+filter8_1dfunction vp9_filter_block1d16_h2_sse2;
+filter8_1dfunction vp9_filter_block1d8_v2_sse2;
+filter8_1dfunction vp9_filter_block1d8_h2_sse2;
+filter8_1dfunction vp9_filter_block1d4_v2_sse2;
+filter8_1dfunction vp9_filter_block1d4_h2_sse2;
+filter8_1dfunction vp9_filter_block1d16_v2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d16_h2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d8_v2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d8_h2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d4_v2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d4_h2_avg_sse2;
-void vp9_convolve8_vert_ssse3(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- if (y_step_q4 == 16 && filter_y[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_v8_ssse3(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_v8_ssse3(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_v8_ssse3(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_vert_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
+// void vp9_convolve8_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_vert_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_avg_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_avg_vert_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+FUN_CONV_1D(horiz, x_step_q4, filter_x, h, src, , ssse3, sse2);
+FUN_CONV_1D(vert, y_step_q4, filter_y, v, src - src_stride * 3, , ssse3, sse2);
+FUN_CONV_1D(avg_horiz, x_step_q4, filter_x, h, src, avg_, ssse3, sse2);
+FUN_CONV_1D(avg_vert, y_step_q4, filter_y, v, src - src_stride * 3, avg_,
+ ssse3, sse2);
-void vp9_convolve8_avg_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- if (x_step_q4 == 16 && filter_x[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_h8_avg_ssse3(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_h8_avg_ssse3(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_h8_avg_ssse3(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_avg_horiz_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
-
-void vp9_convolve8_avg_vert_ssse3(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- if (y_step_q4 == 16 && filter_y[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_v8_avg_ssse3(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_v8_avg_ssse3(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_v8_avg_ssse3(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_avg_vert_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
-
-void vp9_convolve8_ssse3(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- DECLARE_ALIGNED_ARRAY(16, unsigned char, fdata2, 64 * 71);
-
- assert(w <= 64);
- assert(h <= 64);
- if (x_step_q4 == 16 && y_step_q4 == 16) {
- vp9_convolve8_horiz_ssse3(src - 3 * src_stride, src_stride, fdata2, 64,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h + 7);
- vp9_convolve8_vert_ssse3(fdata2 + 3 * 64, 64, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4, w, h);
- } else {
- vp9_convolve8_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4, w, h);
- }
-}
-
-void vp9_convolve8_avg_ssse3(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- DECLARE_ALIGNED_ARRAY(16, unsigned char, fdata2, 64 * 71);
-
- assert(w <= 64);
- assert(h <= 64);
- if (x_step_q4 == 16 && y_step_q4 == 16) {
- vp9_convolve8_horiz_ssse3(src - 3 * src_stride, src_stride, fdata2, 64,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h + 7);
- vp9_convolve8_avg_vert_ssse3(fdata2 + 3 * 64, 64, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- } else {
- vp9_convolve8_avg_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4, w, h);
- }
-}
+// void vp9_convolve8_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_avg_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+FUN_CONV_2D(, ssse3);
+FUN_CONV_2D(avg_ , ssse3);
#endif
#if HAVE_SSE2
@@ -248,199 +203,55 @@
filter8_1dfunction vp9_filter_block1d4_v8_avg_sse2;
filter8_1dfunction vp9_filter_block1d4_h8_avg_sse2;
-void vp9_convolve8_horiz_sse2(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- /* Ensure the filter can be compressed to int16_t. */
- if (x_step_q4 == 16 && filter_x[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_h8_sse2(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_h8_sse2(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_h8_sse2(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_horiz_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
+filter8_1dfunction vp9_filter_block1d16_v2_sse2;
+filter8_1dfunction vp9_filter_block1d16_h2_sse2;
+filter8_1dfunction vp9_filter_block1d8_v2_sse2;
+filter8_1dfunction vp9_filter_block1d8_h2_sse2;
+filter8_1dfunction vp9_filter_block1d4_v2_sse2;
+filter8_1dfunction vp9_filter_block1d4_h2_sse2;
+filter8_1dfunction vp9_filter_block1d16_v2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d16_h2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d8_v2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d8_h2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d4_v2_avg_sse2;
+filter8_1dfunction vp9_filter_block1d4_h2_avg_sse2;
-void vp9_convolve8_vert_sse2(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- if (y_step_q4 == 16 && filter_y[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_v8_sse2(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_v8_sse2(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_v8_sse2(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_vert_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
+// void vp9_convolve8_horiz_sse2(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_vert_sse2(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_avg_horiz_sse2(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_avg_vert_sse2(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+FUN_CONV_1D(horiz, x_step_q4, filter_x, h, src, , sse2, sse2);
+FUN_CONV_1D(vert, y_step_q4, filter_y, v, src - src_stride * 3, , sse2, sse2);
+FUN_CONV_1D(avg_horiz, x_step_q4, filter_x, h, src, avg_, sse2, sse2);
+FUN_CONV_1D(avg_vert, y_step_q4, filter_y, v, src - src_stride * 3, avg_, sse2,
+ sse2);
-void vp9_convolve8_avg_horiz_sse2(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- if (x_step_q4 == 16 && filter_x[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_h8_avg_sse2(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_h8_avg_sse2(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_h8_avg_sse2(src, src_stride,
- dst, dst_stride,
- h, filter_x);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_avg_horiz_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
-
-void vp9_convolve8_avg_vert_sse2(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- if (y_step_q4 == 16 && filter_y[3] != 128) {
- while (w >= 16) {
- vp9_filter_block1d16_v8_avg_sse2(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 16;
- dst += 16;
- w -= 16;
- }
- while (w >= 8) {
- vp9_filter_block1d8_v8_avg_sse2(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 8;
- dst += 8;
- w -= 8;
- }
- while (w >= 4) {
- vp9_filter_block1d4_v8_avg_sse2(src - src_stride * 3, src_stride,
- dst, dst_stride,
- h, filter_y);
- src += 4;
- dst += 4;
- w -= 4;
- }
- }
- if (w) {
- vp9_convolve8_avg_vert_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- }
-}
-
-void vp9_convolve8_sse2(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- DECLARE_ALIGNED_ARRAY(16, unsigned char, fdata2, 64 * 71);
-
- assert(w <= 64);
- assert(h <= 64);
- if (x_step_q4 == 16 && y_step_q4 == 16) {
- vp9_convolve8_horiz_sse2(src - 3 * src_stride, src_stride, fdata2, 64,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h + 7);
- vp9_convolve8_vert_sse2(fdata2 + 3 * 64, 64, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4, w, h);
- } else {
- vp9_convolve8_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4, w, h);
- }
-}
-
-void vp9_convolve8_avg_sse2(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4,
- int w, int h) {
- DECLARE_ALIGNED_ARRAY(16, unsigned char, fdata2, 64 * 71);
-
- assert(w <= 64);
- assert(h <= 64);
- if (x_step_q4 == 16 && y_step_q4 == 16) {
- vp9_convolve8_horiz_sse2(src - 3 * src_stride, src_stride, fdata2, 64,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h + 7);
- vp9_convolve8_avg_vert_sse2(fdata2 + 3 * 64, 64, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4,
- w, h);
- } else {
- vp9_convolve8_avg_c(src, src_stride, dst, dst_stride,
- filter_x, x_step_q4, filter_y, y_step_q4, w, h);
- }
-}
+// void vp9_convolve8_sse2(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+// void vp9_convolve8_avg_sse2(const uint8_t *src, ptrdiff_t src_stride,
+// uint8_t *dst, ptrdiff_t dst_stride,
+// const int16_t *filter_x, int x_step_q4,
+// const int16_t *filter_y, int y_step_q4,
+// int w, int h);
+FUN_CONV_2D(, sse2);
+FUN_CONV_2D(avg_ , sse2);
#endif
diff --git a/vp9/common/x86/vp9_idct_intrin_sse2.c b/vp9/common/x86/vp9_idct_intrin_sse2.c
index 2f61494..13a5b5a 100644
--- a/vp9/common/x86/vp9_idct_intrin_sse2.c
+++ b/vp9/common/x86/vp9_idct_intrin_sse2.c
@@ -180,7 +180,7 @@
res[1] = _mm_unpackhi_epi16(tr0_0, tr0_1);
}
-static void idct4_1d_sse2(__m128i *in) {
+static void idct4_sse2(__m128i *in) {
const __m128i k__cospi_p16_p16 = pair_set_epi16(cospi_16_64, cospi_16_64);
const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i k__cospi_p24_m08 = pair_set_epi16(cospi_24_64, -cospi_8_64);
@@ -216,7 +216,7 @@
in[1] = _mm_shuffle_epi32(in[1], 0x4E);
}
-static void iadst4_1d_sse2(__m128i *in) {
+static void iadst4_sse2(__m128i *in) {
const __m128i k__sinpi_p01_p04 = pair_set_epi16(sinpi_1_9, sinpi_4_9);
const __m128i k__sinpi_p03_p02 = pair_set_epi16(sinpi_3_9, sinpi_2_9);
const __m128i k__sinpi_p02_m01 = pair_set_epi16(sinpi_2_9, -sinpi_1_9);
@@ -276,20 +276,20 @@
switch (tx_type) {
case 0: // DCT_DCT
- idct4_1d_sse2(in);
- idct4_1d_sse2(in);
+ idct4_sse2(in);
+ idct4_sse2(in);
break;
case 1: // ADST_DCT
- idct4_1d_sse2(in);
- iadst4_1d_sse2(in);
+ idct4_sse2(in);
+ iadst4_sse2(in);
break;
case 2: // DCT_ADST
- iadst4_1d_sse2(in);
- idct4_1d_sse2(in);
+ iadst4_sse2(in);
+ idct4_sse2(in);
break;
case 3: // ADST_ADST
- iadst4_1d_sse2(in);
- iadst4_1d_sse2(in);
+ iadst4_sse2(in);
+ iadst4_sse2(in);
break;
default:
assert(0);
@@ -455,7 +455,7 @@
res1 = _mm_packs_epi32(tmp2, tmp3); \
}
-#define IDCT8_1D(in0, in1, in2, in3, in4, in5, in6, in7, \
+#define IDCT8(in0, in1, in2, in3, in4, in5, in6, in7, \
out0, out1, out2, out3, out4, out5, out6, out7) \
{ \
/* Stage1 */ \
@@ -573,7 +573,7 @@
in0, in1, in2, in3, in4, in5, in6, in7);
// 4-stage 1D idct8x8
- IDCT8_1D(in0, in1, in2, in3, in4, in5, in6, in7,
+ IDCT8(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
}
@@ -674,7 +674,7 @@
out[3] = _mm_unpackhi_epi64(tr1_2, tr1_6);
}
-static void idct8_1d_sse2(__m128i *in) {
+static void idct8_sse2(__m128i *in) {
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
const __m128i stg1_0 = pair_set_epi16(cospi_28_64, -cospi_4_64);
const __m128i stg1_1 = pair_set_epi16(cospi_4_64, cospi_28_64);
@@ -695,11 +695,11 @@
in0, in1, in2, in3, in4, in5, in6, in7);
// 4-stage 1D idct8x8
- IDCT8_1D(in0, in1, in2, in3, in4, in5, in6, in7,
+ IDCT8(in0, in1, in2, in3, in4, in5, in6, in7,
in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7]);
}
-static void iadst8_1d_sse2(__m128i *in) {
+static void iadst8_sse2(__m128i *in) {
const __m128i k__cospi_p02_p30 = pair_set_epi16(cospi_2_64, cospi_30_64);
const __m128i k__cospi_p30_m02 = pair_set_epi16(cospi_30_64, -cospi_2_64);
const __m128i k__cospi_p10_p22 = pair_set_epi16(cospi_10_64, cospi_22_64);
@@ -946,20 +946,20 @@
switch (tx_type) {
case 0: // DCT_DCT
- idct8_1d_sse2(in);
- idct8_1d_sse2(in);
+ idct8_sse2(in);
+ idct8_sse2(in);
break;
case 1: // ADST_DCT
- idct8_1d_sse2(in);
- iadst8_1d_sse2(in);
+ idct8_sse2(in);
+ iadst8_sse2(in);
break;
case 2: // DCT_ADST
- iadst8_1d_sse2(in);
- idct8_1d_sse2(in);
+ iadst8_sse2(in);
+ idct8_sse2(in);
break;
case 3: // ADST_ADST
- iadst8_1d_sse2(in);
- iadst8_1d_sse2(in);
+ iadst8_sse2(in);
+ iadst8_sse2(in);
break;
default:
assert(0);
@@ -1104,7 +1104,7 @@
TRANSPOSE_4X8_10(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3)
- IDCT8_1D(in0, in1, in2, in3, zero, zero, zero, zero,
+ IDCT8(in0, in1, in2, in3, zero, zero, zero, zero,
in0, in1, in2, in3, in4, in5, in6, in7);
// Final rounding and shift
in0 = _mm_adds_epi16(in0, final_rounding);
@@ -1135,7 +1135,7 @@
RECON_AND_STORE(dest, in7);
}
-#define IDCT16_1D \
+#define IDCT16 \
/* Stage2 */ \
{ \
const __m128i lo_1_15 = _mm_unpacklo_epi16(in[1], in[15]); \
@@ -1264,7 +1264,7 @@
stp2_10, stp2_13, stp2_11, stp2_12) \
}
-#define IDCT16_10_1D \
+#define IDCT16_10 \
/* Stage2 */ \
{ \
const __m128i lo_1_15 = _mm_unpacklo_epi16(in[1], zero); \
@@ -1437,7 +1437,7 @@
array_transpose_8x8(in, in);
array_transpose_8x8(in+8, in+8);
- IDCT16_1D
+ IDCT16
// Stage7
curr1[0] = _mm_add_epi16(stp2_0, stp1_15);
@@ -1465,7 +1465,7 @@
array_transpose_8x8(l+i*8, in);
array_transpose_8x8(r+i*8, in+8);
- IDCT16_1D
+ IDCT16
// 2-D
in[0] = _mm_add_epi16(stp2_0, stp1_15);
@@ -1590,7 +1590,7 @@
res0[15] = tbuf[7];
}
-static void iadst16_1d_8col(__m128i *in) {
+static void iadst16_8col(__m128i *in) {
// perform 16x16 1-D ADST for 8 columns
__m128i s[16], x[16], u[32], v[32];
const __m128i k__cospi_p01_p31 = pair_set_epi16(cospi_1_64, cospi_31_64);
@@ -2060,7 +2060,7 @@
in[15] = _mm_sub_epi16(kZero, s[1]);
}
-static void idct16_1d_8col(__m128i *in) {
+static void idct16_8col(__m128i *in) {
const __m128i k__cospi_p30_m02 = pair_set_epi16(cospi_30_64, -cospi_2_64);
const __m128i k__cospi_p02_p30 = pair_set_epi16(cospi_2_64, cospi_30_64);
const __m128i k__cospi_p14_m18 = pair_set_epi16(cospi_14_64, -cospi_18_64);
@@ -2404,16 +2404,16 @@
in[15] = _mm_sub_epi16(s[0], s[15]);
}
-static void idct16_1d_sse2(__m128i *in0, __m128i *in1) {
+static void idct16_sse2(__m128i *in0, __m128i *in1) {
array_transpose_16x16(in0, in1);
- idct16_1d_8col(in0);
- idct16_1d_8col(in1);
+ idct16_8col(in0);
+ idct16_8col(in1);
}
-static void iadst16_1d_sse2(__m128i *in0, __m128i *in1) {
+static void iadst16_sse2(__m128i *in0, __m128i *in1) {
array_transpose_16x16(in0, in1);
- iadst16_1d_8col(in0);
- iadst16_1d_8col(in1);
+ iadst16_8col(in0);
+ iadst16_8col(in1);
}
static INLINE void load_buffer_8x16(const int16_t *input, __m128i *in) {
@@ -2502,20 +2502,20 @@
switch (tx_type) {
case 0: // DCT_DCT
- idct16_1d_sse2(in0, in1);
- idct16_1d_sse2(in0, in1);
+ idct16_sse2(in0, in1);
+ idct16_sse2(in0, in1);
break;
case 1: // ADST_DCT
- idct16_1d_sse2(in0, in1);
- iadst16_1d_sse2(in0, in1);
+ idct16_sse2(in0, in1);
+ iadst16_sse2(in0, in1);
break;
case 2: // DCT_ADST
- iadst16_1d_sse2(in0, in1);
- idct16_1d_sse2(in0, in1);
+ iadst16_sse2(in0, in1);
+ idct16_sse2(in0, in1);
break;
case 3: // ADST_ADST
- iadst16_1d_sse2(in0, in1);
- iadst16_1d_sse2(in0, in1);
+ iadst16_sse2(in0, in1);
+ iadst16_sse2(in0, in1);
break;
default:
assert(0);
@@ -2732,7 +2732,7 @@
for (i = 0; i < 2; i++) {
array_transpose_4X8(l + 8*i, in);
- IDCT16_10_1D
+ IDCT16_10
// Stage7
in[0] = _mm_add_epi16(stp2_0, stp1_15);
@@ -2814,7 +2814,7 @@
input += 8; \
} \
-#define IDCT32_1D_34 \
+#define IDCT32_34 \
/* Stage1 */ \
{ \
const __m128i zero = _mm_setzero_si128();\
@@ -3115,7 +3115,7 @@
}
-#define IDCT32_1D \
+#define IDCT32 \
/* Stage1 */ \
{ \
const __m128i lo_1_31 = _mm_unpacklo_epi16(in[1], in[31]); \
@@ -3554,7 +3554,7 @@
array_transpose_8x8(in+16, in+16);
array_transpose_8x8(in+24, in+24);
- IDCT32_1D
+ IDCT32
// 1_D: Store 32 intermediate results for each 8x32 block.
col[0] = _mm_add_epi16(stp1_0, stp1_31);
@@ -3593,7 +3593,7 @@
const __m128i zero = _mm_setzero_si128();
// Transpose 32x8 block to 8x32 block
array_transpose_8x8(col+i*8, in);
- IDCT32_1D_34
+ IDCT32_34
// 2_D: Calculate the results and store them to destination.
in[0] = _mm_add_epi16(stp1_0, stp1_31);
@@ -3922,7 +3922,7 @@
array_transpose_8x8(in+16, in+16);
array_transpose_8x8(in+24, in+24);
- IDCT32_1D
+ IDCT32
// 1_D: Store 32 intermediate results for each 8x32 block.
col[i32 + 0] = _mm_add_epi16(stp1_0, stp1_31);
@@ -3969,7 +3969,7 @@
array_transpose_8x8(col+j+64, in+16);
array_transpose_8x8(col+j+96, in+24);
- IDCT32_1D
+ IDCT32
// 2_D: Calculate the results and store them to destination.
in[0] = _mm_add_epi16(stp1_0, stp1_31);
diff --git a/vp9/common/x86/vp9_subpixel_bilinear_sse2.asm b/vp9/common/x86/vp9_subpixel_bilinear_sse2.asm
new file mode 100644
index 0000000..d94ccf2
--- /dev/null
+++ b/vp9/common/x86/vp9_subpixel_bilinear_sse2.asm
@@ -0,0 +1,448 @@
+;
+; Copyright (c) 2014 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.
+;
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%macro GET_PARAM_4 0
+ mov rdx, arg(5) ;filter ptr
+ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(2) ;output_ptr
+ mov rcx, 0x0400040
+
+ movdqa xmm3, [rdx] ;load filters
+ pshuflw xmm4, xmm3, 11111111b ;k3
+ psrldq xmm3, 8
+ pshuflw xmm3, xmm3, 0b ;k4
+ punpcklqdq xmm4, xmm3 ;k3k4
+
+ movq xmm3, rcx ;rounding
+ pshufd xmm3, xmm3, 0
+
+ pxor xmm2, xmm2
+
+ movsxd rax, DWORD PTR arg(1) ;pixels_per_line
+ movsxd rdx, DWORD PTR arg(3) ;out_pitch
+ movsxd rcx, DWORD PTR arg(4) ;output_height
+%endm
+
+%macro APPLY_FILTER_4 1
+
+ punpckldq xmm0, xmm1 ;two row in one register
+ punpcklbw xmm0, xmm2 ;unpack to word
+ pmullw xmm0, xmm4 ;multiply the filter factors
+
+ movdqa xmm1, xmm0
+ psrldq xmm1, 8
+ paddsw xmm0, xmm1
+
+ paddsw xmm0, xmm3 ;rounding
+ psraw xmm0, 7 ;shift
+ packuswb xmm0, xmm0 ;pack to byte
+
+%if %1
+ movd xmm1, [rdi]
+ pavgb xmm0, xmm1
+%endif
+
+ movd [rdi], xmm0
+ lea rsi, [rsi + rax]
+ lea rdi, [rdi + rdx]
+ dec rcx
+%endm
+
+%macro GET_PARAM 0
+ mov rdx, arg(5) ;filter ptr
+ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(2) ;output_ptr
+ mov rcx, 0x0400040
+
+ movdqa xmm7, [rdx] ;load filters
+
+ pshuflw xmm6, xmm7, 11111111b ;k3
+ pshufhw xmm7, xmm7, 0b ;k4
+ punpcklwd xmm6, xmm6
+ punpckhwd xmm7, xmm7
+
+ movq xmm4, rcx ;rounding
+ pshufd xmm4, xmm4, 0
+
+ pxor xmm5, xmm5
+
+ movsxd rax, DWORD PTR arg(1) ;pixels_per_line
+ movsxd rdx, DWORD PTR arg(3) ;out_pitch
+ movsxd rcx, DWORD PTR arg(4) ;output_height
+%endm
+
+%macro APPLY_FILTER_8 1
+ punpcklbw xmm0, xmm5
+ punpcklbw xmm1, xmm5
+
+ pmullw xmm0, xmm6
+ pmullw xmm1, xmm7
+ paddsw xmm0, xmm1
+ paddsw xmm0, xmm4 ;rounding
+ psraw xmm0, 7 ;shift
+ packuswb xmm0, xmm0 ;pack back to byte
+%if %1
+ movq xmm1, [rdi]
+ pavgb xmm0, xmm1
+%endif
+ movq [rdi], xmm0 ;store the result
+
+ lea rsi, [rsi + rax]
+ lea rdi, [rdi + rdx]
+ dec rcx
+%endm
+
+%macro APPLY_FILTER_16 1
+ punpcklbw xmm0, xmm5
+ punpcklbw xmm1, xmm5
+ punpckhbw xmm2, xmm5
+ punpckhbw xmm3, xmm5
+
+ pmullw xmm0, xmm6
+ pmullw xmm1, xmm7
+ pmullw xmm2, xmm6
+ pmullw xmm3, xmm7
+
+ paddsw xmm0, xmm1
+ paddsw xmm2, xmm3
+
+ paddsw xmm0, xmm4 ;rounding
+ paddsw xmm2, xmm4
+ psraw xmm0, 7 ;shift
+ psraw xmm2, 7
+ packuswb xmm0, xmm2 ;pack back to byte
+%if %1
+ movdqu xmm1, [rdi]
+ pavgb xmm0, xmm1
+%endif
+ movdqu [rdi], xmm0 ;store the result
+
+ lea rsi, [rsi + rax]
+ lea rdi, [rdi + rdx]
+ dec rcx
+%endm
+
+global sym(vp9_filter_block1d4_v2_sse2) PRIVATE
+sym(vp9_filter_block1d4_v2_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM_4
+.loop:
+ movd xmm0, [rsi] ;load src
+ movd xmm1, [rsi + rax]
+
+ APPLY_FILTER_4 0
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d8_v2_sse2) PRIVATE
+sym(vp9_filter_block1d8_v2_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movq xmm0, [rsi] ;0
+ movq xmm1, [rsi + rax] ;1
+
+ APPLY_FILTER_8 0
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d16_v2_sse2) PRIVATE
+sym(vp9_filter_block1d16_v2_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movdqu xmm0, [rsi] ;0
+ movdqu xmm1, [rsi + rax] ;1
+ movdqa xmm2, xmm0
+ movdqa xmm3, xmm1
+
+ APPLY_FILTER_16 0
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d4_v2_avg_sse2) PRIVATE
+sym(vp9_filter_block1d4_v2_avg_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM_4
+.loop:
+ movd xmm0, [rsi] ;load src
+ movd xmm1, [rsi + rax]
+
+ APPLY_FILTER_4 1
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d8_v2_avg_sse2) PRIVATE
+sym(vp9_filter_block1d8_v2_avg_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movq xmm0, [rsi] ;0
+ movq xmm1, [rsi + rax] ;1
+
+ APPLY_FILTER_8 1
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d16_v2_avg_sse2) PRIVATE
+sym(vp9_filter_block1d16_v2_avg_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movdqu xmm0, [rsi] ;0
+ movdqu xmm1, [rsi + rax] ;1
+ movdqa xmm2, xmm0
+ movdqa xmm3, xmm1
+
+ APPLY_FILTER_16 1
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d4_h2_sse2) PRIVATE
+sym(vp9_filter_block1d4_h2_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM_4
+.loop:
+ movdqu xmm0, [rsi] ;load src
+ movdqa xmm1, xmm0
+ psrldq xmm1, 1
+
+ APPLY_FILTER_4 0
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d8_h2_sse2) PRIVATE
+sym(vp9_filter_block1d8_h2_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movdqu xmm0, [rsi] ;load src
+ movdqa xmm1, xmm0
+ psrldq xmm1, 1
+
+ APPLY_FILTER_8 0
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d16_h2_sse2) PRIVATE
+sym(vp9_filter_block1d16_h2_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movdqu xmm0, [rsi] ;load src
+ movdqu xmm1, [rsi + 1]
+ movdqa xmm2, xmm0
+ movdqa xmm3, xmm1
+
+ APPLY_FILTER_16 0
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d4_h2_avg_sse2) PRIVATE
+sym(vp9_filter_block1d4_h2_avg_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM_4
+.loop:
+ movdqu xmm0, [rsi] ;load src
+ movdqa xmm1, xmm0
+ psrldq xmm1, 1
+
+ APPLY_FILTER_4 1
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d8_h2_avg_sse2) PRIVATE
+sym(vp9_filter_block1d8_h2_avg_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movdqu xmm0, [rsi] ;load src
+ movdqa xmm1, xmm0
+ psrldq xmm1, 1
+
+ APPLY_FILTER_8 1
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+global sym(vp9_filter_block1d16_h2_avg_sse2) PRIVATE
+sym(vp9_filter_block1d16_h2_avg_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ SAVE_XMM 7
+ push rsi
+ push rdi
+ ; end prolog
+
+ GET_PARAM
+.loop:
+ movdqu xmm0, [rsi] ;load src
+ movdqu xmm1, [rsi + 1]
+ movdqa xmm2, xmm0
+ movdqa xmm3, xmm1
+
+ APPLY_FILTER_16 1
+ jnz .loop
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 1d9be53..93ef750 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -33,18 +33,12 @@
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/decoder/vp9_decodemv.h"
#include "vp9/decoder/vp9_dsubexp.h"
+#include "vp9/decoder/vp9_dthread.h"
#include "vp9/decoder/vp9_onyxd_int.h"
#include "vp9/decoder/vp9_read_bit_buffer.h"
#include "vp9/decoder/vp9_reader.h"
#include "vp9/decoder/vp9_thread.h"
-typedef struct TileWorkerData {
- VP9_COMMON *cm;
- vp9_reader bit_reader;
- DECLARE_ALIGNED(16, MACROBLOCKD, xd);
- DECLARE_ALIGNED(16, int16_t, dqcoeff[MAX_MB_PLANE][64 * 64]);
-} TileWorkerData;
-
static int read_be32(const uint8_t *p) {
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
@@ -413,8 +407,8 @@
if (!is_inter_block(mbmi)) {
struct intra_args arg = { cm, xd, r };
- foreach_transformed_block(xd, bsize, predict_and_reconstruct_intra_block,
- &arg);
+ vp9_foreach_transformed_block(xd, bsize,
+ predict_and_reconstruct_intra_block, &arg);
} else {
// Setup
set_ref(cm, xd, 0, mi_row, mi_col);
@@ -430,7 +424,7 @@
if (!mbmi->skip_coeff) {
int eobtotal = 0;
struct inter_args arg = { cm, xd, r, &eobtotal };
- foreach_transformed_block(xd, bsize, reconstruct_inter_block, &arg);
+ vp9_foreach_transformed_block(xd, bsize, reconstruct_inter_block, &arg);
if (!less8x8 && eobtotal == 0)
mbmi->skip_coeff = 1; // skip loopfilter
}
@@ -982,7 +976,6 @@
++pbi->num_tile_workers;
vp9_worker_init(worker);
- worker->hook = (VP9WorkerHook)tile_worker_hook;
CHECK_MEM_ERROR(cm, worker->data1,
vpx_memalign(32, sizeof(TileWorkerData)));
CHECK_MEM_ERROR(cm, worker->data2, vpx_malloc(sizeof(TileInfo)));
@@ -993,6 +986,11 @@
}
}
+ // Reset tile decoding hook
+ for (n = 0; n < pbi->num_tile_workers; ++n) {
+ pbi->tile_workers[n].hook = (VP9WorkerHook)tile_worker_hook;
+ }
+
// Note: this memset assumes above_context[0], [1] and [2]
// are allocated as part of the same buffer.
vpx_memset(pbi->above_context[0], 0,
@@ -1117,7 +1115,7 @@
if (cm->show_existing_frame) {
// Show an existing frame directly.
int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
- ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->new_fb_idx, frame_to_show);
+ ref_cnt_fb(cm->frame_bufs, &cm->new_fb_idx, frame_to_show);
pbi->refresh_frame_flags = 0;
cm->lf.filter_level = 0;
cm->show_frame = 1;
@@ -1177,7 +1175,7 @@
const int ref = vp9_rb_read_literal(rb, REF_FRAMES_LOG2);
const int idx = cm->ref_frame_map[ref];
cm->frame_refs[i].idx = idx;
- cm->frame_refs[i].buf = &cm->yv12_fb[idx];
+ cm->frame_refs[i].buf = &cm->frame_bufs[idx].buf;
cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb);
}
@@ -1245,8 +1243,8 @@
read_tx_mode_probs(&fc->tx_probs, &r);
read_coef_probs(fc, cm->tx_mode, &r);
- for (k = 0; k < MBSKIP_CONTEXTS; ++k)
- vp9_diff_update_prob(&r, &fc->mbskip_probs[k]);
+ for (k = 0; k < SKIP_CONTEXTS; ++k)
+ vp9_diff_update_prob(&r, &fc->skip_probs[k]);
if (!frame_is_intra_only(cm)) {
nmv_context *const nmvc = &fc->nmvc;
@@ -1321,8 +1319,7 @@
assert(!memcmp(cm->counts.comp_ref, zero_counts.comp_ref,
sizeof(cm->counts.comp_ref)));
assert(!memcmp(&cm->counts.tx, &zero_counts.tx, sizeof(cm->counts.tx)));
- assert(!memcmp(cm->counts.mbskip, zero_counts.mbskip,
- sizeof(cm->counts.mbskip)));
+ assert(!memcmp(cm->counts.skip, zero_counts.skip, sizeof(cm->counts.skip)));
assert(!memcmp(&cm->counts.mv, &zero_counts.mv, sizeof(cm->counts.mv)));
}
#endif // NDEBUG
@@ -1374,7 +1371,7 @@
set_prev_mi(cm);
setup_plane_dequants(cm, xd, cm->base_qindex);
- setup_block_dptrs(xd, cm->subsampling_x, cm->subsampling_y);
+ vp9_setup_block_planes(xd, cm->subsampling_x, cm->subsampling_y);
cm->fc = cm->frame_contexts[cm->frame_context_idx];
vp9_zero(cm->counts);
@@ -1393,9 +1390,6 @@
*p_data_end = decode_tiles(pbi, data + first_partition_size);
}
- cm->last_width = cm->width;
- cm->last_height = cm->height;
-
new_fb->corrupted |= xd->corrupted;
if (!pbi->decoded_key_frame) {
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index d7cd635..c7fb71d 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -152,9 +152,9 @@
return 1;
} else {
const int ctx = vp9_get_skip_context(xd);
- const int skip = vp9_read(r, cm->fc.mbskip_probs[ctx]);
+ const int skip = vp9_read(r, cm->fc.skip_probs[ctx]);
if (!cm->frame_parallel_decoding_mode)
- ++cm->counts.mbskip[ctx][skip];
+ ++cm->counts.skip[ctx][skip];
return skip;
}
}
@@ -175,8 +175,8 @@
mbmi->ref_frame[1] = NONE;
if (bsize >= BLOCK_8X8) {
- const MB_PREDICTION_MODE A = above_block_mode(mi, above_mi, 0);
- const MB_PREDICTION_MODE L = left_block_mode(mi, left_mi, 0);
+ const MB_PREDICTION_MODE A = vp9_above_block_mode(mi, above_mi, 0);
+ const MB_PREDICTION_MODE L = vp9_left_block_mode(mi, left_mi, 0);
mbmi->mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]);
} else {
// Only 4x4, 4x8, 8x4 blocks
@@ -187,8 +187,8 @@
for (idy = 0; idy < 2; idy += num_4x4_h) {
for (idx = 0; idx < 2; idx += num_4x4_w) {
const int ib = idy * 2 + idx;
- const MB_PREDICTION_MODE A = above_block_mode(mi, above_mi, ib);
- const MB_PREDICTION_MODE L = left_block_mode(mi, left_mi, ib);
+ const MB_PREDICTION_MODE A = vp9_above_block_mode(mi, above_mi, ib);
+ const MB_PREDICTION_MODE L = vp9_left_block_mode(mi, left_mi, ib);
const MB_PREDICTION_MODE b_mode = read_intra_mode(r,
vp9_kf_y_mode_prob[A][L]);
mi->bmi[ib].as_mode = b_mode;
diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c
index 18cafba..52e78cd 100644
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -204,7 +204,7 @@
const int eob = decode_coefs(cm, xd, pd->plane_type,
BLOCK_OFFSET(pd->dqcoeff, block), tx_size,
pd->dequant, ctx, so->scan, so->neighbors, r);
- set_contexts(xd, pd, plane_bsize, tx_size, eob > 0, x, y);
+ vp9_set_contexts(xd, pd, plane_bsize, tx_size, eob > 0, x, y);
return eob;
}
diff --git a/vp9/decoder/vp9_dsubexp.c b/vp9/decoder/vp9_dsubexp.c
index fcca017..e67b372 100644
--- a/vp9/decoder/vp9_dsubexp.c
+++ b/vp9/decoder/vp9_dsubexp.c
@@ -19,14 +19,10 @@
return v % 2 ? m - (v + 1) / 2 : m + v / 2;
}
-static int decode_uniform(vp9_reader *r, int n) {
- int v;
- const int l = get_unsigned_bits(n);
- const int m = (1 << l) - n;
- if (!l)
- return 0;
-
- v = vp9_read_literal(r, l - 1);
+static int decode_uniform(vp9_reader *r) {
+ const int l = 8;
+ const int m = (1 << l) - 191;
+ const int v = vp9_read_literal(r, l - 1);
return v < m ? v : (v << 1) - m + vp9_read_bit(r);
}
@@ -78,30 +74,19 @@
}
}
-static int decode_term_subexp(vp9_reader *r, int k, int num_syms) {
- int i = 0, mk = 0, word;
- while (1) {
- const int b = i ? k + i - 1 : k;
- const int a = 1 << b;
- if (num_syms <= mk + 3 * a) {
- word = decode_uniform(r, num_syms - mk) + mk;
- break;
- } else {
- if (vp9_read_bit(r)) {
- i++;
- mk += a;
- } else {
- word = vp9_read_literal(r, b) + mk;
- break;
- }
- }
- }
- return word;
+static int decode_term_subexp(vp9_reader *r) {
+ if (!vp9_read_bit(r))
+ return vp9_read_literal(r, 4);
+ if (!vp9_read_bit(r))
+ return vp9_read_literal(r, 4) + 16;
+ if (!vp9_read_bit(r))
+ return vp9_read_literal(r, 5) + 32;
+ return decode_uniform(r) + 64;
}
void vp9_diff_update_prob(vp9_reader *r, vp9_prob* p) {
if (vp9_read(r, DIFF_UPDATE_PROB)) {
- const int delp = decode_term_subexp(r, SUBEXP_PARAM, 255);
+ const int delp = decode_term_subexp(r);
*p = (vp9_prob)inv_remap_prob(delp, *p);
}
}
diff --git a/vp9/decoder/vp9_dthread.c b/vp9/decoder/vp9_dthread.c
new file mode 100644
index 0000000..128b9f8
--- /dev/null
+++ b/vp9/decoder/vp9_dthread.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#include "./vpx_config.h"
+#include "vp9/common/vp9_reconinter.h"
+#include "vp9/decoder/vp9_dthread.h"
+#include "vp9/decoder/vp9_onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+
+#if CONFIG_MULTITHREAD
+static INLINE void mutex_lock(pthread_mutex_t *const mutex) {
+ const int kMaxTryLocks = 4000;
+ int locked = 0;
+ int i;
+
+ for (i = 0; i < kMaxTryLocks; ++i) {
+ if (!pthread_mutex_trylock(mutex)) {
+ locked = 1;
+ break;
+ }
+ }
+
+ if (!locked)
+ pthread_mutex_lock(mutex);
+}
+#endif // CONFIG_MULTITHREAD
+
+static INLINE void sync_read(VP9LfSync *const lf_sync, int r, int c) {
+#if CONFIG_MULTITHREAD
+ const int nsync = lf_sync->sync_range;
+
+ if (r && !(c & (nsync - 1))) {
+ mutex_lock(&lf_sync->mutex_[r - 1]);
+
+ while (c > lf_sync->cur_sb_col[r - 1] - nsync) {
+ pthread_cond_wait(&lf_sync->cond_[r - 1],
+ &lf_sync->mutex_[r - 1]);
+ }
+ pthread_mutex_unlock(&lf_sync->mutex_[r - 1]);
+ }
+#else
+ (void)lf_sync;
+ (void)r;
+ (void)c;
+#endif // CONFIG_MULTITHREAD
+}
+
+static INLINE void sync_write(VP9LfSync *const lf_sync, int r, int c,
+ const int sb_cols) {
+#if CONFIG_MULTITHREAD
+ const int nsync = lf_sync->sync_range;
+ int cur;
+ // Only signal when there are enough filtered SB for next row to run.
+ int sig = 1;
+
+ if (c < sb_cols - 1) {
+ cur = c;
+ if (c % nsync)
+ sig = 0;
+ } else {
+ cur = sb_cols + nsync;
+ }
+
+ if (sig) {
+ mutex_lock(&lf_sync->mutex_[r]);
+
+ lf_sync->cur_sb_col[r] = cur;
+
+ pthread_cond_signal(&lf_sync->cond_[r]);
+ pthread_mutex_unlock(&lf_sync->mutex_[r]);
+ }
+#else
+ (void)lf_sync;
+ (void)r;
+ (void)c;
+ (void)sb_cols;
+#endif // CONFIG_MULTITHREAD
+}
+
+// Implement row loopfiltering for each thread.
+static void loop_filter_rows_mt(const YV12_BUFFER_CONFIG *const frame_buffer,
+ VP9_COMMON *const cm, MACROBLOCKD *const xd,
+ int start, int stop, int y_only,
+ VP9LfSync *const lf_sync, int num_lf_workers) {
+ const int num_planes = y_only ? 1 : MAX_MB_PLANE;
+ int r, c; // SB row and col
+ LOOP_FILTER_MASK lfm;
+ const int sb_cols = mi_cols_aligned_to_sb(cm->mi_cols) >> MI_BLOCK_SIZE_LOG2;
+
+ for (r = start; r < stop; r += num_lf_workers) {
+ const int mi_row = r << MI_BLOCK_SIZE_LOG2;
+ MODE_INFO **mi_8x8 = cm->mi_grid_visible + mi_row * cm->mode_info_stride;
+
+ for (c = 0; c < sb_cols; ++c) {
+ const int mi_col = c << MI_BLOCK_SIZE_LOG2;
+ int plane;
+
+ sync_read(lf_sync, r, c);
+
+ setup_dst_planes(xd, frame_buffer, mi_row, mi_col);
+ vp9_setup_mask(cm, mi_row, mi_col, mi_8x8 + mi_col, cm->mode_info_stride,
+ &lfm);
+
+ for (plane = 0; plane < num_planes; ++plane) {
+ vp9_filter_block_plane(cm, &xd->plane[plane], mi_row, &lfm);
+ }
+
+ sync_write(lf_sync, r, c, sb_cols);
+ }
+ }
+}
+
+// Row-based multi-threaded loopfilter hook
+static int loop_filter_row_worker(void *arg1, void *arg2) {
+ TileWorkerData *const tile_data = (TileWorkerData*)arg1;
+ LFWorkerData *const lf_data = &tile_data->lfdata;
+
+ loop_filter_rows_mt(lf_data->frame_buffer, lf_data->cm, &lf_data->xd,
+ lf_data->start, lf_data->stop, lf_data->y_only,
+ lf_data->lf_sync, lf_data->num_lf_workers);
+ return 1;
+}
+
+// VP9 decoder: Implement multi-threaded loopfilter that uses the tile
+// threads.
+void vp9_loop_filter_frame_mt(VP9D_COMP *pbi,
+ VP9_COMMON *cm,
+ MACROBLOCKD *xd,
+ int frame_filter_level,
+ int y_only, int partial_frame) {
+ // Number of superblock rows and cols
+ const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
+ int i;
+
+ // Allocate memory used in thread synchronization.
+ // This always needs to be done even if frame_filter_level is 0.
+ if (!cm->current_video_frame || cm->last_height != cm->height) {
+ VP9LfSync *const lf_sync = &pbi->lf_row_sync;
+
+ if (cm->last_height != cm->height) {
+ const int aligned_last_height =
+ ALIGN_POWER_OF_TWO(cm->last_height, MI_SIZE_LOG2);
+ const int last_sb_rows =
+ mi_cols_aligned_to_sb(aligned_last_height >> MI_SIZE_LOG2) >>
+ MI_BLOCK_SIZE_LOG2;
+
+ vp9_loop_filter_dealloc(lf_sync, last_sb_rows);
+ }
+
+ vp9_loop_filter_alloc(cm, lf_sync, sb_rows, cm->width);
+ }
+
+ if (!frame_filter_level) return;
+
+ vp9_loop_filter_frame_init(cm, frame_filter_level);
+
+ // Initialize cur_sb_col to -1 for all SB rows.
+ vpx_memset(pbi->lf_row_sync.cur_sb_col, -1,
+ sizeof(*pbi->lf_row_sync.cur_sb_col) * sb_rows);
+
+ // Set up loopfilter thread data.
+ for (i = 0; i < pbi->num_tile_workers; ++i) {
+ VP9Worker *const worker = &pbi->tile_workers[i];
+ TileWorkerData *const tile_data = (TileWorkerData*)worker->data1;
+ LFWorkerData *const lf_data = &tile_data->lfdata;
+
+ worker->hook = (VP9WorkerHook)loop_filter_row_worker;
+
+ // Loopfilter data
+ lf_data->frame_buffer = get_frame_new_buffer(cm);
+ lf_data->cm = cm;
+ lf_data->xd = pbi->mb;
+ lf_data->start = i;
+ lf_data->stop = sb_rows;
+ lf_data->y_only = y_only; // always do all planes in decoder
+
+ lf_data->lf_sync = &pbi->lf_row_sync;
+ lf_data->num_lf_workers = pbi->num_tile_workers;
+
+ // Start loopfiltering
+ if (i == pbi->num_tile_workers - 1) {
+ vp9_worker_execute(worker);
+ } else {
+ vp9_worker_launch(worker);
+ }
+ }
+
+ // Wait till all rows are finished
+ for (i = 0; i < pbi->num_tile_workers; ++i) {
+ vp9_worker_sync(&pbi->tile_workers[i]);
+ }
+}
+
+// Set up nsync by width.
+static int get_sync_range(int width) {
+ // nsync numbers are picked by testing. For example, for 4k
+ // video, using 4 gives best performance.
+ if (width < 640)
+ return 1;
+ else if (width <= 1280)
+ return 2;
+ else if (width <= 4096)
+ return 4;
+ else
+ return 8;
+}
+
+// Allocate memory for lf row synchronization
+void vp9_loop_filter_alloc(VP9_COMMON *cm, VP9LfSync *lf_sync, int rows,
+ int width) {
+#if CONFIG_MULTITHREAD
+ int i;
+
+ CHECK_MEM_ERROR(cm, lf_sync->mutex_,
+ vpx_malloc(sizeof(*lf_sync->mutex_) * rows));
+ CHECK_MEM_ERROR(cm, lf_sync->cond_,
+ vpx_malloc(sizeof(*lf_sync->cond_) * rows));
+
+ for (i = 0; i < rows; ++i) {
+ pthread_mutex_init(&lf_sync->mutex_[i], NULL);
+ pthread_cond_init(&lf_sync->cond_[i], NULL);
+ }
+#endif // CONFIG_MULTITHREAD
+
+ CHECK_MEM_ERROR(cm, lf_sync->cur_sb_col,
+ vpx_malloc(sizeof(*lf_sync->cur_sb_col) * rows));
+
+ // Set up nsync.
+ lf_sync->sync_range = get_sync_range(width);
+}
+
+// Deallocate lf synchronization related mutex and data
+void vp9_loop_filter_dealloc(VP9LfSync *lf_sync, int rows) {
+#if CONFIG_MULTITHREAD
+ if (lf_sync != NULL) {
+ int i;
+
+ for (i = 0; i < rows; ++i) {
+ pthread_mutex_destroy(&lf_sync->mutex_[i]);
+ pthread_cond_destroy(&lf_sync->cond_[i]);
+ }
+
+ vpx_free(lf_sync->mutex_);
+ vpx_free(lf_sync->cond_);
+ vpx_free(lf_sync->cur_sb_col);
+ }
+#else
+ (void)rows;
+ if (lf_sync != NULL)
+ vpx_free(lf_sync->cur_sb_col);
+#endif // CONFIG_MULTITHREAD
+}
diff --git a/vp9/decoder/vp9_dthread.h b/vp9/decoder/vp9_dthread.h
new file mode 100644
index 0000000..6d4450f
--- /dev/null
+++ b/vp9/decoder/vp9_dthread.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#ifndef VP9_DECODER_VP9_DTHREAD_H_
+#define VP9_DECODER_VP9_DTHREAD_H_
+
+#include "./vpx_config.h"
+#include "vp9/common/vp9_loopfilter.h"
+#include "vp9/decoder/vp9_reader.h"
+#include "vp9/decoder/vp9_thread.h"
+
+struct macroblockd;
+struct VP9Common;
+struct VP9Decompressor;
+
+typedef struct TileWorkerData {
+ struct VP9Common *cm;
+ vp9_reader bit_reader;
+ DECLARE_ALIGNED(16, struct macroblockd, xd);
+ DECLARE_ALIGNED(16, int16_t, dqcoeff[MAX_MB_PLANE][64 * 64]);
+
+ // Row-based parallel loopfilter data
+ LFWorkerData lfdata;
+} TileWorkerData;
+
+// Loopfilter row synchronization
+typedef struct VP9LfSyncData {
+#if CONFIG_MULTITHREAD
+ pthread_mutex_t *mutex_;
+ pthread_cond_t *cond_;
+#endif
+ // Allocate memory to store the loop-filtered superblock index in each row.
+ int *cur_sb_col;
+ // The optimal sync_range for different resolution and platform should be
+ // determined by testing. Currently, it is chosen to be a power-of-2 number.
+ int sync_range;
+} VP9LfSync;
+
+// Allocate memory for loopfilter row synchronization.
+void vp9_loop_filter_alloc(struct VP9Common *cm, struct VP9LfSyncData *lf_sync,
+ int rows, int width);
+
+// Deallocate loopfilter synchronization related mutex and data.
+void vp9_loop_filter_dealloc(struct VP9LfSyncData *lf_sync, int rows);
+
+// Multi-threaded loopfilter that uses the tile threads.
+void vp9_loop_filter_frame_mt(struct VP9Decompressor *pbi,
+ struct VP9Common *cm,
+ struct macroblockd *xd,
+ int frame_filter_level,
+ int y_only, int partial_frame);
+
+#endif // VP9_DECODER_VP9_DTHREAD_H_
diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c
index 75d52c2..803d536 100644
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -27,6 +27,7 @@
#include "vpx_ports/vpx_timer.h"
#include "vp9/decoder/vp9_decodeframe.h"
#include "vp9/decoder/vp9_detokenize.h"
+#include "vp9/decoder/vp9_dthread.h"
#include "./vpx_scale_rtcd.h"
#define WRITE_RECON_BUFFER 0
@@ -177,13 +178,24 @@
vpx_free(worker->data2);
}
vpx_free(pbi->tile_workers);
+
+ if (pbi->num_tile_workers) {
+ VP9_COMMON *const cm = &pbi->common;
+ const int sb_rows =
+ mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
+ VP9LfSync *const lf_sync = &pbi->lf_row_sync;
+
+ vp9_loop_filter_dealloc(lf_sync, sb_rows);
+ }
+
vpx_free(pbi->mi_streams);
vpx_free(pbi->above_context[0]);
vpx_free(pbi->above_seg_context);
vpx_free(pbi);
}
-static int equal_dimensions(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
+static int equal_dimensions(const YV12_BUFFER_CONFIG *a,
+ const YV12_BUFFER_CONFIG *b) {
return a->y_height == b->y_height && a->y_width == b->y_width &&
a->uv_height == b->uv_height && a->uv_width == b->uv_width;
}
@@ -200,7 +212,8 @@
* later commit that adds VP9-specific controls for this functionality.
*/
if (ref_frame_flag == VP9_LAST_FLAG) {
- YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[0]];
+ const YV12_BUFFER_CONFIG *const cfg =
+ &cm->frame_bufs[cm->ref_frame_map[0]].buf;
if (!equal_dimensions(cfg, sd))
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
"Incorrect buffer dimensions");
@@ -246,13 +259,13 @@
// Find an empty frame buffer.
const int free_fb = get_free_fb(cm);
- // Decrease fb_idx_ref_cnt since it will be increased again in
+ // Decrease ref_count since it will be increased again in
// ref_cnt_fb() below.
- cm->fb_idx_ref_cnt[free_fb]--;
+ cm->frame_bufs[free_fb].ref_count--;
// Manage the reference counters and copy image.
- ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
- ref_buf->buf = &cm->yv12_fb[*ref_fb_ptr];
+ ref_cnt_fb(cm->frame_bufs, ref_fb_ptr, free_fb);
+ ref_buf->buf = &cm->frame_bufs[*ref_fb_ptr].buf;
vp8_yv12_copy_frame(sd, ref_buf->buf);
}
@@ -267,7 +280,7 @@
if (index < 0 || index >= REF_FRAMES)
return -1;
- *fb = &cm->yv12_fb[cm->ref_frame_map[index]];
+ *fb = &cm->frame_bufs[cm->ref_frame_map[index]].buf;
return 0;
}
@@ -278,13 +291,13 @@
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
if (mask & 1)
- ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index],
+ ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index],
cm->new_fb_idx);
++ref_index;
}
cm->frame_to_show = get_frame_new_buffer(cm);
- cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+ cm->frame_bufs[cm->new_fb_idx].ref_count--;
// Invalidate these references until the next frame starts.
for (ref_index = 0; ref_index < 3; ref_index++)
@@ -340,8 +353,8 @@
if (cm->frame_refs[0].idx != INT_MAX)
cm->frame_refs[0].buf->corrupted = 1;
- if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
- cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+ if (cm->frame_bufs[cm->new_fb_idx].ref_count > 0)
+ cm->frame_bufs[cm->new_fb_idx].ref_count--;
return -1;
}
@@ -353,8 +366,8 @@
if (retcode < 0) {
cm->error.error_code = VPX_CODEC_ERROR;
cm->error.setjmp = 0;
- if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
- cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+ if (cm->frame_bufs[cm->new_fb_idx].ref_count > 0)
+ cm->frame_bufs[cm->new_fb_idx].ref_count--;
return retcode;
}
@@ -370,7 +383,13 @@
#endif
if (!pbi->do_loopfilter_inline) {
- vp9_loop_filter_frame(cm, &pbi->mb, pbi->common.lf.filter_level, 0, 0);
+ // If multiple threads are used to decode tiles, then we use those threads
+ // to do parallel loopfiltering.
+ if (pbi->num_tile_workers) {
+ vp9_loop_filter_frame_mt(pbi, cm, &pbi->mb, cm->lf.filter_level, 0, 0);
+ } else {
+ vp9_loop_filter_frame(cm, &pbi->mb, cm->lf.filter_level, 0, 0);
+ }
}
#if WRITE_RECON_BUFFER == 2
@@ -390,7 +409,11 @@
vp9_clear_system_state();
- cm->last_show_frame = cm->show_frame;
+ cm->last_width = cm->width;
+ cm->last_height = cm->height;
+
+ if (!cm->show_existing_frame)
+ cm->last_show_frame = cm->show_frame;
if (cm->show_frame) {
if (!cm->show_existing_frame) {
// current mip will be the prev_mip for the next frame
diff --git a/vp9/decoder/vp9_onyxd_int.h b/vp9/decoder/vp9_onyxd_int.h
index 242c600..6c6c239 100644
--- a/vp9/decoder/vp9_onyxd_int.h
+++ b/vp9/decoder/vp9_onyxd_int.h
@@ -14,6 +14,7 @@
#include "./vpx_config.h"
#include "vp9/common/vp9_onyxc_int.h"
+#include "vp9/decoder/vp9_dthread.h"
#include "vp9/decoder/vp9_onyxd.h"
#include "vp9/decoder/vp9_thread.h"
@@ -49,6 +50,8 @@
VP9Worker *tile_workers;
int num_tile_workers;
+ VP9LfSync lf_row_sync;
+
/* Each tile column has its own MODE_INFO stream. This array indexes them by
tile column index. */
MODE_INFO **mi_streams;
diff --git a/vp9/decoder/vp9_thread.c b/vp9/decoder/vp9_thread.c
index d953e72..5d31d3d 100644
--- a/vp9/decoder/vp9_thread.c
+++ b/vp9/decoder/vp9_thread.c
@@ -24,116 +24,6 @@
#if CONFIG_MULTITHREAD
-#if defined(_WIN32)
-
-//------------------------------------------------------------------------------
-// simplistic pthread emulation layer
-
-#include <process.h> // NOLINT
-
-// _beginthreadex requires __stdcall
-#define THREADFN unsigned int __stdcall
-#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val)
-
-static int pthread_create(pthread_t* const thread, const void* attr,
- unsigned int (__stdcall *start)(void*), void* arg) {
- (void)attr;
- *thread = (pthread_t)_beginthreadex(NULL, /* void *security */
- 0, /* unsigned stack_size */
- start,
- arg,
- 0, /* unsigned initflag */
- NULL); /* unsigned *thrdaddr */
- if (*thread == NULL) return 1;
- SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL);
- return 0;
-}
-
-static int pthread_join(pthread_t thread, void** value_ptr) {
- (void)value_ptr;
- return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 ||
- CloseHandle(thread) == 0);
-}
-
-// Mutex
-static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) {
- (void)mutexattr;
- InitializeCriticalSection(mutex);
- return 0;
-}
-
-static int pthread_mutex_lock(pthread_mutex_t* const mutex) {
- EnterCriticalSection(mutex);
- return 0;
-}
-
-static int pthread_mutex_unlock(pthread_mutex_t* const mutex) {
- LeaveCriticalSection(mutex);
- return 0;
-}
-
-static int pthread_mutex_destroy(pthread_mutex_t* const mutex) {
- DeleteCriticalSection(mutex);
- return 0;
-}
-
-// Condition
-static int pthread_cond_destroy(pthread_cond_t* const condition) {
- int ok = 1;
- ok &= (CloseHandle(condition->waiting_sem_) != 0);
- ok &= (CloseHandle(condition->received_sem_) != 0);
- ok &= (CloseHandle(condition->signal_event_) != 0);
- return !ok;
-}
-
-static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) {
- (void)cond_attr;
- condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
- condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
- condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (condition->waiting_sem_ == NULL ||
- condition->received_sem_ == NULL ||
- condition->signal_event_ == NULL) {
- pthread_cond_destroy(condition);
- return 1;
- }
- return 0;
-}
-
-static int pthread_cond_signal(pthread_cond_t* const condition) {
- int ok = 1;
- if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) {
- // a thread is waiting in pthread_cond_wait: allow it to be notified
- ok = SetEvent(condition->signal_event_);
- // wait until the event is consumed so the signaler cannot consume
- // the event via its own pthread_cond_wait.
- ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
- WAIT_OBJECT_0);
- }
- return !ok;
-}
-
-static int pthread_cond_wait(pthread_cond_t* const condition,
- pthread_mutex_t* const mutex) {
- int ok;
- // note that there is a consumer available so the signal isn't dropped in
- // pthread_cond_signal
- if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
- return 1;
- // now unlock the mutex so pthread_cond_signal may be issued
- pthread_mutex_unlock(mutex);
- ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
- WAIT_OBJECT_0);
- ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
- pthread_mutex_lock(mutex);
- return !ok;
-}
-
-#else // _WIN32
-# define THREADFN void*
-# define THREAD_RETURN(val) val
-#endif
-
//------------------------------------------------------------------------------
static THREADFN thread_loop(void *ptr) { // thread loop
diff --git a/vp9/decoder/vp9_thread.h b/vp9/decoder/vp9_thread.h
index bc69cfa..2f8728d 100644
--- a/vp9/decoder/vp9_thread.h
+++ b/vp9/decoder/vp9_thread.h
@@ -26,7 +26,8 @@
#if CONFIG_MULTITHREAD
#if defined(_WIN32)
-
+#include <errno.h> // NOLINT
+#include <process.h> // NOLINT
#include <windows.h> // NOLINT
typedef HANDLE pthread_t;
typedef CRITICAL_SECTION pthread_mutex_t;
@@ -36,12 +37,120 @@
HANDLE signal_event_;
} pthread_cond_t;
-#else
+//------------------------------------------------------------------------------
+// simplistic pthread emulation layer
+// _beginthreadex requires __stdcall
+#define THREADFN unsigned int __stdcall
+#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val)
+
+static INLINE int pthread_create(pthread_t* const thread, const void* attr,
+ unsigned int (__stdcall *start)(void*),
+ void* arg) {
+ (void)attr;
+ *thread = (pthread_t)_beginthreadex(NULL, /* void *security */
+ 0, /* unsigned stack_size */
+ start,
+ arg,
+ 0, /* unsigned initflag */
+ NULL); /* unsigned *thrdaddr */
+ if (*thread == NULL) return 1;
+ SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL);
+ return 0;
+}
+
+static INLINE int pthread_join(pthread_t thread, void** value_ptr) {
+ (void)value_ptr;
+ return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 ||
+ CloseHandle(thread) == 0);
+}
+
+// Mutex
+static INLINE int pthread_mutex_init(pthread_mutex_t *const mutex,
+ void* mutexattr) {
+ (void)mutexattr;
+ InitializeCriticalSection(mutex);
+ return 0;
+}
+
+static INLINE int pthread_mutex_trylock(pthread_mutex_t *const mutex) {
+ return TryEnterCriticalSection(mutex) ? 0 : EBUSY;
+}
+
+static INLINE int pthread_mutex_lock(pthread_mutex_t *const mutex) {
+ EnterCriticalSection(mutex);
+ return 0;
+}
+
+static INLINE int pthread_mutex_unlock(pthread_mutex_t *const mutex) {
+ LeaveCriticalSection(mutex);
+ return 0;
+}
+
+static INLINE int pthread_mutex_destroy(pthread_mutex_t *const mutex) {
+ DeleteCriticalSection(mutex);
+ return 0;
+}
+
+// Condition
+static INLINE int pthread_cond_destroy(pthread_cond_t *const condition) {
+ int ok = 1;
+ ok &= (CloseHandle(condition->waiting_sem_) != 0);
+ ok &= (CloseHandle(condition->received_sem_) != 0);
+ ok &= (CloseHandle(condition->signal_event_) != 0);
+ return !ok;
+}
+
+static INLINE int pthread_cond_init(pthread_cond_t *const condition,
+ void* cond_attr) {
+ (void)cond_attr;
+ condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
+ condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
+ condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (condition->waiting_sem_ == NULL ||
+ condition->received_sem_ == NULL ||
+ condition->signal_event_ == NULL) {
+ pthread_cond_destroy(condition);
+ return 1;
+ }
+ return 0;
+}
+
+static INLINE int pthread_cond_signal(pthread_cond_t *const condition) {
+ int ok = 1;
+ if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) {
+ // a thread is waiting in pthread_cond_wait: allow it to be notified
+ ok = SetEvent(condition->signal_event_);
+ // wait until the event is consumed so the signaler cannot consume
+ // the event via its own pthread_cond_wait.
+ ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
+ WAIT_OBJECT_0);
+ }
+ return !ok;
+}
+
+static INLINE int pthread_cond_wait(pthread_cond_t *const condition,
+ pthread_mutex_t *const mutex) {
+ int ok;
+ // note that there is a consumer available so the signal isn't dropped in
+ // pthread_cond_signal
+ if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
+ return 1;
+ // now unlock the mutex so pthread_cond_signal may be issued
+ pthread_mutex_unlock(mutex);
+ ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
+ WAIT_OBJECT_0);
+ ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
+ pthread_mutex_lock(mutex);
+ return !ok;
+}
+#else // _WIN32
#include <pthread.h> // NOLINT
+# define THREADFN void*
+# define THREAD_RETURN(val) val
+#endif
-#endif /* _WIN32 */
-#endif /* CONFIG_MULTITHREAD */
+#endif // CONFIG_MULTITHREAD
// State of the worker thread object
typedef enum {
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 8db517a..c8f334f 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -33,11 +33,6 @@
#include "vp9/encoder/vp9_tokenize.h"
#include "vp9/encoder/vp9_write_bit_buffer.h"
-
-#if defined(SECTIONBITS_OUTPUT)
-unsigned __int64 Sectionbits[500];
-#endif
-
#ifdef ENTROPY_STATS
vp9_coeff_stats tree_update_hist[TX_SIZES][PLANE_TYPES];
extern unsigned int active_section;
@@ -124,8 +119,8 @@
void vp9_update_skip_probs(VP9_COMMON *cm, vp9_writer *w) {
int k;
- for (k = 0; k < MBSKIP_CONTEXTS; ++k)
- vp9_cond_prob_diff_update(w, &cm->fc.mbskip_probs[k], cm->counts.mbskip[k]);
+ for (k = 0; k < SKIP_CONTEXTS; ++k)
+ vp9_cond_prob_diff_update(w, &cm->fc.skip_probs[k], cm->counts.skip[k]);
}
static void update_switchable_interp_probs(VP9_COMP *cpi, vp9_writer *w) {
@@ -393,8 +388,8 @@
write_selected_tx_size(cpi, m, m->mbmi.tx_size, m->mbmi.sb_type, bc);
if (m->mbmi.sb_type >= BLOCK_8X8) {
- const MB_PREDICTION_MODE A = above_block_mode(m, above_mi, 0);
- const MB_PREDICTION_MODE L = left_block_mode(m, left_mi, 0);
+ const MB_PREDICTION_MODE A = vp9_above_block_mode(m, above_mi, 0);
+ const MB_PREDICTION_MODE L = vp9_left_block_mode(m, left_mi, 0);
write_intra_mode(bc, ym, vp9_kf_y_mode_prob[A][L]);
} else {
int idx, idy;
@@ -403,8 +398,8 @@
for (idy = 0; idy < 2; idy += num_4x4_blocks_high) {
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
int i = idy * 2 + idx;
- const MB_PREDICTION_MODE A = above_block_mode(m, above_mi, i);
- const MB_PREDICTION_MODE L = left_block_mode(m, left_mi, i);
+ const MB_PREDICTION_MODE A = vp9_above_block_mode(m, above_mi, i);
+ const MB_PREDICTION_MODE L = vp9_left_block_mode(m, left_mi, i);
const int bm = m->bmi[i].as_mode;
write_intra_mode(bc, bm, vp9_kf_y_mode_prob[A][L]);
}
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 716ad61..713cc51 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -239,25 +239,6 @@
}
}
-struct rdcost_block_args {
- MACROBLOCK *x;
- ENTROPY_CONTEXT t_above[16];
- ENTROPY_CONTEXT t_left[16];
- TX_SIZE tx_size;
- int bw;
- int bh;
- int rate;
- int64_t dist;
- int64_t sse;
- int this_rate;
- int64_t this_dist;
- int64_t this_sse;
- int64_t this_rd;
- int64_t best_rd;
- int skip;
- const int16_t *scan, *nb;
-};
-
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/encoder/vp9_dct.c b/vp9/encoder/vp9_dct.c
index 0f4a6bb..a840b48 100644
--- a/vp9/encoder/vp9_dct.c
+++ b/vp9/encoder/vp9_dct.c
@@ -997,7 +997,7 @@
return rv;
}
-static void dct32_1d(const int *input, int *output, int round) {
+static void fdct32(const int *input, int *output, int round) {
int step[32];
// Stage 1
step[0] = input[0] + input[(32 - 1)];
@@ -1329,7 +1329,7 @@
int temp_in[32], temp_out[32];
for (j = 0; j < 32; ++j)
temp_in[j] = input[j * stride + i] * 4;
- dct32_1d(temp_in, temp_out, 0);
+ fdct32(temp_in, temp_out, 0);
for (j = 0; j < 32; ++j)
output[j * 32 + i] = (temp_out[j] + 1 + (temp_out[j] > 0)) >> 2;
}
@@ -1339,13 +1339,13 @@
int temp_in[32], temp_out[32];
for (j = 0; j < 32; ++j)
temp_in[j] = output[j + i * 32];
- dct32_1d(temp_in, temp_out, 0);
+ fdct32(temp_in, temp_out, 0);
for (j = 0; j < 32; ++j)
out[j + i * 32] = (temp_out[j] + 1 + (temp_out[j] < 0)) >> 2;
}
}
-// Note that although we use dct_32_round in dct32_1d computation flow,
+// Note that although we use dct_32_round in dct32 computation flow,
// this 2d fdct32x32 for rate-distortion optimization loop is operating
// within 16 bits precision.
void vp9_fdct32x32_rd_c(const int16_t *input, int16_t *out, int stride) {
@@ -1357,7 +1357,7 @@
int temp_in[32], temp_out[32];
for (j = 0; j < 32; ++j)
temp_in[j] = input[j * stride + i] * 4;
- dct32_1d(temp_in, temp_out, 0);
+ fdct32(temp_in, temp_out, 0);
for (j = 0; j < 32; ++j)
// TODO(cd): see quality impact of only doing
// output[j * 32 + i] = (temp_out[j] + 1) >> 2;
@@ -1370,7 +1370,7 @@
int temp_in[32], temp_out[32];
for (j = 0; j < 32; ++j)
temp_in[j] = output[j + i * 32];
- dct32_1d(temp_in, temp_out, 1);
+ fdct32(temp_in, temp_out, 1);
for (j = 0; j < 32; ++j)
out[j + i * 32] = temp_out[j];
}
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 317ac98..eaedf1e 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -40,14 +40,6 @@
#include "vp9/encoder/vp9_tokenize.h"
#include "vp9/encoder/vp9_vaq.h"
-#define DBG_PRNT_SEGMAP 0
-
-
-// #define ENC_DEBUG
-#ifdef ENC_DEBUG
-int enc_debug = 0;
-#endif
-
static INLINE uint8_t *get_sb_index(MACROBLOCK *x, BLOCK_SIZE subsize) {
switch (subsize) {
case BLOCK_64X64:
@@ -380,8 +372,10 @@
segment = 0;
}
- complexity_metric =
- clamp((int)((projected_rate * 64) / target_rate), 16, 255);
+ if (target_rate > 0) {
+ complexity_metric =
+ clamp((int)((projected_rate * 64) / target_rate), 16, 255);
+ }
}
// Fill in the entires in the segment map corresponding to this SB64
@@ -481,18 +475,18 @@
if (frame_is_intra_only(cm)) {
#if CONFIG_INTERNAL_STATS
static const int kf_mode_index[] = {
- THR_DC /*DC_PRED*/,
- THR_V_PRED /*V_PRED*/,
- THR_H_PRED /*H_PRED*/,
- THR_D45_PRED /*D45_PRED*/,
+ THR_DC /*DC_PRED*/,
+ THR_V_PRED /*V_PRED*/,
+ THR_H_PRED /*H_PRED*/,
+ THR_D45_PRED /*D45_PRED*/,
THR_D135_PRED /*D135_PRED*/,
THR_D117_PRED /*D117_PRED*/,
THR_D153_PRED /*D153_PRED*/,
THR_D207_PRED /*D207_PRED*/,
- THR_D63_PRED /*D63_PRED*/,
- THR_TM /*TM_PRED*/,
+ THR_D63_PRED /*D63_PRED*/,
+ THR_TM /*TM_PRED*/,
};
- cpi->mode_chosen_counts[kf_mode_index[mi->mbmi.mode]]++;
+ cpi->mode_chosen_counts[kf_mode_index[mbmi->mode]]++;
#endif
} else {
// Note how often each mode chosen as best
@@ -1029,131 +1023,171 @@
}
return 0;
}
-
-// TODO(jingning) This currently serves as a test framework for non-RD mode
-// decision. To be continued on optimizing the partition type decisions.
-static void pick_partition_type(VP9_COMP *cpi,
- const TileInfo *const tile,
- MODE_INFO **mi_8x8, TOKENEXTRA **tp,
- int mi_row, int mi_col,
- BLOCK_SIZE bsize, int *rate, int64_t *dist,
- int do_recon) {
+static void update_state_rt(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
+ BLOCK_SIZE bsize, int output_enabled) {
+ int i;
VP9_COMMON *const cm = &cpi->common;
MACROBLOCK *const x = &cpi->mb;
- const int mi_stride = cm->mode_info_stride;
- const int num_8x8_subsize = (num_8x8_blocks_wide_lookup[bsize] >> 1);
- int i;
- PARTITION_TYPE partition = PARTITION_NONE;
- BLOCK_SIZE subsize;
- BLOCK_SIZE bs_type = mi_8x8[0]->mbmi.sb_type;
- int sub_rate[4] = {0};
- int64_t sub_dist[4] = {0};
- int mi_offset;
+ MACROBLOCKD *const xd = &x->e_mbd;
+ struct macroblock_plane *const p = x->plane;
+ struct macroblockd_plane *const pd = xd->plane;
+ MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
- if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
- return;
+ const int mb_mode_index = ctx->best_mode_index;
+ int max_plane;
- partition = partition_lookup[b_width_log2(bsize)][bs_type];
- subsize = get_subsize(bsize, partition);
+ max_plane = is_inter_block(mbmi) ? MAX_MB_PLANE : 1;
+ for (i = 0; i < max_plane; ++i) {
+ p[i].coeff = ctx->coeff_pbuf[i][1];
+ p[i].qcoeff = ctx->qcoeff_pbuf[i][1];
+ pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][1];
+ p[i].eobs = ctx->eobs_pbuf[i][1];
+ }
+
+ for (i = max_plane; i < MAX_MB_PLANE; ++i) {
+ p[i].coeff = ctx->coeff_pbuf[i][2];
+ p[i].qcoeff = ctx->qcoeff_pbuf[i][2];
+ pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][2];
+ p[i].eobs = ctx->eobs_pbuf[i][2];
+ }
+
+ x->skip = ctx->skip;
+
+ if (frame_is_intra_only(cm)) {
+#if CONFIG_INTERNAL_STATS
+ static const int kf_mode_index[] = {
+ THR_DC /*DC_PRED*/,
+ THR_V_PRED /*V_PRED*/,
+ THR_H_PRED /*H_PRED*/,
+ THR_D45_PRED /*D45_PRED*/,
+ THR_D135_PRED /*D135_PRED*/,
+ THR_D117_PRED /*D117_PRED*/,
+ THR_D153_PRED /*D153_PRED*/,
+ THR_D207_PRED /*D207_PRED*/,
+ THR_D63_PRED /*D63_PRED*/,
+ THR_TM /*TM_PRED*/,
+ };
+ ++cpi->mode_chosen_counts[kf_mode_index[mbmi->mode]];
+#endif
+ } else {
+ // Note how often each mode chosen as best
+ cpi->mode_chosen_counts[mb_mode_index]++;
+ if (is_inter_block(mbmi) &&
+ (mbmi->sb_type < BLOCK_8X8 || mbmi->mode == NEWMV)) {
+ int_mv best_mv[2];
+ for (i = 0; i < 1 + has_second_ref(mbmi); ++i)
+ best_mv[i].as_int = mbmi->ref_mvs[mbmi->ref_frame[i]][0].as_int;
+ vp9_update_mv_count(cpi, x, best_mv);
+ }
+
+ if (cm->interp_filter == SWITCHABLE && is_inter_mode(mbmi->mode)) {
+ const int ctx = vp9_get_pred_context_switchable_interp(xd);
+ ++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
+ }
+ }
+}
+
+static void encode_b_rt(VP9_COMP *cpi, const TileInfo *const tile,
+ TOKENEXTRA **tp, int mi_row, int mi_col,
+ int output_enabled, BLOCK_SIZE bsize) {
+ MACROBLOCK *const x = &cpi->mb;
if (bsize < BLOCK_8X8) {
// When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
// there is nothing to be done.
- if (x->ab_index != 0) {
- *rate = 0;
- *dist = 0;
+ if (x->ab_index > 0)
return;
- }
- } else {
- *(get_sb_partitioning(x, bsize)) = subsize;
}
+ set_offsets(cpi, tile, mi_row, mi_col, bsize);
+ update_state_rt(cpi, get_block_context(x, bsize), bsize, output_enabled);
+
+ encode_superblock(cpi, tp, output_enabled, mi_row, mi_col, bsize);
+ update_stats(cpi);
+
+ (*tp)->token = EOSB_TOKEN;
+ (*tp)++;
+}
+
+static void encode_sb_rt(VP9_COMP *cpi, const TileInfo *const tile,
+ TOKENEXTRA **tp, int mi_row, int mi_col,
+ int output_enabled, BLOCK_SIZE bsize) {
+ VP9_COMMON *const cm = &cpi->common;
+ MACROBLOCK *const x = &cpi->mb;
+ const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
+ int ctx;
+ PARTITION_TYPE partition;
+ BLOCK_SIZE subsize;
+
+ if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
+ return;
+
+ if (bsize >= BLOCK_8X8) {
+ MACROBLOCKD *const xd = &cpi->mb.e_mbd;
+ const int idx_str = xd->mode_info_stride * mi_row + mi_col;
+ MODE_INFO ** mi_8x8 = cm->mi_grid_visible + idx_str;
+ ctx = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
+ mi_row, mi_col, bsize);
+ subsize = mi_8x8[0]->mbmi.sb_type;
+
+ } else {
+ ctx = 0;
+ subsize = BLOCK_4X4;
+ }
+
+ partition = partition_lookup[bsl][subsize];
switch (partition) {
case PARTITION_NONE:
- rd_pick_sb_modes(cpi, tile, mi_row, mi_col, rate, dist,
- bsize, get_block_context(x, bsize), INT64_MAX);
- break;
- case PARTITION_HORZ:
- *get_sb_index(x, subsize) = 0;
- rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sub_rate[0], &sub_dist[0],
- subsize, get_block_context(x, subsize), INT64_MAX);
- if (bsize >= BLOCK_8X8 && mi_row + num_8x8_subsize < cm->mi_rows) {
- update_state(cpi, get_block_context(x, subsize), subsize, 0);
- encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
- *get_sb_index(x, subsize) = 1;
- rd_pick_sb_modes(cpi, tile, mi_row + num_8x8_subsize, mi_col,
- &sub_rate[1], &sub_dist[1], subsize,
- get_block_context(x, subsize), INT64_MAX);
- }
- *rate = sub_rate[0] + sub_rate[1];
- *dist = sub_dist[0] + sub_dist[1];
+ if (output_enabled && bsize >= BLOCK_8X8)
+ cm->counts.partition[ctx][PARTITION_NONE]++;
+ encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
break;
case PARTITION_VERT:
+ if (output_enabled)
+ cm->counts.partition[ctx][PARTITION_VERT]++;
*get_sb_index(x, subsize) = 0;
- rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sub_rate[0], &sub_dist[0],
- subsize, get_block_context(x, subsize), INT64_MAX);
- if (bsize >= BLOCK_8X8 && mi_col + num_8x8_subsize < cm->mi_cols) {
- update_state(cpi, get_block_context(x, subsize), subsize, 0);
- encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
+ encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
+ if (mi_col + hbs < cm->mi_cols) {
*get_sb_index(x, subsize) = 1;
- rd_pick_sb_modes(cpi, tile, mi_row, mi_col + num_8x8_subsize,
- &sub_rate[1], &sub_dist[1], subsize,
- get_block_context(x, subsize), INT64_MAX);
+ encode_b_rt(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled,
+ subsize);
}
- *rate = sub_rate[0] + sub_rate[1];
- *dist = sub_dist[1] + sub_dist[1];
+ break;
+ case PARTITION_HORZ:
+ if (output_enabled)
+ cm->counts.partition[ctx][PARTITION_HORZ]++;
+ *get_sb_index(x, subsize) = 0;
+ encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
+ if (mi_row + hbs < cm->mi_rows) {
+ *get_sb_index(x, subsize) = 1;
+ encode_b_rt(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled,
+ subsize);
+ }
break;
case PARTITION_SPLIT:
+ subsize = get_subsize(bsize, PARTITION_SPLIT);
+ if (output_enabled)
+ cm->counts.partition[ctx][PARTITION_SPLIT]++;
+
*get_sb_index(x, subsize) = 0;
- pick_partition_type(cpi, tile, mi_8x8, tp, mi_row, mi_col, subsize,
- &sub_rate[0], &sub_dist[0], 0);
-
- if ((mi_col + num_8x8_subsize) < cm->mi_cols) {
- *get_sb_index(x, subsize) = 1;
- pick_partition_type(cpi, tile, mi_8x8 + num_8x8_subsize, tp,
- mi_row, mi_col + num_8x8_subsize, subsize,
- &sub_rate[1], &sub_dist[1], 0);
- }
-
- if ((mi_row + num_8x8_subsize) < cm->mi_rows) {
- *get_sb_index(x, subsize) = 2;
- pick_partition_type(cpi, tile, mi_8x8 + num_8x8_subsize * mi_stride, tp,
- mi_row + num_8x8_subsize, mi_col, subsize,
- &sub_rate[2], &sub_dist[2], 0);
- }
-
- if ((mi_col + num_8x8_subsize) < cm->mi_cols &&
- (mi_row + num_8x8_subsize) < cm->mi_rows) {
- *get_sb_index(x, subsize) = 3;
- mi_offset = num_8x8_subsize * mi_stride + num_8x8_subsize;
- pick_partition_type(cpi, tile, mi_8x8 + mi_offset, tp,
- mi_row + num_8x8_subsize, mi_col + num_8x8_subsize,
- subsize, &sub_rate[3], &sub_dist[3], 0);
- }
-
- for (i = 0; i < 4; ++i) {
- *rate += sub_rate[i];
- *dist += sub_dist[i];
- }
-
+ encode_sb_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
+ *get_sb_index(x, subsize) = 1;
+ encode_sb_rt(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled,
+ subsize);
+ *get_sb_index(x, subsize) = 2;
+ encode_sb_rt(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled,
+ subsize);
+ *get_sb_index(x, subsize) = 3;
+ encode_sb_rt(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
+ subsize);
break;
default:
- assert(0);
+ assert("Invalid partition type.");
}
- if (do_recon) {
- int output_enabled = (bsize == BLOCK_64X64);
-
- // Check the projected output rate for this SB against it's target
- // and and if necessary apply a Q delta using segmentation to get
- // closer to the target.
- if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
- select_in_frame_q_segment(cpi, mi_row, mi_col,
- output_enabled, *rate);
- }
-
- encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize);
- }
+ if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
+ update_partition_context(cpi->above_seg_context, cpi->left_seg_context,
+ mi_row, mi_col, subsize, bsize);
}
static void rd_use_partition(VP9_COMP *cpi,
@@ -1444,15 +1478,19 @@
}
static const BLOCK_SIZE min_partition_size[BLOCK_SIZES] = {
- BLOCK_4X4, BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
- BLOCK_4X4, BLOCK_4X4, BLOCK_8X8, BLOCK_8X8,
- BLOCK_8X8, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16
+ BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
+ BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
+ BLOCK_8X8, BLOCK_8X8, BLOCK_8X8,
+ BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
+ BLOCK_16X16
};
static const BLOCK_SIZE max_partition_size[BLOCK_SIZES] = {
- BLOCK_8X8, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
- BLOCK_32X32, BLOCK_32X32, BLOCK_32X32, BLOCK_64X64,
- BLOCK_64X64, BLOCK_64X64, BLOCK_64X64, BLOCK_64X64, BLOCK_64X64
+ BLOCK_8X8, BLOCK_16X16, BLOCK_16X16,
+ BLOCK_16X16, BLOCK_32X32, BLOCK_32X32,
+ BLOCK_32X32, BLOCK_64X64, BLOCK_64X64,
+ BLOCK_64X64, BLOCK_64X64, BLOCK_64X64,
+ BLOCK_64X64
};
// Look at all the mode_info entries for blocks that are part of this
@@ -1538,9 +1576,11 @@
}
}
- // Give a bit of leaway either side of the observed min and max
- *min_block_size = min_partition_size[*min_block_size];
- *max_block_size = max_partition_size[*max_block_size];
+ // adjust observed min and max
+ if (cpi->sf.auto_min_max_partition_size == RELAXED_NEIGHBORING_MIN_MAX) {
+ *min_block_size = min_partition_size[*min_block_size];
+ *max_block_size = max_partition_size[*max_block_size];
+ }
// Check border cases where max and min from neighbours may not be legal.
*max_block_size = find_partition_size(*max_block_size,
@@ -1996,34 +2036,6 @@
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, BLOCK_64X64);
}
-static void encode_sb_row_rt(VP9_COMP *cpi, const TileInfo *const tile,
- int mi_row, TOKENEXTRA **tp) {
- VP9_COMMON *const cm = &cpi->common;
- int mi_col;
-
- cpi->sf.always_this_block_size = BLOCK_8X8;
-
- // Initialize the left context for the new SB row
- vpx_memset(&cpi->left_context, 0, sizeof(cpi->left_context));
- vpx_memset(cpi->left_seg_context, 0, sizeof(cpi->left_seg_context));
-
- // Code each SB in the row
- for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
- mi_col += MI_BLOCK_SIZE) {
- int dummy_rate;
- int64_t dummy_dist;
- const int idx_str = cm->mode_info_stride * mi_row + mi_col;
- MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
-
- vp9_zero(cpi->mb.pred_mv);
-
- set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
- set_partitioning(cpi, tile, mi_8x8, mi_row, mi_col);
- pick_partition_type(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
- &dummy_rate, &dummy_dist, 1);
- }
-}
-
static void encode_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
int mi_row, TOKENEXTRA **tp) {
VP9_COMMON *const cm = &cpi->common;
@@ -2122,7 +2134,7 @@
setup_pre_planes(xd, 0, get_ref_frame_buffer(cpi, LAST_FRAME), 0, 0, NULL);
setup_dst_planes(xd, get_frame_new_buffer(cm), 0, 0);
- setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
+ vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
xd->mi_8x8[0]->mbmi.mode = DC_PRED;
xd->mi_8x8[0]->mbmi.uv_mode = DC_PRED;
@@ -2136,7 +2148,7 @@
vp9_zero(cm->counts.single_ref);
vp9_zero(cm->counts.comp_ref);
vp9_zero(cm->counts.tx);
- vp9_zero(cm->counts.mbskip);
+ vp9_zero(cm->counts.skip);
// Note: this memset assumes above_context[0], [1] and [2]
// are allocated as part of the same buffer.
@@ -2179,16 +2191,6 @@
// cpi->common.current_video_frame, cpi->common.show_frame,
// cm->frame_type);
-// debug output
-#if DBG_PRNT_SEGMAP
- {
- FILE *statsfile;
- statsfile = fopen("segmap2.stt", "a");
- fprintf(statsfile, "\n");
- fclose(statsfile);
- }
-#endif
-
vp9_zero(cm->counts.switchable_interp);
vp9_zero(cpi->tx_stepdown_count);
@@ -2250,11 +2252,7 @@
vp9_tile_init(&tile, cm, tile_row, tile_col);
for (mi_row = tile.mi_row_start;
mi_row < tile.mi_row_end; mi_row += 8)
-#if 1
encode_sb_row(cpi, &tile, mi_row, &tp);
-#else
- encode_sb_row_rt(cpi, &tile, mi_row, &tp);
-#endif
cpi->tok_count[tile_row][tile_col] = (unsigned int)(tp - tp_old);
assert(tp - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
@@ -2395,15 +2393,15 @@
}
}
-static int get_frame_type(VP9_COMP *cpi) {
+static MV_REFERENCE_FRAME get_frame_type(VP9_COMP *cpi) {
if (frame_is_intra_only(&cpi->common))
- return 0;
+ return INTRA_FRAME;
else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
- return 3;
+ return ALTREF_FRAME;
else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
- return 1;
+ return LAST_FRAME;
else
- return 2;
+ return GOLDEN_FRAME;
}
static void select_tx_mode(VP9_COMP *cpi) {
@@ -2433,6 +2431,264 @@
}
}
}
+// Start RTC Exploration
+typedef enum {
+ BOTH_ZERO = 0,
+ ZERO_PLUS_PREDICTED = 1,
+ BOTH_PREDICTED = 2,
+ NEW_PLUS_NON_INTRA = 3,
+ BOTH_NEW = 4,
+ INTRA_PLUS_NON_INTRA = 5,
+ BOTH_INTRA = 6,
+ INVALID_CASE = 9
+} motion_vector_context;
+
+static void set_mode_info(MB_MODE_INFO *mbmi, BLOCK_SIZE bsize,
+ MB_PREDICTION_MODE mode, int mi_row, int mi_col) {
+ mbmi->interp_filter = EIGHTTAP;
+ mbmi->mode = mode;
+ mbmi->mv[0].as_int = 0;
+ mbmi->mv[1].as_int = 0;
+ if (mode < NEARESTMV) {
+ mbmi->ref_frame[0] = INTRA_FRAME;
+ } else {
+ mbmi->ref_frame[0] = LAST_FRAME;
+ }
+
+ mbmi->ref_frame[1] = INTRA_FRAME;
+ mbmi->tx_size = max_txsize_lookup[bsize];
+ mbmi->uv_mode = mode;
+ mbmi->skip_coeff = 0;
+ mbmi->sb_type = bsize;
+ mbmi->segment_id = 0;
+}
+static INLINE int get_block_row(int b32i, int b16i, int b8i) {
+ return ((b32i >> 1) << 2) + ((b16i >> 1) << 1) + (b8i >> 1);
+}
+static INLINE int get_block_col(int b32i, int b16i, int b8i) {
+ return ((b32i & 1) << 2) + ((b16i & 1) << 1) + (b8i & 1);
+}
+static void rtc_use_partition(VP9_COMP *cpi,
+ const TileInfo *const tile,
+ MODE_INFO **mi_8x8,
+ TOKENEXTRA **tp, int mi_row, int mi_col,
+ BLOCK_SIZE bsize, int *rate, int64_t *dist,
+ int do_recon) {
+ VP9_COMMON *const cm = &cpi->common;
+ MACROBLOCK *const x = &cpi->mb;
+ MACROBLOCKD *const xd = &cpi->mb.e_mbd;
+ const int mis = cm->mode_info_stride;
+ int mi_width = num_8x8_blocks_wide_lookup[cpi->sf.always_this_block_size];
+ int mi_height = num_8x8_blocks_high_lookup[cpi->sf.always_this_block_size];
+ int i, j;
+ int chosen_rate = INT_MAX;
+ int64_t chosen_dist = INT_MAX;
+ MB_PREDICTION_MODE mode = DC_PRED;
+ int row8x8_remaining = tile->mi_row_end - mi_row;
+ int col8x8_remaining = tile->mi_col_end - mi_col;
+ int b32i;
+ x->fast_ms = 0;
+ x->subblock_ref = 0;
+ for (b32i = 0; b32i < 4; b32i++) {
+ int b16i;
+ for (b16i = 0; b16i < 4; b16i++) {
+ int b8i;
+ int block_row = get_block_row(b32i, b16i, 0);
+ int block_col = get_block_col(b32i, b16i, 0);
+ int index = block_row * mis + block_col;
+ int rate;
+ int64_t dist;
+
+ int_mv frame_nearest_mv[MAX_REF_FRAMES];
+ int_mv frame_near_mv[MAX_REF_FRAMES];
+ struct buf_2d yv12_mb[MAX_REF_FRAMES][MAX_MB_PLANE];
+
+ // Find a partition size that fits
+ bsize = find_partition_size(cpi->sf.always_this_block_size,
+ (row8x8_remaining - block_row),
+ (col8x8_remaining - block_col),
+ &mi_height, &mi_width);
+ mi_8x8[index] = mi_8x8[0] + index;
+
+ set_mi_row_col(xd, tile, mi_row + block_row, mi_height,
+ mi_col + block_col, mi_width, cm->mi_rows, cm->mi_cols);
+
+ xd->mi_8x8 = mi_8x8 + index;
+
+ if (cm->frame_type != KEY_FRAME) {
+ set_offsets(cpi, tile, mi_row + block_row, mi_col + block_col, bsize);
+
+ vp9_pick_inter_mode(cpi, x, tile,
+ mi_row + block_row, mi_col + block_col,
+ &rate, &dist, bsize);
+ } else {
+ set_mode_info(&mi_8x8[index]->mbmi, bsize, mode,
+ mi_row + block_row, mi_col + block_col);
+ vp9_setup_buffer_inter(cpi, x, tile,
+ LAST_FRAME, cpi->sf.always_this_block_size,
+ mi_row + block_row, mi_col + block_col,
+ frame_nearest_mv, frame_near_mv, yv12_mb);
+ }
+
+ for (j = 0; j < mi_height; j++)
+ for (i = 0; i < mi_width; i++)
+ if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width > i
+ && (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > j) {
+ mi_8x8[index+ i + j * mis] = mi_8x8[index];
+ }
+
+ for (b8i = 0; b8i < 4; b8i++) {
+ }
+ }
+ }
+ encode_sb_rt(cpi, tile, tp, mi_row, mi_col, 1, BLOCK_64X64);
+
+ *rate = chosen_rate;
+ *dist = chosen_dist;
+}
+
+static void encode_rtc_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
+ int mi_row, TOKENEXTRA **tp) {
+ VP9_COMMON * const cm = &cpi->common;
+ int mi_col;
+
+ // Initialize the left context for the new SB row
+ vpx_memset(&cpi->left_context, 0, sizeof(cpi->left_context));
+ vpx_memset(cpi->left_seg_context, 0, sizeof(cpi->left_seg_context));
+
+ // Code each SB in the row
+ for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
+ mi_col += MI_BLOCK_SIZE) {
+ int dummy_rate;
+ int64_t dummy_dist;
+
+ const int idx_str = cm->mode_info_stride * mi_row + mi_col;
+ MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
+
+ cpi->mb.source_variance = UINT_MAX;
+ set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
+ set_partitioning(cpi, tile, mi_8x8, mi_row, mi_col);
+ rtc_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
+ &dummy_rate, &dummy_dist, 1);
+ }
+}
+
+
+static void encode_rtc_frame_internal(VP9_COMP *cpi) {
+ int mi_row;
+ MACROBLOCK * const x = &cpi->mb;
+ VP9_COMMON * const cm = &cpi->common;
+ MACROBLOCKD * const xd = &x->e_mbd;
+
+// fprintf(stderr, "encode_frame_internal frame %d (%d) type %d\n",
+// cpi->common.current_video_frame, cpi->common.show_frame,
+// cm->frame_type);
+
+// debug output
+#if DBG_PRNT_SEGMAP
+ {
+ FILE *statsfile;
+ statsfile = fopen("segmap2.stt", "a");
+ fprintf(statsfile, "\n");
+ fclose(statsfile);
+ }
+#endif
+
+ vp9_zero(cm->counts.switchable_interp);
+ vp9_zero(cpi->tx_stepdown_count);
+
+ xd->mi_8x8 = cm->mi_grid_visible;
+ // required for vp9_frame_init_quantizer
+ xd->mi_8x8[0] = cm->mi;
+
+ xd->last_mi = cm->prev_mi;
+
+ vp9_zero(cpi->common.counts.mv);
+ vp9_zero(cpi->coef_counts);
+ vp9_zero(cm->counts.eob_branch);
+
+ cpi->mb.e_mbd.lossless = cm->base_qindex == 0 && cm->y_dc_delta_q == 0
+ && cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
+ switch_lossless_mode(cpi, cpi->mb.e_mbd.lossless);
+
+ vp9_frame_init_quantizer(cpi);
+
+ vp9_initialize_rd_consts(cpi);
+ vp9_initialize_me_consts(cpi, cm->base_qindex);
+ switch_tx_mode(cpi);
+ cpi->sf.always_this_block_size = BLOCK_16X16;
+
+ if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
+ // Initialize encode frame context.
+ init_encode_frame_mb_context(cpi);
+
+ // Build a frame level activity map
+ build_activity_map(cpi);
+ }
+
+ // Re-initialize encode frame context.
+ init_encode_frame_mb_context(cpi);
+
+ vp9_zero(cpi->rd_comp_pred_diff);
+ vp9_zero(cpi->rd_filter_diff);
+ vp9_zero(cpi->rd_tx_select_diff);
+ vp9_zero(cpi->rd_tx_select_threshes);
+
+ set_prev_mi(cm);
+
+ {
+ struct vpx_usec_timer emr_timer;
+ vpx_usec_timer_start(&emr_timer);
+
+ {
+ // Take tiles into account and give start/end MB
+ int tile_col, tile_row;
+ TOKENEXTRA *tp = cpi->tok;
+ const int tile_cols = 1 << cm->log2_tile_cols;
+ const int tile_rows = 1 << cm->log2_tile_rows;
+
+ for (tile_row = 0; tile_row < tile_rows; tile_row++) {
+ for (tile_col = 0; tile_col < tile_cols; tile_col++) {
+ TileInfo tile;
+ TOKENEXTRA *tp_old = tp;
+
+ // For each row of SBs in the frame
+ vp9_tile_init(&tile, cm, tile_row, tile_col);
+ for (mi_row = tile.mi_row_start;
+ mi_row < tile.mi_row_end; mi_row += 8)
+ encode_rtc_sb_row(cpi, &tile, mi_row, &tp);
+
+ cpi->tok_count[tile_row][tile_col] = (unsigned int)(tp - tp_old);
+ assert(tp - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
+ }
+ }
+ }
+
+ vpx_usec_timer_mark(&emr_timer);
+ cpi->time_encode_sb_row += vpx_usec_timer_elapsed(&emr_timer);
+ }
+
+ if (cpi->sf.skip_encode_sb) {
+ int j;
+ unsigned int intra_count = 0, inter_count = 0;
+ for (j = 0; j < INTRA_INTER_CONTEXTS; ++j) {
+ intra_count += cm->counts.intra_inter[j][0];
+ inter_count += cm->counts.intra_inter[j][1];
+ }
+ cpi->sf.skip_encode_frame = ((intra_count << 2) < inter_count);
+ cpi->sf.skip_encode_frame &= (cm->frame_type != KEY_FRAME);
+ cpi->sf.skip_encode_frame &= cm->show_frame;
+ } else {
+ cpi->sf.skip_encode_frame = 0;
+ }
+
+#if 0
+ // Keep record of the total distortion this time around for future use
+ cpi->last_frame_distortion = cpi->frame_distortion;
+#endif
+}
+// end RTC play code
+
void vp9_encode_frame(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
@@ -2460,7 +2716,6 @@
if (cpi->sf.RD) {
int i;
REFERENCE_MODE reference_mode;
- INTERP_FILTER interp_filter;
/*
* This code does a single RD pass over the whole frame assuming
* either compound, single or hybrid prediction as per whatever has
@@ -2470,7 +2725,7 @@
* that for subsequent frames.
* It does the same analysis for transform size selection also.
*/
- const int frame_type = get_frame_type(cpi);
+ const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
const int64_t *mode_thresh = cpi->rd_prediction_type_threshes[frame_type];
const int64_t *filter_thresh = cpi->rd_filter_threshes[frame_type];
@@ -2488,22 +2743,18 @@
else
reference_mode = REFERENCE_MODE_SELECT;
- /* filter type selection */
- // FIXME(rbultje) for some odd reason, we often select smooth_filter
- // as default filter for ARF overlay frames. This is a REALLY BAD
- // IDEA so we explicitly disable it here.
- if (frame_type != 3 &&
- filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP] &&
- filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP_SHARP] &&
- filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[SWITCHABLE - 1]) {
- interp_filter = EIGHTTAP_SMOOTH;
- } else if (filter_thresh[EIGHTTAP_SHARP] > filter_thresh[EIGHTTAP] &&
- filter_thresh[EIGHTTAP_SHARP] > filter_thresh[SWITCHABLE - 1]) {
- interp_filter = EIGHTTAP_SHARP;
- } else if (filter_thresh[EIGHTTAP] > filter_thresh[SWITCHABLE - 1]) {
- interp_filter = EIGHTTAP;
- } else {
- interp_filter = SWITCHABLE;
+ if (cm->interp_filter == SWITCHABLE) {
+ if (frame_type != ALTREF_FRAME &&
+ filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP] &&
+ filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP_SHARP] &&
+ filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[SWITCHABLE - 1]) {
+ cm->interp_filter = EIGHTTAP_SMOOTH;
+ } else if (filter_thresh[EIGHTTAP_SHARP] > filter_thresh[EIGHTTAP] &&
+ filter_thresh[EIGHTTAP_SHARP] > filter_thresh[SWITCHABLE - 1]) {
+ cm->interp_filter = EIGHTTAP_SHARP;
+ } else if (filter_thresh[EIGHTTAP] > filter_thresh[SWITCHABLE - 1]) {
+ cm->interp_filter = EIGHTTAP;
+ }
}
cpi->mb.e_mbd.lossless = cpi->oxcf.lossless;
@@ -2511,8 +2762,11 @@
/* transform size selection (4x4, 8x8, 16x16 or select-per-mb) */
select_tx_mode(cpi);
cm->reference_mode = reference_mode;
- cm->interp_filter = interp_filter;
- encode_frame_internal(cpi);
+
+ if (cpi->sf.super_fast_rtc)
+ encode_rtc_frame_internal(cpi);
+ else
+ encode_frame_internal(cpi);
for (i = 0; i < REFERENCE_MODES; ++i) {
const int diff = (int) (cpi->rd_comp_pred_diff[i] / cm->MBs);
@@ -2590,7 +2844,12 @@
}
}
} else {
- encode_frame_internal(cpi);
+ // Force the usage of the BILINEAR interp_filter.
+ cm->interp_filter = BILINEAR;
+ if (cpi->sf.super_fast_rtc)
+ encode_rtc_frame_internal(cpi);
+ else
+ encode_frame_internal(cpi);
}
}
@@ -2666,7 +2925,8 @@
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
const int mi_height = num_8x8_blocks_high_lookup[bsize];
x->skip_recode = !x->select_txfm_size && mbmi->sb_type >= BLOCK_8X8 &&
- (cpi->oxcf.aq_mode != COMPLEXITY_AQ);
+ (cpi->oxcf.aq_mode != COMPLEXITY_AQ) &&
+ !cpi->sf.super_fast_rtc;
x->skip_optimize = ctx->is_coded;
ctx->is_coded = 1;
x->use_lp32x32fdct = cpi->sf.use_lp32x32fdct;
@@ -2681,7 +2941,8 @@
vp9_update_zbin_extra(cpi, x);
}
} else {
- vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
+ set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
+ xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
// Adjust the zbin based on this MB rate.
@@ -2721,7 +2982,7 @@
} else {
mbmi->skip_coeff = 1;
if (output_enabled)
- cm->counts.mbskip[vp9_get_skip_context(xd)][1]++;
+ cm->counts.skip[vp9_get_skip_context(xd)][1]++;
reset_skip_context(xd, MAX(bsize, BLOCK_8X8));
}
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 5ea75c3..376a899 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -25,23 +25,6 @@
#include "vp9/encoder/vp9_rdopt.h"
#include "vp9/encoder/vp9_tokenize.h"
-void vp9_setup_interp_filters(MACROBLOCKD *xd, INTERP_FILTER filter,
- VP9_COMMON *cm) {
- if (xd->mi_8x8 && xd->mi_8x8[0]) {
- MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
-
- set_ref_ptrs(cm, xd, mbmi->ref_frame[0] - LAST_FRAME,
- mbmi->ref_frame[1] - LAST_FRAME);
-
- } else {
- set_ref_ptrs(cm, xd, -1, -1);
- }
-
- xd->interp_kernel = vp9_get_interp_kernel(filter == SWITCHABLE ? EIGHTTAP
- : filter);
- assert(((intptr_t)xd->interp_kernel & 0xff) == 0);
-}
-
void vp9_subtract_block_c(int rows, int cols,
int16_t *diff_ptr, ptrdiff_t diff_stride,
const uint8_t *src_ptr, ptrdiff_t src_stride,
@@ -355,7 +338,6 @@
pd->above_context, pd->left_context,
num_4x4_w, num_4x4_h);
}
-
void vp9_xform_quant(int plane, int block, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, void *arg) {
struct encode_b_args* const args = arg;
@@ -505,7 +487,8 @@
if (x->optimize)
optimize_init_b(0, bsize, &arg);
- foreach_transformed_block_in_plane(xd, bsize, 0, encode_block_pass1, &arg);
+ vp9_foreach_transformed_block_in_plane(xd, bsize, 0, encode_block_pass1,
+ &arg);
}
void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize) {
@@ -523,7 +506,7 @@
optimize_init_b(i, bsize, &arg);
}
- foreach_transformed_block(xd, bsize, encode_block, &arg);
+ vp9_foreach_transformed_block(xd, bsize, encode_block, &arg);
}
void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
@@ -666,7 +649,7 @@
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
struct encode_b_args arg = {x, &ctx, &mbmi->skip_coeff};
- foreach_transformed_block_in_plane(xd, bsize, 0, vp9_encode_block_intra,
+ vp9_foreach_transformed_block_in_plane(xd, bsize, 0, vp9_encode_block_intra,
&arg);
}
void vp9_encode_intra_block_uv(MACROBLOCK *x, BLOCK_SIZE bsize) {
@@ -674,7 +657,7 @@
struct optimize_ctx ctx;
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
struct encode_b_args arg = {x, &ctx, &mbmi->skip_coeff};
- foreach_transformed_block_uv(xd, bsize, vp9_encode_block_intra, &arg);
+ vp9_foreach_transformed_block_uv(xd, bsize, vp9_encode_block_intra, &arg);
}
int vp9_encode_intra(MACROBLOCK *x, int use_16x16_pred) {
diff --git a/vp9/encoder/vp9_encodemb.h b/vp9/encoder/vp9_encodemb.h
index c728efd..9f6c9f0 100644
--- a/vp9/encoder/vp9_encodemb.h
+++ b/vp9/encoder/vp9_encodemb.h
@@ -48,8 +48,7 @@
void vp9_encode_intra_block_uv(MACROBLOCK *x, BLOCK_SIZE bsize);
int vp9_encode_intra(MACROBLOCK *x, int use_16x16_pred);
-void vp9_setup_interp_filters(MACROBLOCKD *xd, INTERP_FILTER filter,
- VP9_COMMON *cm);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/encoder/vp9_encodemv.h b/vp9/encoder/vp9_encodemv.h
index c57b01d..f0463bbd 100644
--- a/vp9/encoder/vp9_encodemv.h
+++ b/vp9/encoder/vp9_encodemv.h
@@ -20,7 +20,7 @@
void vp9_entropy_mv_init();
-void vp9_write_nmv_probs(VP9_COMMON *cm, int usehp, vp9_writer* const);
+void vp9_write_nmv_probs(VP9_COMMON *cm, int usehp, vp9_writer *w);
void vp9_encode_mv(VP9_COMP *cpi, vp9_writer* w, const MV* mv, const MV* ref,
const nmv_context* mvctx, int usehp);
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 28b343c..dcebefb 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -49,6 +49,10 @@
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
+#define MIN_KF_BOOST 300
+
+#define DISABLE_RC_LONG_TERM_MEM 0
+
static void swap_yv12(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
YV12_BUFFER_CONFIG temp = *a;
*a = *b;
@@ -491,10 +495,7 @@
int sum_in_vectors = 0;
uint32_t lastmv_as_int = 0;
struct twopass_rc *const twopass = &cpi->twopass;
-
- int_mv zero_ref_mv;
-
- zero_ref_mv.as_int = 0;
+ const MV zero_mv = {0, 0};
vp9_clear_system_state(); // __asm emms;
@@ -503,10 +504,9 @@
setup_dst_planes(xd, new_yv12, 0, 0);
xd->mi_8x8 = cm->mi_grid_visible;
- // required for vp9_frame_init_quantizer
- xd->mi_8x8[0] = cm->mi;
+ xd->mi_8x8[0] = cm->mi; // required for vp9_frame_init_quantizer
- setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
+ vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
vp9_frame_init_quantizer(cpi);
@@ -518,14 +518,8 @@
}
x->skip_recode = 0;
-
- // Initialise the MV cost table to the defaults
- // if( cm->current_video_frame == 0)
- // if ( 0 )
- {
- vp9_init_mv_probs(cm);
- vp9_initialize_rd_consts(cpi);
- }
+ vp9_init_mv_probs(cm);
+ vp9_initialize_rd_consts(cpi);
// tiling is ignored in the first pass
vp9_tile_init(&tile, cm, 0, 0);
@@ -550,7 +544,7 @@
// for each macroblock col in image
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
int this_error;
- int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
+ const int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
double error_weight = 1.0;
const BLOCK_SIZE bsize = get_bsize(cm, mb_row, mb_col);
@@ -568,7 +562,7 @@
cm->mi_rows, cm->mi_cols);
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
- int energy = vp9_block_energy(cpi, x, bsize);
+ const int energy = vp9_block_energy(cpi, x, bsize);
error_weight = vp9_vaq_inv_q_ratio(energy);
}
@@ -594,8 +588,7 @@
// Set up limit values for motion vectors to prevent them extending
// outside the UMV borders.
x->mv_col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16);
- x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16)
- + BORDER_MV_PIXELS_B16;
+ x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16;
// Other than for the first frame do a motion search
if (cm->current_video_frame > 0) {
@@ -620,7 +613,7 @@
// based search as well.
if (best_ref_mv.as_int) {
tmp_err = INT_MAX;
- first_pass_motion_search(cpi, x, &zero_ref_mv.as_mv, &tmp_mv.as_mv,
+ first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv,
&tmp_err);
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_clear_system_state(); // __asm emms;
@@ -641,17 +634,15 @@
xd->plane[0].pre[0].buf = gld_yv12->y_buffer + recon_yoffset;
gf_motion_error = zz_motion_search(cpi, x);
- first_pass_motion_search(cpi, x, &zero_ref_mv.as_mv, &tmp_mv.as_mv,
+ first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv,
&gf_motion_error);
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_clear_system_state(); // __asm emms;
gf_motion_error *= error_weight;
}
- if ((gf_motion_error < motion_error) &&
- (gf_motion_error < this_error)) {
+ if (gf_motion_error < motion_error && gf_motion_error < this_error)
second_ref_count++;
- }
// Reset to last frame as reference buffer
xd->plane[0].pre[0].buf = lst_yv12->y_buffer + recon_yoffset;
@@ -779,13 +770,11 @@
fps.mvr_abs = (double)sum_mvr_abs / mvcount;
fps.MVc = (double)sum_mvc / mvcount;
fps.mvc_abs = (double)sum_mvc_abs / mvcount;
- fps.MVrv = ((double)sum_mvrs - (fps.MVr * fps.MVr / mvcount)) /
- mvcount;
- fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / mvcount)) /
- mvcount;
+ fps.MVrv = ((double)sum_mvrs - (fps.MVr * fps.MVr / mvcount)) / mvcount;
+ fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / mvcount)) / mvcount;
fps.mv_in_out_count = (double)sum_in_vectors / (mvcount * 2);
fps.new_mv_count = new_mv_count;
- fps.pcnt_motion = (double)mvcount / cpi->common.MBs;
+ fps.pcnt_motion = (double)mvcount / cm->MBs;
} else {
fps.MVr = 0.0;
fps.mvr_abs = 0.0;
@@ -913,8 +902,7 @@
return fclamp(pow(error_term, power_term), 0.05, 5.0);
}
-static int estimate_max_q(VP9_COMP *cpi,
- FIRSTPASS_STATS *fpstats,
+static int estimate_max_q(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
int section_target_bandwitdh) {
int q;
const int num_mbs = cpi->common.MBs;
@@ -949,58 +937,6 @@
return q;
}
-// For cq mode estimate a cq level that matches the observed
-// complexity and data rate.
-static int estimate_cq(VP9_COMP *cpi,
- FIRSTPASS_STATS *fpstats,
- int section_target_bandwitdh) {
- int q;
- int num_mbs = cpi->common.MBs;
- int target_norm_bits_per_mb;
-
- double section_err = (fpstats->coded_error / fpstats->count);
- double err_per_mb = section_err / num_mbs;
- double err_correction_factor;
- double clip_iiratio;
- double clip_iifactor;
-
- target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20))
- ? (512 * section_target_bandwitdh) / num_mbs
- : 512 * (section_target_bandwitdh / num_mbs);
-
-
- // II ratio correction factor for clip as a whole
- clip_iiratio = cpi->twopass.total_stats.intra_error /
- DOUBLE_DIVIDE_CHECK(cpi->twopass.total_stats.coded_error);
- clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025);
- if (clip_iifactor < 0.80)
- clip_iifactor = 0.80;
-
- // Try and pick a Q that can encode the content at the given rate.
- for (q = 0; q < MAXQ; q++) {
- int bits_per_mb_at_this_q;
-
- // Error per MB based correction factor
- err_correction_factor =
- calc_correction_factor(err_per_mb, 100.0, 0.5, 0.90, q) * clip_iifactor;
-
- bits_per_mb_at_this_q =
- vp9_rc_bits_per_mb(INTER_FRAME, q, err_correction_factor);
-
- if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
- break;
- }
-
- // Clip value to range "best allowed to (worst allowed - 1)"
- q = select_cq_level(q);
- if (q >= cpi->rc.worst_quality)
- q = cpi->rc.worst_quality - 1;
- if (q < cpi->rc.best_quality)
- q = cpi->rc.best_quality;
-
- return q;
-}
-
extern void vp9_new_framerate(VP9_COMP *cpi, double framerate);
void vp9_init_second_pass(VP9_COMP *cpi) {
@@ -1088,12 +1024,12 @@
// This function gives and estimate of how badly we believe
// the prediction quality is decaying from frame to frame.
-static double get_prediction_decay_rate(VP9_COMP *cpi,
- FIRSTPASS_STATS *next_frame) {
+static double get_prediction_decay_rate(const VP9_COMMON *cm,
+ const FIRSTPASS_STATS *next_frame) {
// Look at the observed drop in prediction quality between the last frame
// and the GF buffer (which contains an older frame).
const double mb_sr_err_diff = (next_frame->sr_coded_error -
- next_frame->coded_error) / cpi->common.MBs;
+ next_frame->coded_error) / cm->MBs;
const double second_ref_decay = mb_sr_err_diff <= 512.0
? fclamp(pow(1.0 - (mb_sr_err_diff / 512.0), 0.5), 0.85, 1.0)
: 0.85;
@@ -1121,7 +1057,6 @@
int j;
FIRSTPASS_STATS *position = cpi->twopass.stats_in;
FIRSTPASS_STATS tmp_next_frame;
- double zz_inter;
// Look ahead a few frames to see if static condition
// persists...
@@ -1129,11 +1064,10 @@
if (EOF == input_stats(&cpi->twopass, &tmp_next_frame))
break;
- zz_inter = (tmp_next_frame.pcnt_inter - tmp_next_frame.pcnt_motion);
- if (zz_inter < 0.999)
+ if (tmp_next_frame.pcnt_inter - tmp_next_frame.pcnt_motion < 0.999)
break;
}
- // Reset file position
+
reset_fpf_position(&cpi->twopass, position);
// Only if it does do we signal a transition to still
@@ -1147,14 +1081,14 @@
// This function detects a flash through the high relative pcnt_second_ref
// score in the frame following a flash frame. The offset passed in should
// reflect this
-static int detect_flash(VP9_COMP *cpi, int offset) {
+static int detect_flash(const struct twopass_rc *twopass, int offset) {
FIRSTPASS_STATS next_frame;
int flash_detected = 0;
// Read the frame data.
// The return is FALSE (no flash detected) if not a valid frame
- if (read_frame_stats(&cpi->twopass, &next_frame, offset) != EOF) {
+ if (read_frame_stats(twopass, &next_frame, offset) != EOF) {
// What we are looking for here is a situation where there is a
// brief break in prediction (such as a flash) but subsequent frames
// are reasonably well predicted by an earlier (pre flash) frame.
@@ -1183,16 +1117,15 @@
// Accumulate Motion In/Out of frame stats
*this_frame_mv_in_out = this_frame->mv_in_out_count * motion_pct;
*mv_in_out_accumulator += this_frame->mv_in_out_count * motion_pct;
- *abs_mv_in_out_accumulator +=
- fabs(this_frame->mv_in_out_count * motion_pct);
+ *abs_mv_in_out_accumulator += fabs(this_frame->mv_in_out_count * motion_pct);
// Accumulate a measure of how uniform (or conversely how random)
// the motion field is. (A ratio of absmv / mv)
if (motion_pct > 0.05) {
- double this_frame_mvr_ratio = fabs(this_frame->mvr_abs) /
+ const double this_frame_mvr_ratio = fabs(this_frame->mvr_abs) /
DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVr));
- double this_frame_mvc_ratio = fabs(this_frame->mvc_abs) /
+ const double this_frame_mvc_ratio = fabs(this_frame->mvc_abs) /
DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVc));
*mv_ratio_accumulator += (this_frame_mvr_ratio < this_frame->mvr_abs)
@@ -1235,7 +1168,7 @@
int f_frames, int b_frames,
int *f_boost, int *b_boost) {
FIRSTPASS_STATS this_frame;
-
+ struct twopass_rc *const twopass = &cpi->twopass;
int i;
double boost_score = 0.0;
double mv_ratio_accumulator = 0.0;
@@ -1248,7 +1181,7 @@
// Search forward from the proposed arf/next gf position
for (i = 0; i < f_frames; i++) {
- if (read_frame_stats(&cpi->twopass, &this_frame, (i + offset)) == EOF)
+ if (read_frame_stats(twopass, &this_frame, (i + offset)) == EOF)
break;
// Update the motion related elements to the boost calculation
@@ -1259,12 +1192,12 @@
// We want to discount the flash frame itself and the recovery
// frame that follows as both will have poor scores.
- flash_detected = detect_flash(cpi, (i + offset)) ||
- detect_flash(cpi, (i + offset + 1));
+ flash_detected = detect_flash(twopass, i + offset) ||
+ detect_flash(twopass, i + offset + 1);
// Cumulative effect of prediction quality decay
if (!flash_detected) {
- decay_accumulator *= get_prediction_decay_rate(cpi, &this_frame);
+ decay_accumulator *= get_prediction_decay_rate(&cpi->common, &this_frame);
decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
? MIN_DECAY_FACTOR : decay_accumulator;
}
@@ -1285,7 +1218,7 @@
// Search backward towards last gf position
for (i = -1; i >= -b_frames; i--) {
- if (read_frame_stats(&cpi->twopass, &this_frame, (i + offset)) == EOF)
+ if (read_frame_stats(twopass, &this_frame, (i + offset)) == EOF)
break;
// Update the motion related elements to the boost calculation
@@ -1296,12 +1229,12 @@
// We want to discount the the flash frame itself and the recovery
// frame that follows as both will have poor scores.
- flash_detected = detect_flash(cpi, (i + offset)) ||
- detect_flash(cpi, (i + offset + 1));
+ flash_detected = detect_flash(twopass, i + offset) ||
+ detect_flash(twopass, i + offset + 1);
// Cumulative effect of prediction quality decay
if (!flash_detected) {
- decay_accumulator *= get_prediction_decay_rate(cpi, &this_frame);
+ decay_accumulator *= get_prediction_decay_rate(&cpi->common, &this_frame);
decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
? MIN_DECAY_FACTOR : decay_accumulator;
}
@@ -1461,6 +1394,7 @@
static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
FIRSTPASS_STATS next_frame = { 0 };
FIRSTPASS_STATS *start_pos;
+ struct twopass_rc *const twopass = &cpi->twopass;
int i;
double boost_score = 0.0;
double old_boost_score = 0.0;
@@ -1481,8 +1415,8 @@
double mv_ratio_accumulator_thresh;
int max_bits = frame_max_bits(cpi); // Max for a single frame
- unsigned int allow_alt_ref =
- cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
+ unsigned int allow_alt_ref = cpi->oxcf.play_alternate &&
+ cpi->oxcf.lag_in_frames;
int f_boost = 0;
int b_boost = 0;
@@ -1490,11 +1424,11 @@
int active_max_gf_interval;
RATE_CONTROL *const rc = &cpi->rc;
- cpi->twopass.gf_group_bits = 0;
+ twopass->gf_group_bits = 0;
vp9_clear_system_state(); // __asm emms;
- start_pos = cpi->twopass.stats_in;
+ start_pos = twopass->stats_in;
// Load stats for the current frame.
mod_frame_err = calculate_modified_err(cpi, this_frame);
@@ -1525,20 +1459,19 @@
active_max_gf_interval = rc->max_gf_interval;
i = 0;
- while ((i < cpi->twopass.static_scene_max_gf_interval) &&
- (i < rc->frames_to_key)) {
+ while (i < twopass->static_scene_max_gf_interval && i < rc->frames_to_key) {
i++; // Increment the loop counter
// Accumulate error score of frames in this gf group
mod_frame_err = calculate_modified_err(cpi, this_frame);
gf_group_err += mod_frame_err;
- if (EOF == input_stats(&cpi->twopass, &next_frame))
+ if (EOF == input_stats(twopass, &next_frame))
break;
// Test for the case where there is a brief flash but the prediction
// quality back to an earlier frame is then restored.
- flash_detected = detect_flash(cpi, 0);
+ flash_detected = detect_flash(twopass, 0);
// Update the motion related elements to the boost calculation
accumulate_frame_motion_stats(&next_frame,
@@ -1549,14 +1482,14 @@
// Cumulative effect of prediction quality decay
if (!flash_detected) {
last_loop_decay_rate = loop_decay_rate;
- loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+ loop_decay_rate = get_prediction_decay_rate(&cpi->common, &next_frame);
decay_accumulator = decay_accumulator * loop_decay_rate;
// Monitor for static sections.
if ((next_frame.pcnt_inter - next_frame.pcnt_motion) <
zero_motion_accumulator) {
- zero_motion_accumulator =
- (next_frame.pcnt_inter - next_frame.pcnt_motion);
+ zero_motion_accumulator = next_frame.pcnt_inter -
+ next_frame.pcnt_motion;
}
// Break clause to detect very still sections after motion
@@ -1594,14 +1527,14 @@
old_boost_score = boost_score;
}
- cpi->twopass.gf_zeromotion_pct = (int)(zero_motion_accumulator * 1000.0);
+ twopass->gf_zeromotion_pct = (int)(zero_motion_accumulator * 1000.0);
// Don't allow a gf too near the next kf
if ((rc->frames_to_key - i) < MIN_GF_INTERVAL) {
while (i < (rc->frames_to_key + !rc->next_key_frame_forced)) {
i++;
- if (EOF == input_stats(&cpi->twopass, this_frame))
+ if (EOF == input_stats(twopass, this_frame))
break;
if (i < rc->frames_to_key) {
@@ -1793,7 +1726,7 @@
(!rc->source_alt_ref_pending &&
(cpi->common.frame_type != KEY_FRAME))) {
// Per frame bit target for this frame
- rc->per_frame_bandwidth = gf_bits;
+ vp9_rc_set_frame_target(cpi, gf_bits);
}
}
@@ -1895,12 +1828,7 @@
cpi->twopass.gf_group_bits = 0;
// Per frame bit target for this frame.
- cpi->rc.per_frame_bandwidth = target_frame_size;
-}
-
-static int test_for_kf_one_pass(VP9_COMP *cpi) {
- // Placeholder function for auto key frame
- return 0;
+ vp9_rc_set_frame_target(cpi, target_frame_size);
}
static int test_candidate_kf(VP9_COMP *cpi,
@@ -2064,7 +1992,7 @@
// How fast is prediction quality decaying
- loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+ loop_decay_rate = get_prediction_decay_rate(&cpi->common, &next_frame);
// We want to know something about the recent past... rather than
// as used elsewhere where we are concened with decay in prediction
@@ -2120,7 +2048,7 @@
kf_group_intra_err += tmp_frame.intra_error;
kf_group_coded_err += tmp_frame.coded_error;
- // Load a the next frame's stats
+ // Load the next frame's stats.
input_stats(twopass, &tmp_frame);
}
rc->next_key_frame_forced = 1;
@@ -2198,8 +2126,8 @@
r = RMAX;
// How fast is prediction quality decaying
- if (!detect_flash(cpi, 0)) {
- loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+ if (!detect_flash(twopass, 0)) {
+ loop_decay_rate = get_prediction_decay_rate(&cpi->common, &next_frame);
decay_accumulator *= loop_decay_rate;
decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
? MIN_DECAY_FACTOR : decay_accumulator;
@@ -2238,8 +2166,8 @@
if (kf_boost < (rc->frames_to_key * 3))
kf_boost = (rc->frames_to_key * 3);
- if (kf_boost < 300) // Min KF boost
- kf_boost = 300;
+ if (kf_boost < MIN_KF_BOOST)
+ kf_boost = MIN_KF_BOOST;
// Make a note of baseline boost and the zero motion
// accumulator value for use elsewhere.
@@ -2248,7 +2176,7 @@
// We do three calculations for kf size.
// The first is based on the error score for the whole kf group.
- // The second (optionaly) on the key frames own error if this is
+ // The second (optionally) on the key frames own error if this is
// smaller than the average for the group.
// The final one insures that the frame receives at least the
// allocation it would have received based on its own error score vs
@@ -2279,8 +2207,8 @@
((double)twopass->kf_group_bits / allocation_chunks));
// If the key frame is actually easier than the average for the
- // kf group (which does sometimes happen... eg a blank intro frame)
- // Then use an alternate calculation based on the kf error score
+ // kf group (which does sometimes happen, e.g. a blank intro frame)
+ // then use an alternate calculation based on the kf error score
// which should give a smaller key frame.
if (kf_mod_err < kf_group_err / rc->frames_to_key) {
double alt_kf_grp_bits = ((double)twopass->bits_left *
@@ -2303,13 +2231,9 @@
twopass->kf_bits = alt_kf_bits;
}
}
-
twopass->kf_group_bits -= twopass->kf_bits;
-
- // Peer frame bit target for this frame
- rc->per_frame_bandwidth = twopass->kf_bits;
- // Convert to a per second bitrate
- cpi->target_bandwidth = (int)(twopass->kf_bits * cpi->output_framerate);
+ // Per frame bit target for this frame.
+ vp9_rc_set_frame_target(cpi, twopass->kf_bits);
}
// Note the total error score of the kf group minus the key frame itself
@@ -2321,61 +2245,7 @@
twopass->modified_error_left -= kf_group_err;
}
-void vp9_get_svc_params(VP9_COMP *cpi) {
- VP9_COMMON *const cm = &cpi->common;
- if ((cm->current_video_frame == 0) ||
- (cm->frame_flags & FRAMEFLAGS_KEY) ||
- (cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
- cpi->key_frame_frequency == 0))) {
- cm->frame_type = KEY_FRAME;
- } else {
- cm->frame_type = INTER_FRAME;
- }
- cpi->rc.frames_till_gf_update_due = INT_MAX;
- cpi->rc.baseline_gf_interval = INT_MAX;
-}
-
-void vp9_get_one_pass_params(VP9_COMP *cpi) {
- VP9_COMMON *const cm = &cpi->common;
- if (!cpi->refresh_alt_ref_frame &&
- (cm->current_video_frame == 0 ||
- cm->frame_flags & FRAMEFLAGS_KEY ||
- cpi->rc.frames_to_key == 0 ||
- (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
- cm->frame_type = KEY_FRAME;
- cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
- cpi->rc.frames_to_key == 0;
- cpi->rc.frames_to_key = cpi->key_frame_frequency;
- cpi->rc.kf_boost = 300;
- } else {
- cm->frame_type = INTER_FRAME;
- }
- if (cpi->rc.frames_till_gf_update_due == 0) {
- cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
- cpi->refresh_golden_frame = 1;
- }
-}
-
-void vp9_get_one_pass_cbr_params(VP9_COMP *cpi) {
- VP9_COMMON *const cm = &cpi->common;
- if ((cm->current_video_frame == 0 ||
- cm->frame_flags & FRAMEFLAGS_KEY ||
- cpi->rc.frames_to_key == 0 ||
- (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
- cm->frame_type = KEY_FRAME;
- cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
- cpi->rc.frames_to_key == 0;
- cpi->rc.frames_to_key = cpi->key_frame_frequency;
- cpi->rc.kf_boost = 300;
- } else {
- cm->frame_type = INTER_FRAME;
- }
- // Don't use gf_update by default in CBR mode.
- cpi->rc.frames_till_gf_update_due = INT_MAX;
- cpi->rc.baseline_gf_interval = INT_MAX;
-}
-
-void vp9_get_first_pass_params(VP9_COMP *cpi) {
+void vp9_rc_get_first_pass_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
if (!cpi->refresh_alt_ref_frame &&
(cm->current_video_frame == 0 ||
@@ -2388,36 +2258,38 @@
cpi->rc.frames_to_key = INT_MAX;
}
-void vp9_get_second_pass_params(VP9_COMP *cpi) {
- int tmp_q;
- int frames_left = (int)(cpi->twopass.total_stats.count -
- cpi->common.current_video_frame);
-
+void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ RATE_CONTROL *const rc = &cpi->rc;
+ struct twopass_rc *const twopass = &cpi->twopass;
+ const int frames_left = (int)(twopass->total_stats.count -
+ cm->current_video_frame);
FIRSTPASS_STATS this_frame;
FIRSTPASS_STATS this_frame_copy;
- RATE_CONTROL *rc = &cpi->rc;
double this_frame_intra_error;
double this_frame_coded_error;
+ int target;
+
+ if (!twopass->stats_in)
+ return;
if (cpi->refresh_alt_ref_frame) {
- cpi->common.frame_type = INTER_FRAME;
+ cm->frame_type = INTER_FRAME;
+ vp9_rc_set_frame_target(cpi, twopass->gf_bits);
return;
}
- if (!cpi->twopass.stats_in)
- return;
vp9_clear_system_state();
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
rc->active_worst_quality = cpi->oxcf.cq_level;
- } else if (cpi->common.current_video_frame == 0) {
+ } else if (cm->current_video_frame == 0) {
// Special case code for first frame.
- int section_target_bandwidth =
- (int)(cpi->twopass.bits_left / frames_left);
-
- tmp_q = estimate_max_q(cpi, &cpi->twopass.total_left_stats,
- section_target_bandwidth);
+ const int section_target_bandwidth = (int)(twopass->bits_left /
+ frames_left);
+ const int tmp_q = estimate_max_q(cpi, &twopass->total_left_stats,
+ section_target_bandwidth);
rc->active_worst_quality = tmp_q;
rc->ni_av_qi = tmp_q;
@@ -2431,7 +2303,7 @@
// adjust_maxq_qrange(cpi);
}
vp9_zero(this_frame);
- if (EOF == input_stats(&cpi->twopass, &this_frame))
+ if (EOF == input_stats(twopass, &this_frame))
return;
this_frame_intra_error = this_frame.intra_error;
@@ -2439,12 +2311,12 @@
// keyframe and section processing !
if (rc->frames_to_key == 0 ||
- (cpi->common.frame_flags & FRAMEFLAGS_KEY)) {
+ (cm->frame_flags & FRAMEFLAGS_KEY)) {
// Define next KF group and assign bits to it
this_frame_copy = this_frame;
find_next_key_frame(cpi, &this_frame_copy);
} else {
- cpi->common.frame_type = INTER_FRAME;
+ cm->frame_type = INTER_FRAME;
}
// Is this a GF / ARF (Note that a KF is always also a GF)
@@ -2462,10 +2334,10 @@
}
#endif
- if (cpi->twopass.gf_zeromotion_pct > 995) {
+ if (twopass->gf_zeromotion_pct > 995) {
// As long as max_thresh for encode breakout is small enough, it is ok
// to enable it for no-show frame, i.e. set enable_encode_breakout to 2.
- if (!cpi->common.show_frame)
+ if (!cm->show_frame)
cpi->enable_encode_breakout = 0;
else
cpi->enable_encode_breakout = 2;
@@ -2481,24 +2353,24 @@
}
// Keep a globally available copy of this and the next frame's iiratio.
- cpi->twopass.this_iiratio = (int)(this_frame_intra_error /
+ twopass->this_iiratio = (int)(this_frame_intra_error /
DOUBLE_DIVIDE_CHECK(this_frame_coded_error));
{
FIRSTPASS_STATS next_frame;
- if (lookup_next_frame_stats(&cpi->twopass, &next_frame) != EOF) {
- cpi->twopass.next_iiratio = (int)(next_frame.intra_error /
- DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
+ if (lookup_next_frame_stats(twopass, &next_frame) != EOF) {
+ twopass->next_iiratio = (int)(next_frame.intra_error /
+ DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
}
}
- // Set nominal per second bandwidth for this frame
- cpi->target_bandwidth = (int)(rc->per_frame_bandwidth *
- cpi->output_framerate);
- if (cpi->target_bandwidth < 0)
- cpi->target_bandwidth = 0;
+ if (cpi->common.frame_type == KEY_FRAME)
+ target = vp9_rc_clamp_iframe_target_size(cpi, rc->this_frame_target);
+ else
+ target = vp9_rc_clamp_pframe_target_size(cpi, rc->this_frame_target);
+ vp9_rc_set_frame_target(cpi, target);
// Update the total stats remaining structure
- subtract_stats(&cpi->twopass.total_left_stats, &this_frame);
+ subtract_stats(&twopass->total_left_stats, &this_frame);
}
void vp9_twopass_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
@@ -2506,5 +2378,18 @@
cpi->twopass.bits_left -= cpi->rc.this_frame_target;
#else
cpi->twopass.bits_left -= 8 * bytes_used;
+ // Update bits left to the kf and gf groups to account for overshoot or
+ // undershoot on these frames
+ if (cm->frame_type == KEY_FRAME) {
+ cpi->twopass.kf_group_bits += cpi->rc.this_frame_target -
+ cpi->rc.projected_frame_size;
+
+ cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0);
+ } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) {
+ cpi->twopass.gf_group_bits += cpi->rc.this_frame_target -
+ cpi->rc.projected_frame_size;
+
+ cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0);
+ }
#endif
}
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index ca5b100..19b5981 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -17,18 +17,17 @@
#endif
void vp9_init_first_pass(VP9_COMP *cpi);
+void vp9_rc_get_first_pass_params(VP9_COMP *cpi);
void vp9_first_pass(VP9_COMP *cpi);
void vp9_end_first_pass(VP9_COMP *cpi);
void vp9_init_second_pass(VP9_COMP *cpi);
-void vp9_get_second_pass_params(VP9_COMP *cpi);
+void vp9_rc_get_second_pass_params(VP9_COMP *cpi);
void vp9_end_second_pass(VP9_COMP *cpi);
-void vp9_get_first_pass_params(VP9_COMP *cpi);
-void vp9_get_one_pass_params(VP9_COMP *cpi);
-void vp9_get_one_pass_cbr_params(VP9_COMP *cpi);
-void vp9_get_svc_params(VP9_COMP *cpi);
-
+// Post encode update of the rate control parameters for 2-pass
+void vp9_twopass_postencode_update(struct VP9_COMP *cpi,
+ uint64_t bytes_used);
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/encoder/vp9_lookahead.c b/vp9/encoder/vp9_lookahead.c
index ee73ff1..e6e59c0 100644
--- a/vp9/encoder/vp9_lookahead.c
+++ b/vp9/encoder/vp9_lookahead.c
@@ -173,7 +173,6 @@
int index) {
struct lookahead_entry *buf = NULL;
- assert(index < (int)ctx->max_sz);
if (index < (int)ctx->sz) {
index += ctx->read_idx;
if (index >= (int)ctx->max_sz)
diff --git a/vp9/encoder/vp9_mbgraph.h b/vp9/encoder/vp9_mbgraph.h
index 79dd2bc..bc2a704 100644
--- a/vp9/encoder/vp9_mbgraph.h
+++ b/vp9/encoder/vp9_mbgraph.h
@@ -15,7 +15,23 @@
extern "C" {
#endif
-void vp9_update_mbgraph_stats(VP9_COMP *cpi);
+typedef struct {
+ struct {
+ int err;
+ union {
+ int_mv mv;
+ MB_PREDICTION_MODE mode;
+ } m;
+ } ref[MAX_REF_FRAMES];
+} MBGRAPH_MB_STATS;
+
+typedef struct {
+ MBGRAPH_MB_STATS *mb_stats;
+} MBGRAPH_FRAME_STATS;
+
+struct VP9_COMP;
+
+void vp9_update_mbgraph_stats(struct VP9_COMP *cpi);
#ifdef __cplusplus
} // extern "C"
diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c
index d48dace..36591bd 100644
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -184,7 +184,8 @@
return (x & 7) << 1;
}
-static INLINE uint8_t *pre(uint8_t *buf, int stride, int r, int c, int offset) {
+static INLINE const uint8_t *pre(const uint8_t *buf, int stride, int r, int c,
+ int offset) {
return &buf[(r >> 3) * stride + (c >> 3) - offset];
}
@@ -273,7 +274,7 @@
} \
}
-int vp9_find_best_sub_pixel_tree(MACROBLOCK *x,
+int vp9_find_best_sub_pixel_tree(const MACROBLOCK *x,
MV *bestmv, const MV *ref_mv,
int allow_hp,
int error_per_bit,
@@ -283,9 +284,9 @@
int *mvjcost, int *mvcost[2],
int *distortion,
unsigned int *sse1) {
- uint8_t *z = x->plane[0].src.buf;
+ const uint8_t *z = x->plane[0].src.buf;
const int src_stride = x->plane[0].src.stride;
- MACROBLOCKD *xd = &x->e_mbd;
+ const MACROBLOCKD *xd = &x->e_mbd;
unsigned int besterr = INT_MAX;
unsigned int sse;
unsigned int whichdir;
@@ -296,7 +297,7 @@
const int y_stride = xd->plane[0].pre[0].stride;
const int offset = bestmv->row * y_stride + bestmv->col;
- uint8_t *y = xd->plane[0].pre[0].buf + offset;
+ const uint8_t *y = xd->plane[0].pre[0].buf + offset;
int rr = ref_mv->row;
int rc = ref_mv->col;
@@ -365,7 +366,7 @@
vfp->svaf(pre(y, y_stride, r, c, offset), y_stride, sp(c), sp(r), \
z, src_stride, &sse, second_pred)
-int vp9_find_best_sub_pixel_comp_tree(MACROBLOCK *x,
+int vp9_find_best_sub_pixel_comp_tree(const MACROBLOCK *x,
MV *bestmv, const MV *ref_mv,
int allow_hp,
int error_per_bit,
@@ -377,9 +378,9 @@
unsigned int *sse1,
const uint8_t *second_pred,
int w, int h) {
- uint8_t *z = x->plane[0].src.buf;
+ const uint8_t *z = x->plane[0].src.buf;
const int src_stride = x->plane[0].src.stride;
- MACROBLOCKD *xd = &x->e_mbd;
+ const MACROBLOCKD *xd = &x->e_mbd;
unsigned int besterr = INT_MAX;
unsigned int sse;
unsigned int whichdir;
@@ -391,7 +392,7 @@
DECLARE_ALIGNED_ARRAY(16, uint8_t, comp_pred, 64 * 64);
const int y_stride = xd->plane[0].pre[0].stride;
const int offset = bestmv->row * y_stride + bestmv->col;
- uint8_t *y = xd->plane[0].pre[0].buf + offset;
+ const uint8_t *y = xd->plane[0].pre[0].buf + offset;
int rr = ref_mv->row;
int rc = ref_mv->col;
@@ -465,7 +466,6 @@
#undef PRE
#undef DIST
#undef CHECK_BETTER
-#undef SP
static INLINE int check_bounds(const MACROBLOCK *x, int row, int col,
int range) {
@@ -484,25 +484,17 @@
#define CHECK_BETTER \
{\
- if (thissad < bestsad)\
- {\
+ if (thissad < bestsad) {\
if (use_mvcost) \
thissad += mvsad_err_cost(&this_mv, &fcenter_mv, \
- mvjsadcost, mvsadcost, \
- sad_per_bit);\
- if (thissad < bestsad)\
- {\
+ mvjsadcost, mvsadcost, sad_per_bit);\
+ if (thissad < bestsad) {\
bestsad = thissad;\
best_site = i;\
}\
}\
}
-#define get_next_chkpts(list, i, n) \
- list[0] = ((i) == 0 ? (n) - 1 : (i) - 1); \
- list[1] = (i); \
- list[2] = ((i) == (n) - 1 ? 0 : (i) + 1);
-
#define MAX_PATTERN_SCALES 11
#define MAX_PATTERN_CANDIDATES 8 // max number of canddiates per scale
#define PATTERN_CANDIDATES_REF 3 // number of refinement candidates
@@ -511,7 +503,7 @@
// Each scale can have a different number of candidates and shape of
// candidates as indicated in the num_candidates and candidates arrays
// passed into this function
-static int vp9_pattern_search(MACROBLOCK *x,
+static int vp9_pattern_search(const MACROBLOCK *x,
MV *ref_mv,
int search_param,
int sad_per_bit,
@@ -523,37 +515,34 @@
const int num_candidates[MAX_PATTERN_SCALES],
const MV candidates[MAX_PATTERN_SCALES]
[MAX_PATTERN_CANDIDATES]) {
- const MACROBLOCKD* const xd = &x->e_mbd;
+ const MACROBLOCKD *const xd = &x->e_mbd;
static const int search_param_to_steps[MAX_MVSEARCH_STEPS] = {
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
};
int i, j, s, t;
- uint8_t *what = x->plane[0].src.buf;
- int what_stride = x->plane[0].src.stride;
- int in_what_stride = xd->plane[0].pre[0].stride;
+ const uint8_t *what = x->plane[0].src.buf;
+ const int what_stride = x->plane[0].src.stride;
+ const int in_what_stride = xd->plane[0].pre[0].stride;
int br, bc;
MV this_mv;
int bestsad = INT_MAX;
int thissad;
- uint8_t *base_offset;
- uint8_t *this_offset;
+ const uint8_t *base_offset;
+ const uint8_t *this_offset;
int k = -1;
int best_site = -1;
- MV fcenter_mv;
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
int best_init_s = search_param_to_steps[search_param];
- int *mvjsadcost = x->nmvjointsadcost;
+ const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
// adjust ref_mv to make sure it is within MV range
clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
br = ref_mv->row;
bc = ref_mv->col;
// Work out the start point for the search
- base_offset = (uint8_t *)(xd->plane[0].pre[0].buf);
+ base_offset = xd->plane[0].pre[0].buf;
this_offset = base_offset + (br * in_what_stride) + bc;
this_mv.row = br;
this_mv.col = bc;
@@ -649,7 +638,10 @@
do {
int next_chkpts_indices[PATTERN_CANDIDATES_REF];
best_site = -1;
- get_next_chkpts(next_chkpts_indices, k, num_candidates[s]);
+ next_chkpts_indices[0] = (k == 0) ? num_candidates[s] - 1 : k - 1;
+ next_chkpts_indices[1] = k;
+ next_chkpts_indices[2] = (k == num_candidates[s] - 1) ? 0 : k + 1;
+
if (check_bounds(x, br, bc, 1 << s)) {
for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
this_mv.row = br + candidates[s][next_chkpts_indices[i]].row;
@@ -686,17 +678,15 @@
// Check 4 1-away neighbors if do_refine is true.
// For most well-designed schemes do_refine will not be necessary.
if (do_refine) {
- static const MV neighbors[4] = {
- {0, -1}, { -1, 0}, {1, 0}, {0, 1},
- };
+ static const MV neighbors[4] = { {0, -1}, { -1, 0}, {1, 0}, {0, 1} };
for (j = 0; j < 16; j++) {
best_site = -1;
if (check_bounds(x, br, bc, 1)) {
for (i = 0; i < 4; i++) {
this_mv.row = br + neighbors[i].row;
this_mv.col = bc + neighbors[i].col;
- this_offset = base_offset + (this_mv.row * (in_what_stride)) +
- this_mv.col;
+ this_offset = base_offset + this_mv.row * in_what_stride +
+ this_mv.col;
thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride,
bestsad);
CHECK_BETTER
@@ -707,13 +697,13 @@
this_mv.col = bc + neighbors[i].col;
if (check_point(x, &this_mv))
continue;
- this_offset = base_offset + (this_mv.row * (in_what_stride)) +
- this_mv.col;
+ this_offset = base_offset + this_mv.row * in_what_stride +
+ this_mv.col;
thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride,
bestsad);
CHECK_BETTER
}
- }
+ }
if (best_site == -1) {
break;
@@ -742,7 +732,7 @@
}
-int vp9_hex_search(MACROBLOCK *x,
+int vp9_hex_search(const MACROBLOCK *x,
MV *ref_mv,
int search_param,
int sad_per_bit,
@@ -770,14 +760,13 @@
{{-512, -1024}, {512, -1024}, {1024, 0}, {512, 1024}, { -512, 1024},
{ -1024, 0}},
};
- return
- vp9_pattern_search(x, ref_mv, search_param, sad_per_bit,
- do_init_search, 0, vfp, use_mvcost,
- center_mv, best_mv,
- hex_num_candidates, hex_candidates);
+ return vp9_pattern_search(x, ref_mv, search_param, sad_per_bit,
+ do_init_search, 0, vfp, use_mvcost,
+ center_mv, best_mv,
+ hex_num_candidates, hex_candidates);
}
-int vp9_bigdia_search(MACROBLOCK *x,
+int vp9_bigdia_search(const MACROBLOCK *x,
MV *ref_mv,
int search_param,
int sad_per_bit,
@@ -818,7 +807,7 @@
bigdia_num_candidates, bigdia_candidates);
}
-int vp9_square_search(MACROBLOCK *x,
+int vp9_square_search(const MACROBLOCK *x,
MV *ref_mv,
int search_param,
int sad_per_bit,
@@ -861,27 +850,26 @@
#undef CHECK_BETTER
-int vp9_full_range_search_c(MACROBLOCK *x, MV *ref_mv, MV *best_mv,
+int vp9_full_range_search_c(const MACROBLOCK *x, MV *ref_mv, MV *best_mv,
int search_param, int sad_per_bit, int *num00,
vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
int *mvcost[2], const MV *center_mv) {
- const MACROBLOCKD* const xd = &x->e_mbd;
- uint8_t *what = x->plane[0].src.buf;
- int what_stride = x->plane[0].src.stride;
- uint8_t *in_what;
- int in_what_stride = xd->plane[0].pre[0].stride;
- uint8_t *best_address;
+ const MACROBLOCKD *const xd = &x->e_mbd;
+ const uint8_t *what = x->plane[0].src.buf;
+ const int what_stride = x->plane[0].src.stride;
+ const uint8_t *in_what;
+ const int in_what_stride = xd->plane[0].pre[0].stride;
+ const uint8_t *best_address;
MV this_mv;
int bestsad = INT_MAX;
int ref_row, ref_col;
- uint8_t *check_here;
int thissad;
- MV fcenter_mv;
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
- int *mvjsadcost = x->nmvjointsadcost;
+ const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
int tr, tc;
@@ -893,9 +881,6 @@
int start_row, end_row;
int i;
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
ref_row = ref_mv->row;
ref_col = ref_mv->col;
@@ -904,8 +889,7 @@
best_mv->col = ref_col;
// Work out the start point for the search
- in_what = (uint8_t *)(xd->plane[0].pre[0].buf +
- (ref_row * (xd->plane[0].pre[0].stride)) + ref_col);
+ in_what = xd->plane[0].pre[0].buf + ref_row * in_what_stride + ref_col;
best_address = in_what;
// Check the starting position
@@ -944,7 +928,7 @@
}
} else {
for (i = 0; i < end_col - tc; ++i) {
- check_here = in_what + tr * in_what_stride + tc + i;
+ const uint8_t *check_here = in_what + tr * in_what_stride + tc + i;
thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
bestsad);
@@ -980,21 +964,20 @@
mvjcost, mvcost, x->errorperbit);
}
-int vp9_diamond_search_sad_c(MACROBLOCK *x,
+int vp9_diamond_search_sad_c(const MACROBLOCK *x,
MV *ref_mv, MV *best_mv,
int search_param, int sad_per_bit, int *num00,
vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
int *mvcost[2], const MV *center_mv) {
int i, j, step;
- const MACROBLOCKD* const xd = &x->e_mbd;
- uint8_t *what = x->plane[0].src.buf;
- int what_stride = x->plane[0].src.stride;
- uint8_t *in_what;
- int in_what_stride = xd->plane[0].pre[0].stride;
- uint8_t *best_address;
+ const MACROBLOCKD *const xd = &x->e_mbd;
+ const uint8_t *what = x->plane[0].src.buf;
+ const int what_stride = x->plane[0].src.stride;
+ const uint8_t *in_what;
+ const int in_what_stride = xd->plane[0].pre[0].stride;
+ const uint8_t *best_address;
- int tot_steps;
MV this_mv;
int bestsad = INT_MAX;
@@ -1003,18 +986,20 @@
int ref_row, ref_col;
int this_row_offset, this_col_offset;
- search_site *ss;
- uint8_t *check_here;
+ // search_param determines the length of the initial step and hence the number
+ // of iterations
+ // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 =
+ // (MAX_FIRST_STEP/4) pel... etc.
+ const search_site *const ss = &x->ss[search_param * x->searches_per_step];
+ const int tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
int thissad;
- MV fcenter_mv;
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
- int *mvjsadcost = x->nmvjointsadcost;
+ const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
ref_row = ref_mv->row;
ref_col = ref_mv->col;
@@ -1023,8 +1008,7 @@
best_mv->col = ref_col;
// Work out the start point for the search
- in_what = (uint8_t *)(xd->plane[0].pre[0].buf +
- ref_row * in_what_stride + ref_col);
+ in_what = xd->plane[0].pre[0].buf + ref_row * in_what_stride + ref_col;
best_address = in_what;
// Check the starting position
@@ -1032,13 +1016,6 @@
+ mvsad_err_cost(best_mv, &fcenter_mv,
mvjsadcost, mvsadcost, sad_per_bit);
- // search_param determines the length of the initial step and hence the number
- // of iterations
- // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 =
- // (MAX_FIRST_STEP/4) pel... etc.
- ss = &x->ss[search_param * x->searches_per_step];
- tot_steps = (x->ss_count / x->searches_per_step) - search_param;
-
i = 1;
for (step = 0; step < tot_steps; step++) {
@@ -1051,7 +1028,7 @@
(this_col_offset < x->mv_col_max) &&
(this_row_offset > x->mv_row_min) &&
(this_row_offset < x->mv_row_max)) {
- check_here = ss[i].offset + best_address;
+ const uint8_t *const check_here = ss[i].offset + best_address;
thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
bestsad);
@@ -1121,7 +1098,7 @@
mvjcost, mvcost, x->errorperbit);
}
-int vp9_diamond_search_sadx4(MACROBLOCK *x,
+int vp9_diamond_search_sadx4(const MACROBLOCK *x,
MV *ref_mv, MV *best_mv, int search_param,
int sad_per_bit, int *num00,
vp9_variance_fn_ptr_t *fn_ptr,
@@ -1129,14 +1106,13 @@
const MV *center_mv) {
int i, j, step;
- const MACROBLOCKD* const xd = &x->e_mbd;
+ const MACROBLOCKD *const xd = &x->e_mbd;
uint8_t *what = x->plane[0].src.buf;
- int what_stride = x->plane[0].src.stride;
- uint8_t *in_what;
- int in_what_stride = xd->plane[0].pre[0].stride;
- uint8_t *best_address;
+ const int what_stride = x->plane[0].src.stride;
+ const uint8_t *in_what;
+ const int in_what_stride = xd->plane[0].pre[0].stride;
+ const uint8_t *best_address;
- int tot_steps;
MV this_mv;
unsigned int bestsad = INT_MAX;
@@ -1147,18 +1123,21 @@
int ref_col;
int this_row_offset;
int this_col_offset;
- search_site *ss;
- uint8_t *check_here;
+ // search_param determines the length of the initial step and hence the number
+ // of iterations.
+ // 0 = initial step (MAX_FIRST_STEP) pel
+ // 1 = (MAX_FIRST_STEP/2) pel,
+ // 2 = (MAX_FIRST_STEP/4) pel...
+ const search_site *ss = &x->ss[search_param * x->searches_per_step];
+ const int tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
unsigned int thissad;
- MV fcenter_mv;
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
- int *mvjsadcost = x->nmvjointsadcost;
+ const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
ref_row = ref_mv->row;
ref_col = ref_mv->col;
@@ -1167,8 +1146,7 @@
best_mv->col = ref_col;
// Work out the start point for the search
- in_what = (uint8_t *)(xd->plane[0].pre[0].buf +
- ref_row * in_what_stride + ref_col);
+ in_what = xd->plane[0].pre[0].buf + ref_row * in_what_stride + ref_col;
best_address = in_what;
// Check the starting position
@@ -1176,14 +1154,6 @@
+ mvsad_err_cost(best_mv, &fcenter_mv,
mvjsadcost, mvsadcost, sad_per_bit);
- // search_param determines the length of the initial step and hence the number
- // of iterations.
- // 0 = initial step (MAX_FIRST_STEP) pel
- // 1 = (MAX_FIRST_STEP/2) pel,
- // 2 = (MAX_FIRST_STEP/4) pel...
- ss = &x->ss[search_param * x->searches_per_step];
- tot_steps = (x->ss_count / x->searches_per_step) - search_param;
-
i = 1;
for (step = 0; step < tot_steps; step++) {
@@ -1235,7 +1205,7 @@
(this_col_offset < x->mv_col_max) &&
(this_row_offset > x->mv_row_min) &&
(this_row_offset < x->mv_row_max)) {
- check_here = ss[i].offset + best_address;
+ const uint8_t *const check_here = ss[i].offset + best_address;
thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
bestsad);
@@ -1368,38 +1338,35 @@
return bestsme;
}
-int vp9_full_search_sad_c(MACROBLOCK *x, MV *ref_mv,
+int vp9_full_search_sad_c(const MACROBLOCK *x, MV *ref_mv,
int sad_per_bit, int distance,
vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
int *mvcost[2],
const MV *center_mv, int n) {
- const MACROBLOCKD* const xd = &x->e_mbd;
+ const MACROBLOCKD *const xd = &x->e_mbd;
const uint8_t *const what = x->plane[0].src.buf;
const int what_stride = x->plane[0].src.stride;
const uint8_t *const in_what = xd->plane[0].pre[0].buf;
const int in_what_stride = xd->plane[0].pre[0].stride;
- const uint8_t *bestaddress;
- MV *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0].as_mv;
+ MV *best_mv = &xd->mi_8x8[0]->bmi[n].as_mv[0].as_mv;
MV this_mv;
int bestsad = INT_MAX;
int r, c;
int thissad;
int ref_row = ref_mv->row;
int ref_col = ref_mv->col;
- int row_min = ref_row - distance;
- int row_max = ref_row + distance;
- int col_min = ref_col - distance;
- int col_max = ref_col + distance;
- MV fcenter_mv;
-
- int *mvjsadcost = x->nmvjointsadcost;
+ // Apply further limits to prevent us looking using vectors that stretch
+ // beyond the UMV border
+ const int row_min = MAX(ref_row - distance, x->mv_row_min);
+ const int row_max = MIN(ref_row + distance, x->mv_row_max);
+ const int col_min = MAX(ref_col - distance, x->mv_col_min);
+ const int col_max = MIN(ref_col + distance, x->mv_col_max);
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+ const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
// Work out the mid point for the search
- bestaddress = &in_what[ref_row * in_what_stride + ref_col];
+ const uint8_t *bestaddress = &in_what[ref_row * in_what_stride + ref_col];
best_mv->row = ref_row;
best_mv->col = ref_col;
@@ -1410,13 +1377,6 @@
+ mvsad_err_cost(best_mv, &fcenter_mv,
mvjsadcost, mvsadcost, sad_per_bit);
- // Apply further limits to prevent us looking using vectors that stretch
- // beyond the UMV border
- col_min = MAX(col_min, x->mv_col_min);
- col_max = MIN(col_max, x->mv_col_max);
- row_min = MAX(row_min, x->mv_row_min);
- row_max = MIN(row_max, x->mv_row_max);
-
for (r = row_min; r < row_max; r++) {
const uint8_t *check_here = &in_what[r * in_what_stride + col_min];
this_mv.row = r;
@@ -1452,37 +1412,36 @@
return INT_MAX;
}
-int vp9_full_search_sadx3(MACROBLOCK *x, MV *ref_mv,
+int vp9_full_search_sadx3(const MACROBLOCK *x, MV *ref_mv,
int sad_per_bit, int distance,
vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
int *mvcost[2], const MV *center_mv, int n) {
- const MACROBLOCKD* const xd = &x->e_mbd;
+ const MACROBLOCKD *const xd = &x->e_mbd;
const uint8_t *const what = x->plane[0].src.buf;
const int what_stride = x->plane[0].src.stride;
const uint8_t *const in_what = xd->plane[0].pre[0].buf;
const int in_what_stride = xd->plane[0].pre[0].stride;
- const uint8_t *bestaddress;
- MV *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0].as_mv;
+ MV *best_mv = &xd->mi_8x8[0]->bmi[n].as_mv[0].as_mv;
MV this_mv;
unsigned int bestsad = INT_MAX;
int r, c;
unsigned int thissad;
int ref_row = ref_mv->row;
int ref_col = ref_mv->col;
- int row_min = ref_row - distance;
- int row_max = ref_row + distance;
- int col_min = ref_col - distance;
- int col_max = ref_col + distance;
+
+ // Apply further limits to prevent us looking using vectors that stretch
+ // beyond the UMV border
+ const int row_min = MAX(ref_row - distance, x->mv_row_min);
+ const int row_max = MIN(ref_row + distance, x->mv_row_max);
+ const int col_min = MAX(ref_col - distance, x->mv_col_min);
+ const int col_max = MIN(ref_col + distance, x->mv_col_max);
unsigned int sad_array[3];
- MV fcenter_mv;
- int *mvjsadcost = x->nmvjointsadcost;
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+ const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
// Work out the mid point for the search
- bestaddress = &in_what[ref_row * in_what_stride + ref_col];
+ const uint8_t *bestaddress = &in_what[ref_row * in_what_stride + ref_col];
best_mv->row = ref_row;
best_mv->col = ref_col;
@@ -1493,13 +1452,6 @@
+ mvsad_err_cost(best_mv, &fcenter_mv,
mvjsadcost, mvsadcost, sad_per_bit);
- // Apply further limits to prevent us looking using vectors that stretch
- // beyond the UMV border
- col_min = MAX(col_min, x->mv_col_min);
- col_max = MIN(col_max, x->mv_col_max);
- row_min = MAX(row_min, x->mv_row_min);
- row_max = MIN(row_max, x->mv_row_max);
-
for (r = row_min; r < row_max; r++) {
const uint8_t *check_here = &in_what[r * in_what_stride + col_min];
this_mv.row = r;
@@ -1565,40 +1517,39 @@
return INT_MAX;
}
-int vp9_full_search_sadx8(MACROBLOCK *x, MV *ref_mv,
+int vp9_full_search_sadx8(const MACROBLOCK *x, MV *ref_mv,
int sad_per_bit, int distance,
vp9_variance_fn_ptr_t *fn_ptr,
int *mvjcost, int *mvcost[2],
const MV *center_mv, int n) {
- const MACROBLOCKD* const xd = &x->e_mbd;
+ const MACROBLOCKD *const xd = &x->e_mbd;
const uint8_t *const what = x->plane[0].src.buf;
const int what_stride = x->plane[0].src.stride;
const uint8_t *const in_what = xd->plane[0].pre[0].buf;
const int in_what_stride = xd->plane[0].pre[0].stride;
- const uint8_t *bestaddress;
- MV *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0].as_mv;
+ MV *best_mv = &xd->mi_8x8[0]->bmi[n].as_mv[0].as_mv;
MV this_mv;
unsigned int bestsad = INT_MAX;
int r, c;
unsigned int thissad;
int ref_row = ref_mv->row;
int ref_col = ref_mv->col;
- int row_min = ref_row - distance;
- int row_max = ref_row + distance;
- int col_min = ref_col - distance;
- int col_max = ref_col + distance;
+
+ // Apply further limits to prevent us looking using vectors that stretch
+ // beyond the UMV border
+ const int row_min = MAX(ref_row - distance, x->mv_row_min);
+ const int row_max = MIN(ref_row + distance, x->mv_row_max);
+ const int col_min = MAX(ref_col - distance, x->mv_col_min);
+ const int col_max = MIN(ref_col + distance, x->mv_col_max);
DECLARE_ALIGNED_ARRAY(16, uint32_t, sad_array8, 8);
unsigned int sad_array[3];
- MV fcenter_mv;
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
- int *mvjsadcost = x->nmvjointsadcost;
+ const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
// Work out the mid point for the search
- bestaddress = &in_what[ref_row * in_what_stride + ref_col];
+ const uint8_t *bestaddress = &in_what[ref_row * in_what_stride + ref_col];
best_mv->row = ref_row;
best_mv->col = ref_col;
@@ -1609,13 +1560,6 @@
+ mvsad_err_cost(best_mv, &fcenter_mv,
mvjsadcost, mvsadcost, sad_per_bit);
- // Apply further limits to prevent us looking using vectors that stretch
- // beyond the UMV border
- col_min = MAX(col_min, x->mv_col_min);
- col_max = MIN(col_max, x->mv_col_max);
- row_min = MAX(row_min, x->mv_row_min);
- row_max = MIN(row_max, x->mv_row_max);
-
for (r = row_min; r < row_max; r++) {
const uint8_t *check_here = &in_what[r * in_what_stride + col_min];
this_mv.row = r;
@@ -1787,33 +1731,28 @@
int search_range, vp9_variance_fn_ptr_t *fn_ptr,
int *mvjcost, int *mvcost[2],
const MV *center_mv) {
- const MACROBLOCKD* const xd = &x->e_mbd;
+ const MACROBLOCKD *const xd = &x->e_mbd;
MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}};
int i, j;
int this_row_offset, this_col_offset;
- int what_stride = x->plane[0].src.stride;
- int in_what_stride = xd->plane[0].pre[0].stride;
- uint8_t *what = x->plane[0].src.buf;
- uint8_t *best_address = xd->plane[0].pre[0].buf +
+ const int what_stride = x->plane[0].src.stride;
+ const int in_what_stride = xd->plane[0].pre[0].stride;
+ const uint8_t *what = x->plane[0].src.buf;
+ const uint8_t *best_address = xd->plane[0].pre[0].buf +
(ref_mv->row * xd->plane[0].pre[0].stride) +
ref_mv->col;
- uint8_t *check_here;
unsigned int thissad;
MV this_mv;
- unsigned int bestsad = INT_MAX;
- MV fcenter_mv;
+
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- fcenter_mv.row = center_mv->row >> 3;
- fcenter_mv.col = center_mv->col >> 3;
-
- bestsad = fn_ptr->sdf(what, what_stride, best_address,
- in_what_stride, 0x7fffffff) +
- mvsad_err_cost(ref_mv, &fcenter_mv,
- mvjsadcost, mvsadcost, error_per_bit);
+ unsigned int bestsad = fn_ptr->sdf(what, what_stride, best_address,
+ in_what_stride, 0x7fffffff) +
+ mvsad_err_cost(ref_mv, &fcenter_mv, mvjsadcost, mvsadcost, error_per_bit);
for (i = 0; i < search_range; i++) {
int best_site = -1;
@@ -1824,11 +1763,12 @@
if (all_in) {
unsigned int sad_array[4];
- unsigned char const *block_offset[4];
- block_offset[0] = best_address - in_what_stride;
- block_offset[1] = best_address - 1;
- block_offset[2] = best_address + 1;
- block_offset[3] = best_address + in_what_stride;
+ uint8_t const *block_offset[4] = {
+ best_address - in_what_stride,
+ best_address - 1,
+ best_address + 1,
+ best_address + in_what_stride
+ };
fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride,
sad_array);
@@ -1855,8 +1795,8 @@
(this_col_offset < x->mv_col_max) &&
(this_row_offset > x->mv_row_min) &&
(this_row_offset < x->mv_row_max)) {
- check_here = (neighbors[j].row) * in_what_stride + neighbors[j].col +
- best_address;
+ const uint8_t *check_here = neighbors[j].row * in_what_stride +
+ neighbors[j].col + best_address;
thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
bestsad);
diff --git a/vp9/encoder/vp9_mcomp.h b/vp9/encoder/vp9_mcomp.h
index 5cd9fd1..28b46b5 100644
--- a/vp9/encoder/vp9_mcomp.h
+++ b/vp9/encoder/vp9_mcomp.h
@@ -48,7 +48,7 @@
vp9_variance_fn_ptr_t *fn_ptr,
const MV *ref_mv, int_mv *dst_mv);
-int vp9_hex_search(MACROBLOCK *x,
+int vp9_hex_search(const MACROBLOCK *x,
MV *ref_mv,
int search_param,
int error_per_bit,
@@ -57,7 +57,7 @@
int use_mvcost,
const MV *center_mv,
MV *best_mv);
-int vp9_bigdia_search(MACROBLOCK *x,
+int vp9_bigdia_search(const MACROBLOCK *x,
MV *ref_mv,
int search_param,
int error_per_bit,
@@ -66,7 +66,7 @@
int use_mvcost,
const MV *center_mv,
MV *best_mv);
-int vp9_square_search(MACROBLOCK *x,
+int vp9_square_search(const MACROBLOCK *x,
MV *ref_mv,
int search_param,
int error_per_bit,
@@ -77,7 +77,7 @@
MV *best_mv);
typedef int (fractional_mv_step_fp) (
- MACROBLOCK *x,
+ const MACROBLOCK *x,
MV *bestmv, const MV *ref_mv,
int allow_hp,
int error_per_bit,
@@ -92,7 +92,7 @@
extern fractional_mv_step_fp vp9_find_best_sub_pixel_tree;
typedef int (fractional_mv_step_comp_fp) (
- MACROBLOCK *x,
+ const MACROBLOCK *x,
MV *bestmv, const MV *ref_mv,
int allow_hp,
int error_per_bit,
@@ -106,7 +106,7 @@
extern fractional_mv_step_comp_fp vp9_find_best_sub_pixel_comp_tree;
-typedef int (*vp9_full_search_fn_t)(MACROBLOCK *x,
+typedef int (*vp9_full_search_fn_t)(const MACROBLOCK *x,
MV *ref_mv, int sad_per_bit,
int distance, vp9_variance_fn_ptr_t *fn_ptr,
int *mvjcost, int *mvcost[2],
@@ -119,7 +119,7 @@
int *mvjcost, int *mvcost[2],
const MV *center_mv);
-typedef int (*vp9_diamond_search_fn_t)(MACROBLOCK *x,
+typedef int (*vp9_diamond_search_fn_t)(const MACROBLOCK *x,
MV *ref_mv, MV *best_mv,
int search_param, int sad_per_bit,
int *num00,
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 1852d1e..fe0a291 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -93,16 +93,7 @@
FILE *keyfile;
#endif
-#ifdef SPEEDSTATS
-unsigned int frames_at_speed[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0};
-#endif
-
-#if defined(SECTIONBITS_OUTPUT)
-extern unsigned __int64 Sectionbits[500];
-#endif
-
-extern void vp9_init_quantizer(VP9_COMP *cpi);
+void vp9_init_quantizer(VP9_COMP *cpi);
static const double in_frame_q_adj_ratio[MAX_SEGMENTS] =
{1.0, 1.5, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0};
@@ -455,14 +446,17 @@
cache_ptr += cm->mi_cols;
}
}
+static int is_slowest_mode(int mode) {
+ return (mode == MODE_SECONDPASS_BEST || mode == MODE_BESTQUALITY);
+}
-static void set_rd_speed_thresholds(VP9_COMP *cpi, int mode) {
+static void set_rd_speed_thresholds(VP9_COMP *cpi) {
SPEED_FEATURES *sf = &cpi->sf;
int i;
// Set baseline threshold values
for (i = 0; i < MAX_MODES; ++i)
- sf->thresh_mult[i] = mode == 0 ? -500 : 0;
+ sf->thresh_mult[i] = is_slowest_mode(cpi->oxcf.mode) ? -500 : 0;
sf->thresh_mult[THR_NEARESTMV] = 0;
sf->thresh_mult[THR_NEARESTG] = 0;
@@ -538,12 +532,12 @@
}
}
-static void set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi, int mode) {
+static void set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi) {
SPEED_FEATURES *sf = &cpi->sf;
int i;
for (i = 0; i < MAX_REFS; ++i)
- sf->thresh_mult_sub8x8[i] = mode == 0 ? -500 : 0;
+ sf->thresh_mult_sub8x8[i] = is_slowest_mode(cpi->oxcf.mode) ? -500 : 0;
sf->thresh_mult_sub8x8[THR_LAST] += 2500;
sf->thresh_mult_sub8x8[THR_GOLD] += 2500;
@@ -626,7 +620,7 @@
sf->disable_filter_search_var_thresh = 50;
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
- sf->auto_min_max_partition_size = 1;
+ sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_LOW_MOTION;
sf->adjust_partitioning_from_last_frame = 1;
sf->last_partitioning_redo_frequency = 3;
@@ -663,7 +657,7 @@
sf->disable_filter_search_var_thresh = 100;
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
- sf->auto_min_max_partition_size = 1;
+ sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL;
sf->adjust_partitioning_from_last_frame = 1;
sf->last_partitioning_redo_frequency = 3;
@@ -698,7 +692,7 @@
sf->disable_filter_search_var_thresh = 200;
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
- sf->auto_min_max_partition_size = 1;
+ sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL;
sf->adjust_partitioning_from_last_frame = 1;
sf->last_partitioning_redo_frequency = 3;
@@ -797,7 +791,7 @@
sf->disable_filter_search_var_thresh = 50;
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
- sf->auto_min_max_partition_size = 1;
+ sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_LOW_MOTION;
sf->adjust_partitioning_from_last_frame = 1;
sf->last_partitioning_redo_frequency = 3;
@@ -835,22 +829,29 @@
}
if (speed >= 4) {
sf->optimize_coefficients = 0;
+ sf->disable_split_mask = DISABLE_ALL_SPLIT;
+ sf->use_fast_lpf_pick = 2;
}
if (speed >= 5) {
int i;
- sf->disable_split_mask = DISABLE_ALL_SPLIT;
+ sf->adaptive_rd_thresh = 5;
+ sf->auto_min_max_partition_size = frame_is_intra_only(cm) ?
+ RELAXED_NEIGHBORING_MIN_MAX : STRICT_NEIGHBORING_MIN_MAX;
+ sf->subpel_force_stop = 1;
for (i = 0; i < TX_SIZES; i++) {
sf->intra_y_mode_mask[i] = INTRA_DC_H_V;
sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY;
}
- sf->use_fast_lpf_pick = 2;
+ sf->RD = 0;
+ }
+ if (speed >= 6) {
+ sf->super_fast_rtc = 1;
}
}
void vp9_set_speed_features(VP9_COMP *cpi) {
SPEED_FEATURES *sf = &cpi->sf;
VP9_COMMON *cm = &cpi->common;
- int mode = cpi->compressor_speed;
int speed = cpi->speed;
int i;
@@ -867,6 +868,7 @@
sf->recode_loop = 1;
sf->subpel_search_method = SUBPEL_TREE;
sf->subpel_iters_per_step = 2;
+ sf->subpel_force_stop = 0;
sf->optimize_coefficients = !cpi->oxcf.lossless;
sf->reduce_first_step_size = 0;
sf->auto_mv_step_size = 0;
@@ -882,7 +884,7 @@
sf->use_one_partition_size_always = 0;
sf->less_rectangular_check = 0;
sf->use_square_partition_only = 0;
- sf->auto_min_max_partition_size = 0;
+ sf->auto_min_max_partition_size = NOT_IN_USE;
sf->max_partition_size = BLOCK_64X64;
sf->min_partition_size = BLOCK_4X4;
sf->adjust_partitioning_from_last_frame = 0;
@@ -902,23 +904,26 @@
sf->use_fast_coef_updates = 0;
sf->using_small_partition_info = 0;
sf->mode_skip_start = MAX_MODES; // Mode index at which mode skip mask set
+ sf->super_fast_rtc = 0;
- switch (mode) {
- case 0: // This is the best quality mode.
+ switch (cpi->oxcf.mode) {
+ case MODE_BESTQUALITY:
+ case MODE_SECONDPASS_BEST: // This is the best quality mode.
cpi->diamond_search_sad = vp9_full_range_search;
break;
- case 1:
+ case MODE_FIRSTPASS:
+ case MODE_GOODQUALITY:
+ case MODE_SECONDPASS:
set_good_speed_feature(cm, sf, speed);
break;
- break;
- case 2:
+ case MODE_REALTIME:
set_rt_speed_feature(cm, sf, speed);
break;
}; /* switch */
// Set rd thresholds based on mode and speed setting
- set_rd_speed_thresholds(cpi, mode);
- set_rd_speed_thresholds_sub8x8(cpi, mode);
+ set_rd_speed_thresholds(cpi);
+ set_rd_speed_thresholds_sub8x8(cpi);
// Slow quant, dct and trellis not worthwhile for first pass
// so make sure they are always turned off.
@@ -943,10 +948,6 @@
}
cpi->mb.optimize = cpi->sf.optimize_coefficients == 1 && cpi->pass != 1;
-
-#ifdef SPEEDSTATS
- frames_at_speed[cpi->speed]++;
-#endif
}
static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
@@ -1094,8 +1095,6 @@
cpi->oxcf.framerate = framerate;
cpi->output_framerate = cpi->oxcf.framerate;
- cpi->rc.per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth
- / cpi->output_framerate);
cpi->rc.av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth
/ cpi->output_framerate);
cpi->rc.min_frame_bandwidth = (int)(cpi->rc.av_per_frame_bandwidth *
@@ -1239,24 +1238,24 @@
// Real time and one pass deprecated in test code base
case MODE_GOODQUALITY:
cpi->pass = 0;
- cpi->compressor_speed = 2;
cpi->oxcf.cpu_used = clamp(cpi->oxcf.cpu_used, -5, 5);
break;
case MODE_FIRSTPASS:
cpi->pass = 1;
- cpi->compressor_speed = 1;
break;
case MODE_SECONDPASS:
cpi->pass = 2;
- cpi->compressor_speed = 1;
cpi->oxcf.cpu_used = clamp(cpi->oxcf.cpu_used, -5, 5);
break;
case MODE_SECONDPASS_BEST:
cpi->pass = 2;
- cpi->compressor_speed = 0;
+ break;
+
+ case MODE_REALTIME:
+ cpi->pass = 0;
break;
}
@@ -1334,8 +1333,6 @@
cm->interp_filter = DEFAULT_INTERP_FILTER;
- cpi->target_bandwidth = cpi->oxcf.target_bandwidth;
-
cm->display_width = cpi->oxcf.width;
cm->display_height = cpi->oxcf.height;
@@ -1954,21 +1951,6 @@
}
#endif
-#if defined(SECTIONBITS_OUTPUT)
-
- if (0) {
- int i;
- FILE *f = fopen("tokenbits.stt", "a");
-
- for (i = 0; i < 28; i++)
- fprintf(f, "%8d", (int)(Sectionbits[i] / 256));
-
- fprintf(f, "\n");
- fclose(f);
- }
-
-#endif
-
#if 0
{
printf("\n_pick_loop_filter_level:%d\n", cpi->time_pick_lpf / 1000);
@@ -2184,7 +2166,7 @@
if (index < 0 || index >= REF_FRAMES)
return -1;
- *fb = &cm->yv12_fb[cm->ref_frame_map[index]];
+ *fb = &cm->frame_bufs[cm->ref_frame_map[index]].buf;
return 0;
}
@@ -2476,9 +2458,9 @@
// At this point the new frame has been encoded.
// If any buffer copy / swapping is signaled it should be done here.
if (cm->frame_type == KEY_FRAME) {
- ref_cnt_fb(cm->fb_idx_ref_cnt,
+ ref_cnt_fb(cm->frame_bufs,
&cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
- ref_cnt_fb(cm->fb_idx_ref_cnt,
+ ref_cnt_fb(cm->frame_bufs,
&cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
}
#if CONFIG_MULTIPLE_ARF
@@ -2499,7 +2481,7 @@
*/
int tmp;
- ref_cnt_fb(cm->fb_idx_ref_cnt,
+ ref_cnt_fb(cm->frame_bufs,
&cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
tmp = cpi->alt_fb_idx;
@@ -2513,18 +2495,18 @@
arf_idx = cpi->arf_buffer_idx[cpi->sequence_number + 1];
}
#endif
- ref_cnt_fb(cm->fb_idx_ref_cnt,
+ ref_cnt_fb(cm->frame_bufs,
&cm->ref_frame_map[arf_idx], cm->new_fb_idx);
}
if (cpi->refresh_golden_frame) {
- ref_cnt_fb(cm->fb_idx_ref_cnt,
+ ref_cnt_fb(cm->frame_bufs,
&cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
}
}
if (cpi->refresh_last_frame) {
- ref_cnt_fb(cm->fb_idx_ref_cnt,
+ ref_cnt_fb(cm->frame_bufs,
&cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx);
}
}
@@ -2562,20 +2544,20 @@
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
- YV12_BUFFER_CONFIG *ref = &cm->yv12_fb[idx];
+ YV12_BUFFER_CONFIG *const ref = &cm->frame_bufs[idx].buf;
if (ref->y_crop_width != cm->width ||
ref->y_crop_height != cm->height) {
const int new_fb = get_free_fb(cm);
- vp9_realloc_frame_buffer(&cm->yv12_fb[new_fb],
+ vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS);
- scale_and_extend_frame(ref, &cm->yv12_fb[new_fb]);
+ scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf);
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
} else {
cpi->scaled_ref_idx[ref_frame - 1] = idx;
- cm->fb_idx_ref_cnt[idx]++;
+ cm->frame_bufs[idx].ref_count++;
}
}
}
@@ -2585,7 +2567,7 @@
int i;
for (i = 0; i < 3; i++)
- cm->fb_idx_ref_cnt[cpi->scaled_ref_idx[i]]--;
+ cm->frame_bufs[cpi->scaled_ref_idx[i]].ref_count--;
}
static void full_to_model_count(unsigned int *model_count,
@@ -2730,7 +2712,9 @@
if (cpi->sf.recode_loop != 0) {
vp9_save_coding_context(cpi);
cpi->dummy_packing = 1;
- vp9_pack_bitstream(cpi, dest, size);
+ if (!cpi->sf.super_fast_rtc)
+ vp9_pack_bitstream(cpi, dest, size);
+
cpi->rc.projected_frame_size = (*size) << 3;
vp9_restore_coding_context(cpi);
@@ -2953,15 +2937,6 @@
// Clear down mmx registers to allow floating point in what follows.
vp9_clear_system_state();
- // For an alt ref frame in 2 pass we skip the call to the second
- // pass function that sets the target bandwidth so we must set it here.
- if (cpi->refresh_alt_ref_frame) {
- // Set a per frame bit target for the alt ref frame.
- cpi->rc.per_frame_bandwidth = cpi->twopass.gf_bits;
- // Set a per second target bitrate.
- cpi->target_bandwidth = (int)(cpi->twopass.gf_bits * cpi->output_framerate);
- }
-
// Clear zbin over-quant value and mode boost values.
cpi->zbin_mode_boost = 0;
@@ -3037,10 +3012,7 @@
if (cpi->pass == 0 &&
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER &&
cm->frame_type != KEY_FRAME) {
- if (vp9_drop_frame(cpi)) {
- // Update buffer level with zero size, update frame counters, and return.
- vp9_update_buffer_level(cpi, 0);
- cm->last_frame_type = cm->frame_type;
+ if (vp9_rc_drop_frame(cpi)) {
vp9_rc_postencode_update_drop_frame(cpi);
cm->current_video_frame++;
return;
@@ -3080,19 +3052,27 @@
vp9_write_yuv_frame(cpi->Source);
#endif
- // Decide how big to make the frame.
- vp9_rc_pick_frame_size_target(cpi);
-
// Decide frame size bounds
vp9_rc_compute_frame_size_bounds(cpi, cpi->rc.this_frame_target,
&frame_under_shoot_limit,
&frame_over_shoot_limit);
- // Decide q and q bounds
+ // Decide q and q bounds.
q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
&bottom_index,
&top_index);
+ // JBB : This is realtime mode. In real time mode the first frame
+ // should be larger. Q of 0 is disabled because we force tx size to be
+ // 16x16...
+ if (cpi->sf.super_fast_rtc) {
+ if (cpi->common.current_video_frame == 0)
+ q /= 3;
+
+ if (q == 0)
+ q++;
+ }
+
if (!frame_is_intra_only(cm)) {
cm->interp_filter = DEFAULT_INTERP_FILTER;
/* TODO: Decide this more intelligently */
@@ -3172,10 +3152,6 @@
vp9_update_mode_context_stats(cpi);
#endif
- /* Move storing frame_type out of the above loop since it is also
- * needed in motion search besides loopfilter */
- cm->last_frame_type = cm->frame_type;
-
#if 0
output_frame_level_debug_stats(cpi);
#endif
@@ -3234,7 +3210,8 @@
cm->last_height = cm->height;
// reset to normal state now that we are done.
- cm->last_show_frame = cm->show_frame;
+ if (!cm->show_existing_frame)
+ cm->last_show_frame = cm->show_frame;
if (cm->show_frame) {
// current mip will be the prev_mip for the next frame
MODE_INFO *temp = cm->prev_mip;
@@ -3262,16 +3239,16 @@
static void SvcEncode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
unsigned int *frame_flags) {
- vp9_get_svc_params(cpi);
+ vp9_rc_get_svc_params(cpi);
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
}
static void Pass0Encode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
unsigned int *frame_flags) {
if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
- vp9_get_one_pass_cbr_params(cpi);
+ vp9_rc_get_one_pass_cbr_params(cpi);
} else {
- vp9_get_one_pass_params(cpi);
+ vp9_rc_get_one_pass_vbr_params(cpi);
}
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
}
@@ -3282,7 +3259,7 @@
(void) dest;
(void) frame_flags;
- vp9_get_first_pass_params(cpi);
+ vp9_rc_get_first_pass_params(cpi);
vp9_set_quantizer(cpi, find_fp_qindex());
vp9_first_pass(cpi);
}
@@ -3291,9 +3268,8 @@
uint8_t *dest, unsigned int *frame_flags) {
cpi->enable_encode_breakout = 1;
- vp9_get_second_pass_params(cpi);
+ vp9_rc_get_second_pass_params(cpi);
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
- // vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt");
vp9_twopass_postencode_update(cpi, *size);
}
@@ -3315,6 +3291,7 @@
YV12_BUFFER_CONFIG *sd, int64_t time_stamp,
int64_t end_time) {
VP9_COMP *cpi = (VP9_COMP *) ptr;
+ VP9_COMMON *cm = &cpi->common;
struct vpx_usec_timer timer;
int res = 0;
const int subsampling_x = sd->uv_width < sd->y_width;
@@ -3328,6 +3305,12 @@
vpx_usec_timer_mark(&timer);
cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
+ if (cm->version == 0 && (subsampling_x != 1 || subsampling_y != 1)) {
+ vpx_internal_error(&cm->error, VPX_CODEC_INVALID_PARAM,
+ "Non-4:2:0 color space requires profile >= 1");
+ res = -1;
+ }
+
return res;
}
@@ -3395,6 +3378,7 @@
int64_t *time_stamp, int64_t *time_end, int flush) {
VP9_COMP *cpi = (VP9_COMP *) ptr;
VP9_COMMON *cm = &cpi->common;
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
struct vpx_usec_timer cmptimer;
YV12_BUFFER_CONFIG *force_src_buffer = NULL;
MV_REFERENCE_FRAME ref_frame;
@@ -3442,8 +3426,7 @@
if (cpi->oxcf.arnr_max_frames > 0) {
// Produce the filtered ARF frame.
// TODO(agrange) merge these two functions.
- configure_arnr_filter(cpi, cm->current_video_frame + frames_to_arf,
- cpi->rc.gfu_boost);
+ vp9_configure_arnr_filter(cpi, frames_to_arf, cpi->rc.gfu_boost);
vp9_temporal_filter_prepare(cpi, frames_to_arf);
vp9_extend_frame_borders(&cpi->alt_ref_buffer,
cm->subsampling_x, cm->subsampling_y);
@@ -3459,7 +3442,9 @@
#if CONFIG_MULTIPLE_ARF
if (!cpi->multi_arf_enabled)
#endif
- cpi->rc.source_alt_ref_pending = 0; // Clear Pending altf Ref flag.
+ cpi->rc.source_alt_ref_pending = 0;
+ } else {
+ cpi->rc.source_alt_ref_pending = 0;
}
}
@@ -3541,7 +3526,7 @@
/* find a free buffer for the new frame, releasing the reference previously
* held.
*/
- cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+ cm->frame_bufs[cm->new_fb_idx].ref_count--;
cm->new_fb_idx = get_free_fb(cm);
#if CONFIG_MULTIPLE_ARF
@@ -3565,8 +3550,7 @@
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
- YV12_BUFFER_CONFIG *const buf = &cm->yv12_fb[idx];
-
+ YV12_BUFFER_CONFIG *const buf = &cm->frame_bufs[idx].buf;
RefBuffer *const ref_buf = &cm->frame_refs[ref_frame - 1];
ref_buf->buf = buf;
ref_buf->idx = idx;
@@ -3578,11 +3562,12 @@
vp9_extend_frame_borders(buf, cm->subsampling_x, cm->subsampling_y);
}
- vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm);
+ set_ref_ptrs(cm, xd, LAST_FRAME, LAST_FRAME);
+ xd->interp_kernel = vp9_get_interp_kernel(
+ DEFAULT_INTERP_FILTER == SWITCHABLE ? EIGHTTAP : DEFAULT_INTERP_FILTER);
- if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
- vp9_vaq_init();
- }
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ)
+ vp9_vaq_init();
if (cpi->use_svc) {
SvcEncode(cpi, size, dest, frame_flags);
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 9cf3f62..d0ca962 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -8,34 +8,36 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-
#ifndef VP9_ENCODER_VP9_ONYX_INT_H_
#define VP9_ENCODER_VP9_ONYX_INT_H_
#include <stdio.h>
+
#include "./vpx_config.h"
-#include "vp9/common/vp9_onyx.h"
-#include "vp9/encoder/vp9_treewriter.h"
-#include "vp9/encoder/vp9_tokenize.h"
-#include "vp9/common/vp9_onyxc_int.h"
-#include "vp9/encoder/vp9_variance.h"
-#include "vp9/encoder/vp9_encodemb.h"
-#include "vp9/encoder/vp9_quantize.h"
-#include "vp9/common/vp9_entropy.h"
-#include "vp9/common/vp9_entropymode.h"
#include "vpx_ports/mem.h"
#include "vpx/internal/vpx_codec_internal.h"
-#include "vp9/encoder/vp9_mcomp.h"
+
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_entropymode.h"
+#include "vp9/common/vp9_onyx.h"
+#include "vp9/common/vp9_onyxc_int.h"
+
+#include "vp9/encoder/vp9_encodemb.h"
#include "vp9/encoder/vp9_lookahead.h"
+#include "vp9/encoder/vp9_mbgraph.h"
+#include "vp9/encoder/vp9_mcomp.h"
+#include "vp9/encoder/vp9_quantize.h"
+#include "vp9/encoder/vp9_ratectrl.h"
+#include "vp9/encoder/vp9_tokenize.h"
+#include "vp9/encoder/vp9_treewriter.h"
+#include "vp9/encoder/vp9_variance.h"
#ifdef __cplusplus
extern "C" {
#endif
-#define DISABLE_RC_LONG_TERM_MEM 0
// #define MODE_TEST_HIT_STATS
-// #define SPEEDSTATS 1
#if CONFIG_MULTIPLE_ARF
// Set MIN_GF_INTERVAL to 1 for the full decomposition.
#define MIN_GF_INTERVAL 2
@@ -43,6 +45,7 @@
#define MIN_GF_INTERVAL 4
#endif
#define DEFAULT_GF_INTERVAL 7
+#define DEFAULT_KF_BOOST 2000
#define KEY_FRAME_CONTEXT 5
@@ -97,32 +100,6 @@
double count;
} FIRSTPASS_STATS;
-typedef struct {
- int frames_so_far;
- double frame_intra_error;
- double frame_coded_error;
- double frame_pcnt_inter;
- double frame_pcnt_motion;
- double frame_mvr;
- double frame_mvr_abs;
- double frame_mvc;
- double frame_mvc_abs;
-} ONEPASS_FRAMESTATS;
-
-typedef struct {
- struct {
- int err;
- union {
- int_mv mv;
- MB_PREDICTION_MODE mode;
- } m;
- } ref[MAX_REF_FRAMES];
-} MBGRAPH_MB_STATS;
-
-typedef struct {
- MBGRAPH_MB_STATS *mb_stats;
-} MBGRAPH_FRAME_STATS;
-
// This enumerator type needs to be kept aligned with the mode order in
// const MODE_DEFINITION vp9_mode_order[MAX_MODES] used in the rd code.
typedef enum {
@@ -190,6 +167,12 @@
} TX_SIZE_SEARCH_METHOD;
typedef enum {
+ NOT_IN_USE = 0,
+ RELAXED_NEIGHBORING_MIN_MAX = 1,
+ STRICT_NEIGHBORING_MIN_MAX = 2
+} AUTO_MIN_MAX_MODE;
+
+typedef enum {
// Values should be powers of 2 so that they can be selected as bits of
// an integer flags field
@@ -256,6 +239,9 @@
// Maximum number of steps in logarithmic subpel search before giving up.
int subpel_iters_per_step;
+ // Control when to stop subpel search
+ int subpel_force_stop;
+
// Thresh_mult is used to set a threshold for the rd score. A higher value
// means that we will accept the best mode so far more often. This number
// is used in combination with the current block size, and thresh_freq_fact
@@ -343,9 +329,8 @@
BLOCK_SIZE always_this_block_size;
// Sets min and max partition sizes for this 64x64 region based on the
- // same superblock in last encoded frame, and the left and above neighbor
- // in this block.
- int auto_min_max_partition_size;
+ // same 64x64 in last encoded frame, and the left and above neighbor.
+ AUTO_MIN_MAX_MODE auto_min_max_partition_size;
// Min and max partition size we enable (block_size) as per auto
// min max, but also used by adjust partitioning, and pick_partitioning.
@@ -417,69 +402,11 @@
// This feature limits the number of coefficients updates we actually do
// by only looking at counts from 1/2 the bands.
int use_fast_coef_updates; // 0: 2-loop, 1: 1-loop, 2: 1-loop reduced
+
+ // This flag control the use of the new super fast rtc mode
+ int super_fast_rtc;
} SPEED_FEATURES;
-typedef struct {
- // Rate targetting variables
- int this_frame_target;
- int projected_frame_size;
- int sb64_target_rate;
- int last_q[3]; // Separate values for Intra/Inter/ARF-GF
- int last_boosted_qindex; // Last boosted GF/KF/ARF q
-
- int gfu_boost;
- int last_boost;
- int kf_boost;
-
- double rate_correction_factor;
- double key_frame_rate_correction_factor;
- double gf_rate_correction_factor;
-
- unsigned int frames_since_golden;
- unsigned int frames_till_gf_update_due; // Count down till next GF
- unsigned int max_gf_interval;
- unsigned int baseline_gf_interval;
- unsigned int frames_to_key;
- unsigned int frames_since_key;
- unsigned int this_key_frame_forced;
- unsigned int next_key_frame_forced;
- unsigned int source_alt_ref_pending;
- unsigned int source_alt_ref_active;
- unsigned int is_src_frame_alt_ref;
-
- int per_frame_bandwidth; // Current section per frame bandwidth target
- int av_per_frame_bandwidth; // Average frame size target for clip
- int min_frame_bandwidth; // Minimum allocation used for any frame
- int max_frame_bandwidth; // Maximum burst rate allowed for a frame.
-
- int ni_av_qi;
- int ni_tot_qi;
- int ni_frames;
- int avg_frame_qindex[3]; // 0 - KEY, 1 - INTER, 2 - ARF/GF
- double tot_q;
- double avg_q;
-
- int buffer_level;
- int bits_off_target;
-
- int decimation_factor;
- int decimation_count;
-
- int rolling_target_bits;
- int rolling_actual_bits;
-
- int long_rolling_target_bits;
- int long_rolling_actual_bits;
-
- int64_t total_actual_bits;
- int total_target_vs_actual; // debug stats
-
- int worst_quality;
- int active_worst_quality;
- int best_quality;
- // int active_best_quality;
-} RATE_CONTROL;
-
typedef struct VP9_COMP {
DECLARE_ALIGNED(16, int16_t, y_quant[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, y_quant_shift[QINDEX_RANGE][8]);
@@ -501,7 +428,6 @@
MACROBLOCK mb;
VP9_COMMON common;
VP9_CONFIG oxcf;
- struct rdcost_block_args rdcost_stack;
struct lookahead_ctx *lookahead;
struct lookahead_entry *source;
#if CONFIG_MULTIPLE_ARF
@@ -603,14 +529,8 @@
vp9_coeff_probs_model frame_coef_probs[TX_SIZES][PLANE_TYPES];
vp9_coeff_stats frame_branch_ct[TX_SIZES][PLANE_TYPES];
- int64_t target_bandwidth;
struct vpx_codec_pkt_list *output_pkt_list;
-#if 0
- // Experimental code for lagged and one pass
- ONEPASS_FRAMESTATS one_pass_frame_stats[MAX_LAG_BUFFERS];
- int one_pass_frame_index;
-#endif
MBGRAPH_FRAME_STATS mbgraph_stats[MAX_LAG_BUFFERS];
int mbgraph_n_frames; // number of frames filled in the above
int static_mb_pct; // % forced skip mbs by segmentation
@@ -618,12 +538,11 @@
// for real time encoding
int speed;
- int compressor_speed;
int cpu_used;
int pass;
- vp9_prob last_skip_false_probs[3][MBSKIP_CONTEXTS];
+ vp9_prob last_skip_false_probs[3][SKIP_CONTEXTS];
int last_skip_probs_q[3];
int ref_frame_flags;
@@ -799,7 +718,8 @@
static YV12_BUFFER_CONFIG *get_ref_frame_buffer(VP9_COMP *cpi,
MV_REFERENCE_FRAME ref_frame) {
VP9_COMMON *const cm = &cpi->common;
- return &cm->yv12_fb[cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]];
+ return &cm->frame_bufs[cm->ref_frame_map[get_ref_frame_idx(cpi,
+ ref_frame)]].buf;
}
void vp9_encode_frame(VP9_COMP *cpi);
@@ -821,6 +741,14 @@
return mb_rows * mb_cols * (48 * 16 + 4);
}
+static void set_ref_ptrs(VP9_COMMON *cm, MACROBLOCKD *xd,
+ MV_REFERENCE_FRAME ref0, MV_REFERENCE_FRAME ref1) {
+ xd->block_refs[0] = &cm->frame_refs[ref0 >= LAST_FRAME ? ref0 - LAST_FRAME
+ : 0];
+ xd->block_refs[1] = &cm->frame_refs[ref1 >= LAST_FRAME ? ref1 - LAST_FRAME
+ : 0];
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/encoder/vp9_picklpf.c b/vp9/encoder/vp9_picklpf.c
index 0c0a20f..5b0ecf7 100644
--- a/vp9/encoder/vp9_picklpf.c
+++ b/vp9/encoder/vp9_picklpf.c
@@ -36,11 +36,11 @@
static int try_filter_frame(const YV12_BUFFER_CONFIG *sd, VP9_COMP *const cpi,
MACROBLOCKD *const xd, VP9_COMMON *const cm,
- int filt_level, int partial) {
+ int filt_level, int partial_frame) {
int filt_err;
vp9_set_alt_lf_level(cpi, filt_level);
- vp9_loop_filter_frame(cm, xd, filt_level, 1, partial);
+ vp9_loop_filter_frame(cm, xd, filt_level, 1, partial_frame);
filt_err = vp9_calc_ss_err(sd, cm->frame_to_show);
@@ -51,7 +51,7 @@
}
static void search_filter_level(const YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi,
- int partial) {
+ int partial_frame) {
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
VP9_COMMON *const cm = &cpi->common;
struct loopfilter *const lf = &cm->lf;
@@ -73,7 +73,7 @@
// Make a copy of the unfiltered / processed recon buffer
vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
- best_err = try_filter_frame(sd, cpi, xd, cm, filt_mid, partial);
+ best_err = try_filter_frame(sd, cpi, xd, cm, filt_mid, partial_frame);
filt_best = filt_mid;
ss_err[filt_mid] = best_err;
@@ -95,7 +95,7 @@
if (filt_direction <= 0 && filt_low != filt_mid) {
// Get Low filter error score
if (ss_err[filt_low] < 0) {
- filt_err = try_filter_frame(sd, cpi, xd, cm, filt_low, partial);
+ filt_err = try_filter_frame(sd, cpi, xd, cm, filt_low, partial_frame);
ss_err[filt_low] = filt_err;
} else {
filt_err = ss_err[filt_low];
@@ -114,7 +114,7 @@
// Now look at filt_high
if (filt_direction >= 0 && filt_high != filt_mid) {
if (ss_err[filt_high] < 0) {
- filt_err = try_filter_frame(sd, cpi, xd, cm, filt_high, partial);
+ filt_err = try_filter_frame(sd, cpi, xd, cm, filt_high, partial_frame);
ss_err[filt_high] = filt_err;
} else {
filt_err = ss_err[filt_high];
diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c
index 210d15f..1aaa416 100644
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -80,7 +80,7 @@
step_param = 6;
further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
- for (i = LAST_FRAME; i <= ALTREF_FRAME && cpi->common.show_frame; ++i) {
+ for (i = LAST_FRAME; i <= LAST_FRAME && cpi->common.show_frame; ++i) {
if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
tmp_mv->as_int = INVALID_MV;
@@ -124,8 +124,8 @@
stride, 0x7fffffff);
// scale to 1/8 pixel resolution
- tmp_mv->as_mv.row = tmp_mv->as_mv.row << 3;
- tmp_mv->as_mv.col = tmp_mv->as_mv.col << 3;
+ tmp_mv->as_mv.row = tmp_mv->as_mv.row * 8;
+ tmp_mv->as_mv.col = tmp_mv->as_mv.col * 8;
// calculate the bit cost on motion vector
*rate_mv = vp9_mv_bit_cost(&tmp_mv->as_mv, &ref_mv.as_mv,
@@ -142,8 +142,7 @@
int mi_row, int mi_col,
int *returnrate,
int64_t *returndistortion,
- BLOCK_SIZE bsize,
- PICK_MODE_CONTEXT *ctx) {
+ BLOCK_SIZE bsize) {
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
const BLOCK_SIZE block_size = get_plane_block_size(bsize, &xd->plane[0]);
@@ -155,6 +154,7 @@
VP9_ALT_FLAG };
int64_t best_rd = INT64_MAX;
int64_t this_rd;
+ int64_t cost[4]= { 0, 100, 150, 205 };
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
@@ -171,7 +171,7 @@
mbmi->tx_size = MIN(max_txsize_lookup[bsize],
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
- for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+ for (ref_frame = LAST_FRAME; ref_frame <= LAST_FRAME ; ++ref_frame) {
x->pred_mv_sad[ref_frame] = INT_MAX;
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
vp9_setup_buffer_inter(cpi, x, tile,
@@ -182,7 +182,7 @@
frame_mv[ZEROMV][ref_frame].as_int = 0;
}
- for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+ for (ref_frame = LAST_FRAME; ref_frame <= LAST_FRAME ; ++ref_frame) {
int rate_mv = 0;
if (!(cpi->ref_frame_flags & flag_list[ref_frame]))
@@ -191,29 +191,43 @@
// Select prediction reference frames.
xd->plane[0].pre[0] = yv12_mb[ref_frame][0];
-
- x->mode_sad[ref_frame][INTER_OFFSET(NEWMV)] =
- full_pixel_motion_search(cpi, x, tile, bsize, mi_row, mi_col,
- &frame_mv[NEWMV][ref_frame], &rate_mv);
-
- if (frame_mv[NEWMV][ref_frame].as_int == INVALID_MV)
- continue;
-
clamp_mv2(&frame_mv[NEARESTMV][ref_frame].as_mv, xd);
clamp_mv2(&frame_mv[NEARMV][ref_frame].as_mv, xd);
for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
- int rate = x->inter_mode_cost[mbmi->mode_context[ref_frame]]
- [INTER_OFFSET(this_mode)];
- int64_t dist = x->mode_sad[ref_frame][INTER_OFFSET(this_mode)] *
- x->mode_sad[ref_frame][INTER_OFFSET(this_mode)];
- this_rd = RDCOST(x->rdmult, x->rddiv, rate, dist);
+ int rate = cost[this_mode - NEARESTMV];
+ int64_t dist;
+
+ if (this_mode == NEWMV) {
+ if (this_rd < 300)
+ continue;
+
+ x->mode_sad[ref_frame][INTER_OFFSET(NEWMV)] =
+ full_pixel_motion_search(cpi, x, tile, bsize, mi_row, mi_col,
+ &frame_mv[NEWMV][ref_frame], &rate_mv);
+
+ if (frame_mv[NEWMV][ref_frame].as_int == INVALID_MV)
+ continue;
+ }
+
+ dist = x->mode_sad[ref_frame][INTER_OFFSET(this_mode)];
+ this_rd = rate + dist;
if (this_rd < best_rd) {
best_rd = this_rd;
mbmi->mode = this_mode;
mbmi->ref_frame[0] = ref_frame;
mbmi->mv[0].as_int = frame_mv[this_mode][ref_frame].as_int;
+ xd->mi_8x8[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
+ mbmi->interp_filter = cpi->common.interp_filter == SWITCHABLE ?
+ EIGHTTAP : cpi->common.interp_filter;
+
+ mbmi->ref_frame[1] = INTRA_FRAME;
+ mbmi->tx_size = max_txsize_lookup[bsize];
+ mbmi->uv_mode = this_mode;
+ mbmi->skip_coeff = 0;
+ mbmi->sb_type = bsize;
+ mbmi->segment_id = 0;
}
}
}
@@ -223,8 +237,5 @@
// TODO(jingning) intra prediction search, if the best SAD is above a certain
// threshold.
- // store mode decisions
- ctx->mic = *xd->mi_8x8[0];
-
return INT64_MAX;
}
diff --git a/vp9/encoder/vp9_pickmode.h b/vp9/encoder/vp9_pickmode.h
index 82904ae..05ff187 100644
--- a/vp9/encoder/vp9_pickmode.h
+++ b/vp9/encoder/vp9_pickmode.h
@@ -22,8 +22,7 @@
int mi_row, int mi_col,
int *returnrate,
int64_t *returndistortion,
- BLOCK_SIZE bsize,
- PICK_MODE_CONTEXT *ctx);
+ BLOCK_SIZE bsize);
#ifdef __cplusplus
} // extern "C"
diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c
index 8c41724..a2eea1c 100644
--- a/vp9/encoder/vp9_quantize.c
+++ b/vp9/encoder/vp9_quantize.c
@@ -18,10 +18,6 @@
#include "vp9/common/vp9_seg_common.h"
-#ifdef ENC_DEBUG
-extern int enc_debug;
-#endif
-
void vp9_quantize_b_c(const int16_t *coeff_ptr, intptr_t count,
int skip_block,
const int16_t *zbin_ptr, const int16_t *round_ptr,
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index a5911be..abbf39b 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -209,51 +209,40 @@
: (bpm * mbs) >> BPER_MB_NORMBITS;
}
-
-static void calc_iframe_target_size(VP9_COMP *cpi) {
- const VP9_CONFIG *oxcf = &cpi->oxcf;
- RATE_CONTROL *const rc = &cpi->rc;
- int target;
-
- vp9_clear_system_state(); // __asm emms;
-
- // For 1-pass.
- if (cpi->pass == 0) {
- if (cpi->common.current_video_frame == 0) {
- target = oxcf->starting_buffer_level / 2;
- } else {
- // TODO(marpan): Add in adjustment based on Q.
- // If this keyframe was forced, use a more recent Q estimate.
- // int Q = (cpi->common.frame_flags & FRAMEFLAGS_KEY) ?
- // cpi->rc.avg_frame_qindex : cpi->rc.ni_av_qi;
- int initial_boost = 32;
- // Boost depends somewhat on frame rate.
- int kf_boost = MAX(initial_boost, (int)(2 * cpi->output_framerate - 16));
- // Adjustment up based on q: need to fix.
- // kf_boost = kf_boost * kfboost_qadjust(Q) / 100;
- // Frame separation adjustment (down).
- if (rc->frames_since_key < cpi->output_framerate / 2) {
- kf_boost = (int)(kf_boost * rc->frames_since_key /
- (cpi->output_framerate / 2));
- }
- kf_boost = (kf_boost < 16) ? 16 : kf_boost;
- target = ((16 + kf_boost) * rc->per_frame_bandwidth) >> 4;
- }
- rc->active_worst_quality = rc->worst_quality;
- } else {
- target = rc->per_frame_bandwidth;
+int vp9_rc_clamp_pframe_target_size(const VP9_COMP *const cpi, int target) {
+ const RATE_CONTROL *rc = &cpi->rc;
+ const int min_frame_target = MAX(rc->min_frame_bandwidth,
+ rc->av_per_frame_bandwidth >> 5);
+ if (target < min_frame_target)
+ target = min_frame_target;
+ if (cpi->refresh_golden_frame && rc->source_alt_ref_active) {
+ // If there is an active ARF at this location use the minimum
+ // bits on this frame even if it is a constructed arf.
+ // The active maximum quantizer insures that an appropriate
+ // number of bits will be spent if needed for constructed ARFs.
+ target = 0;
}
+ // Clip the frame target to the maximum allowed value.
+ if (target > rc->max_frame_bandwidth)
+ target = rc->max_frame_bandwidth;
+ return target;
+}
+int vp9_rc_clamp_iframe_target_size(const VP9_COMP *const cpi, int target) {
+ const RATE_CONTROL *rc = &cpi->rc;
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
if (oxcf->rc_max_intra_bitrate_pct) {
- const int max_rate = rc->per_frame_bandwidth *
- oxcf->rc_max_intra_bitrate_pct / 100;
+ const int max_rate = rc->av_per_frame_bandwidth *
+ oxcf->rc_max_intra_bitrate_pct / 100;
target = MIN(target, max_rate);
}
- rc->this_frame_target = target;
+ if (target > rc->max_frame_bandwidth)
+ target = rc->max_frame_bandwidth;
+ return target;
}
// Update the buffer level: leaky bucket model.
-void vp9_update_buffer_level(VP9_COMP *const cpi, int encoded_frame_size) {
+static void update_buffer_level(VP9_COMP *cpi, int encoded_frame_size) {
const VP9_COMMON *const cm = &cpi->common;
const VP9_CONFIG *oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
@@ -269,7 +258,7 @@
rc->buffer_level = MIN(rc->bits_off_target, oxcf->maximum_buffer_size);
}
-int vp9_drop_frame(VP9_COMP *const cpi) {
+int vp9_rc_drop_frame(VP9_COMP *cpi) {
const VP9_CONFIG *oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
@@ -308,124 +297,6 @@
}
}
-// Adjust active_worst_quality level based on buffer level.
-static int adjust_active_worst_quality_from_buffer_level(const VP9_CONFIG *oxcf,
- const RATE_CONTROL *rc) {
- // Adjust active_worst_quality: If buffer is above the optimal/target level,
- // bring active_worst_quality down depending on fullness over buffer.
- // If buffer is below the optimal level, let the active_worst_quality go from
- // ambient Q (at buffer = optimal level) to worst_quality level
- // (at buffer = critical level).
-
- int active_worst_quality = rc->active_worst_quality;
- // Maximum limit for down adjustment, ~20%.
- int max_adjustment_down = active_worst_quality / 5;
- // Buffer level below which we push active_worst to worst_quality.
- int critical_level = oxcf->optimal_buffer_level >> 2;
- int adjustment = 0;
- int buff_lvl_step = 0;
- if (rc->buffer_level > oxcf->optimal_buffer_level) {
- // Adjust down.
- if (max_adjustment_down) {
- buff_lvl_step = (int)((oxcf->maximum_buffer_size -
- oxcf->optimal_buffer_level) / max_adjustment_down);
- if (buff_lvl_step)
- adjustment = (int)((rc->buffer_level - oxcf->optimal_buffer_level) /
- buff_lvl_step);
- active_worst_quality -= adjustment;
- }
- } else if (rc->buffer_level > critical_level) {
- // Adjust up from ambient Q.
- if (critical_level) {
- buff_lvl_step = (oxcf->optimal_buffer_level - critical_level);
- if (buff_lvl_step) {
- adjustment = (rc->worst_quality - rc->avg_frame_qindex[INTER_FRAME]) *
- (oxcf->optimal_buffer_level - rc->buffer_level) /
- buff_lvl_step;
- }
- active_worst_quality = rc->avg_frame_qindex[INTER_FRAME] + adjustment;
- }
- } else {
- // Set to worst_quality if buffer is below critical level.
- active_worst_quality = rc->worst_quality;
- }
- return active_worst_quality;
-}
-
-// Adjust target frame size with respect to the buffering constraints:
-static int target_size_from_buffer_level(const VP9_CONFIG *oxcf,
- const RATE_CONTROL *rc) {
- int target = rc->this_frame_target;
- const int64_t diff = oxcf->optimal_buffer_level - rc->buffer_level;
- const int one_pct_bits = 1 + oxcf->optimal_buffer_level / 100;
-
- if (diff > 0) {
- // Lower the target bandwidth for this frame.
- const int pct_low = MIN(diff / one_pct_bits, oxcf->under_shoot_pct);
- target -= (target * pct_low) / 200;
- } else if (diff < 0) {
- // Increase the target bandwidth for this frame.
- const int pct_high = MIN(-diff / one_pct_bits, oxcf->over_shoot_pct);
- target += (target * pct_high) / 200;
- }
-
- return target;
-}
-
-static void calc_pframe_target_size(VP9_COMP *const cpi) {
- RATE_CONTROL *const rc = &cpi->rc;
- const VP9_CONFIG *const oxcf = &cpi->oxcf;
- int min_frame_target = MAX(rc->min_frame_bandwidth,
- rc->av_per_frame_bandwidth >> 5);
- if (cpi->refresh_alt_ref_frame) {
- // Special alt reference frame case
- // Per frame bit target for the alt ref frame
- rc->per_frame_bandwidth = cpi->twopass.gf_bits;
- rc->this_frame_target = rc->per_frame_bandwidth;
- } else {
- // Normal frames (gf and inter).
- rc->this_frame_target = rc->per_frame_bandwidth;
- // Set target frame size based on buffer level, for 1 pass CBR.
- if (cpi->pass == 0 && oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
- // Need to decide how low min_frame_target should be for 1-pass CBR.
- // For now, use: cpi->rc.av_per_frame_bandwidth / 16:
- min_frame_target = MAX(rc->av_per_frame_bandwidth >> 4,
- FRAME_OVERHEAD_BITS);
- rc->this_frame_target = target_size_from_buffer_level(oxcf, rc);
- // Adjust qp-max based on buffer level.
- rc->active_worst_quality =
- adjust_active_worst_quality_from_buffer_level(oxcf, rc);
- }
- }
-
- // Check that the total sum of adjustments is not above the maximum allowed.
- // That is, having allowed for the KF and GF penalties, we have not pushed
- // the current inter-frame target too low. If the adjustment we apply here is
- // not capable of recovering all the extra bits we have spent in the KF or GF,
- // then the remainder will have to be recovered over a longer time span via
- // other buffer / rate control mechanisms.
- if (rc->this_frame_target < min_frame_target)
- rc->this_frame_target = min_frame_target;
-
- // Adjust target frame size for Golden Frames:
- if (cpi->refresh_golden_frame) {
- // If we are using alternate ref instead of gf then do not apply the boost
- // It will instead be applied to the altref update
- // Jims modified boost
- if (!rc->source_alt_ref_active) {
- // The spend on the GF is defined in the two pass code
- // for two pass encodes
- rc->this_frame_target = rc->per_frame_bandwidth;
- } else {
- // If there is an active ARF at this location use the minimum
- // bits on this frame even if it is a constructed arf.
- // The active maximum quantizer insures that an appropriate
- // number of bits will be spent if needed for constructed ARFs.
- rc->this_frame_target = 0;
- }
- }
-}
-
static double get_rate_correction_factor(const VP9_COMP *cpi) {
if (cpi->common.frame_type == KEY_FRAME) {
return cpi->rc.key_frame_rate_correction_factor;
@@ -465,7 +336,6 @@
projected_size_based_on_q = estimate_bits_at_q(cpi->common.frame_type, q,
cpi->common.MBs,
rate_correction_factor);
-
// Work out a size correction factor.
if (projected_size_based_on_q > 0)
correction_factor = (100 * cpi->rc.projected_frame_size) /
@@ -564,8 +434,9 @@
}
}
-int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
- int *bottom_index, int *top_index) {
+static int rc_pick_q_and_adjust_q_bounds_one_pass(const VP9_COMP *cpi,
+ int *bottom_index,
+ int *top_index) {
const VP9_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
const VP9_CONFIG *const oxcf = &cpi->oxcf;
@@ -585,7 +456,7 @@
int delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
(last_boosted_q * 0.75));
active_best_quality = MAX(qindex + delta_qindex, rc->best_quality);
- } else if (!(cpi->pass == 0 && cm->current_video_frame == 0)) {
+ } else if (cm->current_video_frame > 0) {
// not first frame of one pass and kf_boost is set
double q_adj_factor = 1.0;
double q_val;
@@ -602,9 +473,6 @@
q_adj_factor -= 0.25;
}
- // Make a further adjustment based on the kf zero motion measure.
- q_adj_factor += 0.05 - (0.001 * (double)cpi->twopass.kf_zeromotion_pct);
-
// Convert the adjustment factor to a qindex delta
// on active_best_quality.
q_val = vp9_convert_qindex_to_q(active_best_quality);
@@ -620,7 +488,6 @@
#endif
} else if (!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
-
// Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
@@ -671,14 +538,7 @@
if (oxcf->end_usage == USAGE_CONSTANT_QUALITY) {
active_best_quality = cpi->cq_target_quality;
} else {
- if (cpi->pass == 0 &&
- rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality)
- // 1-pass: for now, use the average Q for the active_best, if its lower
- // than active_worst.
- active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
- else
- active_best_quality = inter_minq[active_worst_quality];
-
+ active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
// For the constrained quality mode we don't want
// q to fall below the cq level.
if ((oxcf->end_usage == USAGE_CONSTRAINED_QUALITY) &&
@@ -706,7 +566,7 @@
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
// Limit Q range for the adaptive loop.
if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
- if (!(cpi->pass == 0 && cm->current_video_frame == 0))
+ if (!(cm->current_video_frame == 0))
*top_index = (active_worst_quality + active_best_quality * 3) / 4;
} else if (!rc->is_src_frame_alt_ref &&
(oxcf->end_usage != USAGE_STREAM_FROM_SERVER) &&
@@ -756,6 +616,208 @@
return q;
}
+static int rc_pick_q_and_adjust_q_bounds_two_pass(const VP9_COMP *cpi,
+ int *bottom_index,
+ int *top_index) {
+ const VP9_COMMON *const cm = &cpi->common;
+ const RATE_CONTROL *const rc = &cpi->rc;
+ const VP9_CONFIG *const oxcf = &cpi->oxcf;
+ int active_best_quality;
+ int active_worst_quality = rc->active_worst_quality;
+ int q;
+
+ if (frame_is_intra_only(cm)) {
+ active_best_quality = rc->best_quality;
+#if !CONFIG_MULTIPLE_ARF
+ // Handle the special case for key frames forced when we have75 reached
+ // the maximum key frame interval. Here force the Q to a range
+ // based on the ambient Q to reduce the risk of popping.
+ if (rc->this_key_frame_forced) {
+ int qindex = rc->last_boosted_qindex;
+ double last_boosted_q = vp9_convert_qindex_to_q(qindex);
+ int delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
+ (last_boosted_q * 0.75));
+ active_best_quality = MAX(qindex + delta_qindex, rc->best_quality);
+ } else {
+ // Not forced keyframe.
+ double q_adj_factor = 1.0;
+ double q_val;
+ // Baseline value derived from cpi->active_worst_quality and kf boost.
+ active_best_quality = get_active_quality(active_worst_quality,
+ rc->kf_boost,
+ kf_low, kf_high,
+ kf_low_motion_minq,
+ kf_high_motion_minq);
+
+ // Allow somewhat lower kf minq with small image formats.
+ if ((cm->width * cm->height) <= (352 * 288)) {
+ q_adj_factor -= 0.25;
+ }
+
+ // Make a further adjustment based on the kf zero motion measure.
+ q_adj_factor += 0.05 - (0.001 * (double)cpi->twopass.kf_zeromotion_pct);
+
+ // Convert the adjustment factor to a qindex delta
+ // on active_best_quality.
+ q_val = vp9_convert_qindex_to_q(active_best_quality);
+ active_best_quality += vp9_compute_qdelta(cpi, q_val, q_val *
+ q_adj_factor);
+ }
+#else
+ double current_q;
+ // Force the KF quantizer to be 30% of the active_worst_quality.
+ current_q = vp9_convert_qindex_to_q(active_worst_quality);
+ active_best_quality = active_worst_quality
+ + vp9_compute_qdelta(cpi, current_q, current_q * 0.3);
+#endif
+ } else if (!rc->is_src_frame_alt_ref &&
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ // Use the lower of active_worst_quality and recent
+ // average Q as basis for GF/ARF best Q limit unless last frame was
+ // a key frame.
+ if (rc->frames_since_key > 1 &&
+ rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
+ q = rc->avg_frame_qindex[INTER_FRAME];
+ } else {
+ q = active_worst_quality;
+ }
+ // For constrained quality dont allow Q less than the cq level
+ if (oxcf->end_usage == USAGE_CONSTRAINED_QUALITY) {
+ if (q < cpi->cq_target_quality)
+ q = cpi->cq_target_quality;
+ if (rc->frames_since_key > 1) {
+ active_best_quality = get_active_quality(q, rc->gfu_boost,
+ gf_low, gf_high,
+ afq_low_motion_minq,
+ afq_high_motion_minq);
+ } else {
+ active_best_quality = get_active_quality(q, rc->gfu_boost,
+ gf_low, gf_high,
+ gf_low_motion_minq,
+ gf_high_motion_minq);
+ }
+ // Constrained quality use slightly lower active best.
+ active_best_quality = active_best_quality * 15 / 16;
+
+ } else if (oxcf->end_usage == USAGE_CONSTANT_QUALITY) {
+ if (!cpi->refresh_alt_ref_frame) {
+ active_best_quality = cpi->cq_target_quality;
+ } else {
+ if (rc->frames_since_key > 1) {
+ active_best_quality = get_active_quality(
+ q, rc->gfu_boost, gf_low, gf_high,
+ afq_low_motion_minq, afq_high_motion_minq);
+ } else {
+ active_best_quality = get_active_quality(
+ q, rc->gfu_boost, gf_low, gf_high,
+ gf_low_motion_minq, gf_high_motion_minq);
+ }
+ }
+ } else {
+ active_best_quality = get_active_quality(
+ q, rc->gfu_boost, gf_low, gf_high,
+ gf_low_motion_minq, gf_high_motion_minq);
+ }
+ } else {
+ if (oxcf->end_usage == USAGE_CONSTANT_QUALITY) {
+ active_best_quality = cpi->cq_target_quality;
+ } else {
+ active_best_quality = inter_minq[active_worst_quality];
+
+ // For the constrained quality mode we don't want
+ // q to fall below the cq level.
+ if ((oxcf->end_usage == USAGE_CONSTRAINED_QUALITY) &&
+ (active_best_quality < cpi->cq_target_quality)) {
+ // If we are strongly undershooting the target rate in the last
+ // frames then use the user passed in cq value not the auto
+ // cq value.
+ if (rc->rolling_actual_bits < rc->min_frame_bandwidth)
+ active_best_quality = oxcf->cq_level;
+ else
+ active_best_quality = cpi->cq_target_quality;
+ }
+ }
+ }
+
+ // Clip the active best and worst quality values to limits.
+ if (active_worst_quality > rc->worst_quality)
+ active_worst_quality = rc->worst_quality;
+
+ if (active_best_quality < rc->best_quality)
+ active_best_quality = rc->best_quality;
+
+ if (active_best_quality > rc->worst_quality)
+ active_best_quality = rc->worst_quality;
+
+ if (active_worst_quality < active_best_quality)
+ active_worst_quality = active_best_quality;
+
+ *top_index = active_worst_quality;
+ *bottom_index = active_best_quality;
+
+#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
+ // Limit Q range for the adaptive loop.
+ if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
+ *top_index = (active_worst_quality + active_best_quality * 3) / 4;
+ } else if (!rc->is_src_frame_alt_ref &&
+ (oxcf->end_usage != USAGE_STREAM_FROM_SERVER) &&
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ *top_index = (active_worst_quality + active_best_quality) / 2;
+ }
+#endif
+
+ if (oxcf->end_usage == USAGE_CONSTANT_QUALITY) {
+ q = active_best_quality;
+ // Special case code to try and match quality with forced key frames.
+ } else if ((cm->frame_type == KEY_FRAME) && rc->this_key_frame_forced) {
+ q = rc->last_boosted_qindex;
+ } else {
+ q = vp9_rc_regulate_q(cpi, rc->this_frame_target,
+ active_best_quality, active_worst_quality);
+ if (q > *top_index) {
+ // Special case when we are targeting the max allowed rate.
+ if (cpi->rc.this_frame_target >= cpi->rc.max_frame_bandwidth)
+ *top_index = q;
+ else
+ q = *top_index;
+ }
+ }
+#if CONFIG_MULTIPLE_ARF
+ // Force the quantizer determined by the coding order pattern.
+ if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
+ cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
+ double new_q;
+ double current_q = vp9_convert_qindex_to_q(active_worst_quality);
+ int level = cpi->this_frame_weight;
+ assert(level >= 0);
+ new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
+ q = active_worst_quality +
+ vp9_compute_qdelta(cpi, current_q, new_q);
+
+ *bottom_index = q;
+ *top_index = q;
+ printf("frame:%d q:%d\n", cm->current_video_frame, q);
+ }
+#endif
+ assert(*top_index <= rc->worst_quality &&
+ *top_index >= rc->best_quality);
+ assert(*bottom_index <= rc->worst_quality &&
+ *bottom_index >= rc->best_quality);
+ assert(q <= rc->worst_quality && q >= rc->best_quality);
+ return q;
+}
+
+int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
+ int *bottom_index,
+ int *top_index) {
+ if (cpi->pass == 0)
+ return rc_pick_q_and_adjust_q_bounds_one_pass(
+ cpi, bottom_index, top_index);
+ else
+ return rc_pick_q_and_adjust_q_bounds_two_pass(
+ cpi, bottom_index, top_index);
+}
+
void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
int this_frame_target,
int *frame_under_shoot_limit,
@@ -799,24 +861,14 @@
}
}
-// return of 0 means drop frame
-int vp9_rc_pick_frame_size_target(VP9_COMP *cpi) {
+void vp9_rc_set_frame_target(VP9_COMP *cpi, int target) {
const VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
- if (cm->frame_type == KEY_FRAME)
- calc_iframe_target_size(cpi);
- else
- calc_pframe_target_size(cpi);
-
- // Clip the frame target to the maximum allowed value.
- if (rc->this_frame_target > rc->max_frame_bandwidth)
- rc->this_frame_target = rc->max_frame_bandwidth;
-
+ rc->this_frame_target = target;
// Target rate per SB64 (including partial SB64s.
rc->sb64_target_rate = ((int64_t)rc->this_frame_target * 64 * 64) /
(cm->width * cm->height);
- return 1;
}
static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
@@ -860,6 +912,8 @@
void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
+
+ cm->last_frame_type = cm->frame_type;
// Update rate control heuristics
rc->projected_frame_size = (bytes_used << 3);
@@ -902,7 +956,7 @@
rc->last_boosted_qindex = cm->base_qindex;
}
- vp9_update_buffer_level(cpi, rc->projected_frame_size);
+ update_buffer_level(cpi, rc->projected_frame_size);
// Rolling monitors of whether we are over or underspending used to help
// regulate min and Max Q in two pass.
@@ -924,22 +978,6 @@
rc->total_target_vs_actual += (rc->this_frame_target -
rc->projected_frame_size);
-#ifndef DISABLE_RC_LONG_TERM_MEM
- // Update bits left to the kf and gf groups to account for overshoot or
- // undershoot on these frames
- if (cm->frame_type == KEY_FRAME) {
- cpi->twopass.kf_group_bits += cpi->rc.this_frame_target -
- cpi->rc.projected_frame_size;
-
- cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0);
- } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) {
- cpi->twopass.gf_group_bits += cpi->rc.this_frame_target -
- cpi->rc.projected_frame_size;
-
- cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0);
- }
-#endif
-
if (cpi->oxcf.play_alternate && cpi->refresh_alt_ref_frame &&
(cm->frame_type != KEY_FRAME))
// Update the alternate reference frame stats as appropriate.
@@ -957,6 +995,205 @@
}
void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) {
+ // Update buffer level with zero size, update frame counters, and return.
+ update_buffer_level(cpi, 0);
+ cpi->common.last_frame_type = cpi->common.frame_type;
cpi->rc.frames_since_key++;
cpi->rc.frames_to_key--;
}
+
+void vp9_rc_get_svc_params(VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ if ((cm->current_video_frame == 0) ||
+ (cm->frame_flags & FRAMEFLAGS_KEY) ||
+ (cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
+ cpi->key_frame_frequency == 0))) {
+ cm->frame_type = KEY_FRAME;
+ cpi->rc.source_alt_ref_active = 0;
+ } else {
+ cm->frame_type = INTER_FRAME;
+ }
+ cpi->rc.frames_till_gf_update_due = INT_MAX;
+ cpi->rc.baseline_gf_interval = INT_MAX;
+}
+
+static int test_for_kf_one_pass(VP9_COMP *cpi) {
+ // Placeholder function for auto key frame
+ return 0;
+}
+// Use this macro to turn on/off use of alt-refs in one-pass mode.
+#define USE_ALTREF_FOR_ONE_PASS 1
+
+static int calc_pframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
+ const RATE_CONTROL *rc = &cpi->rc;
+ int target = rc->av_per_frame_bandwidth;
+ target = vp9_rc_clamp_pframe_target_size(cpi, target);
+ return target;
+}
+
+static int calc_iframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
+ const RATE_CONTROL *rc = &cpi->rc;
+ int target = rc->av_per_frame_bandwidth * 8;
+ target = vp9_rc_clamp_iframe_target_size(cpi, target);
+ return target;
+}
+
+void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ int target;
+ if (!cpi->refresh_alt_ref_frame &&
+ (cm->current_video_frame == 0 ||
+ cm->frame_flags & FRAMEFLAGS_KEY ||
+ cpi->rc.frames_to_key == 0 ||
+ (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
+ cm->frame_type = KEY_FRAME;
+ cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
+ cpi->rc.frames_to_key == 0;
+ cpi->rc.frames_to_key = cpi->key_frame_frequency;
+ cpi->rc.kf_boost = DEFAULT_KF_BOOST;
+ cpi->rc.source_alt_ref_active = 0;
+ if (cm->current_video_frame == 0) {
+ cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+ } else {
+ // Choose active worst quality twice as large as the last q.
+ cpi->rc.active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 2;
+ if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
+ cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+ }
+ } else {
+ cm->frame_type = INTER_FRAME;
+ if (cm->current_video_frame == 1) {
+ cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+ } else {
+ // Choose active worst quality twice as large as the last q.
+ cpi->rc.active_worst_quality = cpi->rc.last_q[INTER_FRAME] * 2;
+ if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
+ cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+ }
+ }
+ if (cpi->rc.frames_till_gf_update_due == 0) {
+ cpi->rc.baseline_gf_interval = DEFAULT_GF_INTERVAL;
+ cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
+ // NOTE: frames_till_gf_update_due must be <= frames_to_key.
+ if (cpi->rc.frames_till_gf_update_due > cpi->rc.frames_to_key)
+ cpi->rc.frames_till_gf_update_due = cpi->rc.frames_to_key;
+ cpi->refresh_golden_frame = 1;
+ cpi->rc.source_alt_ref_pending = USE_ALTREF_FOR_ONE_PASS;
+ cpi->rc.gfu_boost = 2000;
+ }
+ if (cm->frame_type == KEY_FRAME)
+ target = calc_iframe_target_size_one_pass_vbr(cpi);
+ else
+ target = calc_pframe_target_size_one_pass_vbr(cpi);
+ vp9_rc_set_frame_target(cpi, target);
+}
+
+// Adjust active_worst_quality level based on buffer level.
+static int calc_active_worst_quality_one_pass_cbr(const VP9_COMP *cpi) {
+ // Adjust active_worst_quality: If buffer is above the optimal/target level,
+ // bring active_worst_quality down depending on fullness of buffer.
+ // If buffer is below the optimal level, let the active_worst_quality go from
+ // ambient Q (at buffer = optimal level) to worst_quality level
+ // (at buffer = critical level).
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
+ const RATE_CONTROL *rc = &cpi->rc;
+ int active_worst_quality = rc->active_worst_quality;
+ // Maximum limit for down adjustment, ~20%.
+ int max_adjustment_down = active_worst_quality / 5;
+ // Buffer level below which we push active_worst to worst_quality.
+ int critical_level = oxcf->optimal_buffer_level >> 2;
+ int adjustment = 0;
+ int buff_lvl_step = 0;
+ if (rc->buffer_level > oxcf->optimal_buffer_level) {
+ // Adjust down.
+ if (max_adjustment_down) {
+ buff_lvl_step = (int)((oxcf->maximum_buffer_size -
+ oxcf->optimal_buffer_level) / max_adjustment_down);
+ if (buff_lvl_step)
+ adjustment = (int)((rc->buffer_level - oxcf->optimal_buffer_level) /
+ buff_lvl_step);
+ active_worst_quality -= adjustment;
+ }
+ } else if (rc->buffer_level > critical_level) {
+ // Adjust up from ambient Q.
+ if (critical_level) {
+ buff_lvl_step = (oxcf->optimal_buffer_level - critical_level);
+ if (buff_lvl_step) {
+ adjustment = (rc->worst_quality - rc->avg_frame_qindex[INTER_FRAME]) *
+ (oxcf->optimal_buffer_level - rc->buffer_level) /
+ buff_lvl_step;
+ }
+ active_worst_quality = rc->avg_frame_qindex[INTER_FRAME] + adjustment;
+ }
+ } else {
+ // Set to worst_quality if buffer is below critical level.
+ active_worst_quality = rc->worst_quality;
+ }
+ return active_worst_quality;
+}
+
+static int calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
+ const RATE_CONTROL *rc = &cpi->rc;
+ int target = rc->av_per_frame_bandwidth;
+ const int min_frame_target = MAX(rc->av_per_frame_bandwidth >> 4,
+ FRAME_OVERHEAD_BITS);
+ const int64_t diff = oxcf->optimal_buffer_level - rc->buffer_level;
+ const int one_pct_bits = 1 + oxcf->optimal_buffer_level / 100;
+ if (diff > 0) {
+ // Lower the target bandwidth for this frame.
+ const int pct_low = MIN(diff / one_pct_bits, oxcf->under_shoot_pct);
+ target -= (target * pct_low) / 200;
+ } else if (diff < 0) {
+ // Increase the target bandwidth for this frame.
+ const int pct_high = MIN(-diff / one_pct_bits, oxcf->over_shoot_pct);
+ target += (target * pct_high) / 200;
+ }
+ if (target < min_frame_target)
+ target = min_frame_target;
+ return target;
+}
+
+static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
+ int target;
+ const RATE_CONTROL *rc = &cpi->rc;
+ if (cpi->common.current_video_frame == 0) {
+ target = cpi->oxcf.starting_buffer_level / 2;
+ } else {
+ int initial_boost = 32;
+ int kf_boost = MAX(initial_boost, (int)(2 * cpi->output_framerate - 16));
+ if (rc->frames_since_key < cpi->output_framerate / 2) {
+ kf_boost = (int)(kf_boost * rc->frames_since_key /
+ (cpi->output_framerate / 2));
+ }
+ target = ((16 + kf_boost) * rc->av_per_frame_bandwidth) >> 4;
+ }
+ return target;
+}
+
+void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ int target;
+ if ((cm->current_video_frame == 0 ||
+ cm->frame_flags & FRAMEFLAGS_KEY ||
+ cpi->rc.frames_to_key == 0 ||
+ (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
+ cm->frame_type = KEY_FRAME;
+ cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
+ cpi->rc.frames_to_key == 0;
+ cpi->rc.frames_to_key = cpi->key_frame_frequency;
+ cpi->rc.kf_boost = DEFAULT_KF_BOOST;
+ cpi->rc.source_alt_ref_active = 0;
+ target = calc_iframe_target_size_one_pass_cbr(cpi);
+ cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+ } else {
+ cm->frame_type = INTER_FRAME;
+ target = calc_pframe_target_size_one_pass_cbr(cpi);
+ cpi->rc.active_worst_quality =
+ calc_active_worst_quality_one_pass_cbr(cpi);
+ }
+ vp9_rc_set_frame_target(cpi, target);
+ // Don't use gf_update by default in CBR mode.
+ cpi->rc.frames_till_gf_update_due = INT_MAX;
+ cpi->rc.baseline_gf_interval = INT_MAX;
+}
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 65ddead..8ff567d 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -12,66 +12,155 @@
#ifndef VP9_ENCODER_VP9_RATECTRL_H_
#define VP9_ENCODER_VP9_RATECTRL_H_
-#include "vp9/encoder/vp9_onyx_int.h"
-
#ifdef __cplusplus
extern "C" {
#endif
#define FRAME_OVERHEAD_BITS 200
-void vp9_save_coding_context(VP9_COMP *cpi);
-void vp9_restore_coding_context(VP9_COMP *cpi);
+typedef struct {
+ // Rate targetting variables
+ int this_frame_target;
+ int projected_frame_size;
+ int sb64_target_rate;
+ int last_q[3]; // Separate values for Intra/Inter/ARF-GF
+ int last_boosted_qindex; // Last boosted GF/KF/ARF q
-void vp9_setup_key_frame(VP9_COMP *cpi);
-void vp9_setup_inter_frame(VP9_COMP *cpi);
+ int gfu_boost;
+ int last_boost;
+ int kf_boost;
+
+ double rate_correction_factor;
+ double key_frame_rate_correction_factor;
+ double gf_rate_correction_factor;
+
+ unsigned int frames_since_golden;
+ unsigned int frames_till_gf_update_due; // Count down till next GF
+ unsigned int max_gf_interval;
+ unsigned int baseline_gf_interval;
+ unsigned int frames_to_key;
+ unsigned int frames_since_key;
+ unsigned int this_key_frame_forced;
+ unsigned int next_key_frame_forced;
+ unsigned int source_alt_ref_pending;
+ unsigned int source_alt_ref_active;
+ unsigned int is_src_frame_alt_ref;
+
+ int av_per_frame_bandwidth; // Average frame size target for clip
+ int min_frame_bandwidth; // Minimum allocation used for any frame
+ int max_frame_bandwidth; // Maximum burst rate allowed for a frame.
+
+ int ni_av_qi;
+ int ni_tot_qi;
+ int ni_frames;
+ int avg_frame_qindex[3]; // 0 - KEY, 1 - INTER, 2 - ARF/GF
+ double tot_q;
+ double avg_q;
+
+ int buffer_level;
+ int bits_off_target;
+
+ int decimation_factor;
+ int decimation_count;
+
+ int rolling_target_bits;
+ int rolling_actual_bits;
+
+ int long_rolling_target_bits;
+ int long_rolling_actual_bits;
+
+ int64_t total_actual_bits;
+ int total_target_vs_actual; // debug stats
+
+ int worst_quality;
+ int active_worst_quality;
+ int best_quality;
+ // int active_best_quality;
+} RATE_CONTROL;
+
+struct VP9_COMP;
+
+void vp9_save_coding_context(struct VP9_COMP *cpi);
+void vp9_restore_coding_context(struct VP9_COMP *cpi);
+
+void vp9_setup_key_frame(struct VP9_COMP *cpi);
+void vp9_setup_inter_frame(struct VP9_COMP *cpi);
double vp9_convert_qindex_to_q(int qindex);
-// Updates rate correction factors
-void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var);
-
// initialize luts for minq
void vp9_rc_init_minq_luts(void);
-// return of 0 means drop frame
-// Changes only rc.this_frame_target and rc.sb64_rate_target
-int vp9_rc_pick_frame_size_target(VP9_COMP *cpi);
+// Generally at the high level, the following flow is expected
+// to be enforced for rate control:
+// First call per frame, one of:
+// vp9_rc_get_one_pass_vbr_params()
+// vp9_rc_get_one_pass_cbr_params()
+// vp9_rc_get_svc_params()
+// vp9_rc_get_first_pass_params()
+// vp9_rc_get_second_pass_params()
+// depending on the usage to set the rate control encode parameters desired.
+//
+// Then, call encode_frame_to_data_rate() to perform the
+// actual encode. This function will in turn call encode_frame()
+// one or more times, followed by one of:
+// vp9_rc_postencode_update()
+// vp9_rc_postencode_update_drop_frame()
+//
+// The majority of rate control parameters are only expected
+// to be set in the vp9_rc_get_..._params() functions and
+// updated during the vp9_rc_postencode_update...() functions.
+// The only exceptions are vp9_rc_drop_frame() and
+// vp9_rc_update_rate_correction_factors() functions.
-void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
+// Functions to set parameters for encoding before the actual
+// encode_frame_to_data_rate() function.
+void vp9_rc_get_one_pass_vbr_params(struct VP9_COMP *cpi);
+void vp9_rc_get_one_pass_cbr_params(struct VP9_COMP *cpi);
+void vp9_rc_get_svc_params(struct VP9_COMP *cpi);
+
+// Post encode update of the rate control parameters based
+// on bytes used
+void vp9_rc_postencode_update(struct VP9_COMP *cpi,
+ uint64_t bytes_used);
+// Post encode update of the rate control parameters for dropped frames
+void vp9_rc_postencode_update_drop_frame(struct VP9_COMP *cpi);
+
+// Updates rate correction factors
+// Changes only the rate correction factors in the rate control structure.
+void vp9_rc_update_rate_correction_factors(struct VP9_COMP *cpi, int damp_var);
+
+// Decide if we should drop this frame: For 1-pass CBR.
+// Changes only the decimation count in the rate control structure
+int vp9_rc_drop_frame(struct VP9_COMP *cpi);
+
+// Computes frame size bounds.
+void vp9_rc_compute_frame_size_bounds(const struct VP9_COMP *cpi,
int this_frame_target,
int *frame_under_shoot_limit,
int *frame_over_shoot_limit);
// Picks q and q bounds given the target for bits
-int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
+int vp9_rc_pick_q_and_adjust_q_bounds(const struct VP9_COMP *cpi,
int *bottom_index,
int *top_index);
// Estimates q to achieve a target bits per frame
-int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
+int vp9_rc_regulate_q(const struct VP9_COMP *cpi, int target_bits_per_frame,
int active_best_quality, int active_worst_quality);
-// Post encode update of the rate control parameters based
-// on bytes used
-void vp9_rc_postencode_update(VP9_COMP *cpi,
- uint64_t bytes_used);
-// for dropped frames
-void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi);
-
-// estimates bits per mb for a given qindex and correction factor
+// Estimates bits per mb for a given qindex and correction factor.
int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,
double correction_factor);
-// Post encode update of the rate control parameters for 2-pass
-void vp9_twopass_postencode_update(VP9_COMP *cpi,
- uint64_t bytes_used);
-
-// Decide if we should drop this frame: For 1-pass CBR.
-int vp9_drop_frame(VP9_COMP *cpi);
-
-// Update the buffer level.
-void vp9_update_buffer_level(VP9_COMP *cpi, int encoded_frame_size);
+// Clamping utilities for bitrate targets for iframes and pframes.
+int vp9_rc_clamp_iframe_target_size(const struct VP9_COMP *const cpi,
+ int target);
+int vp9_rc_clamp_pframe_target_size(const struct VP9_COMP *const cpi,
+ int target);
+// Utility to set frame_target into the RATE_CONTROL structure
+// This function is called only from the vp9_rc_get_..._params() functions.
+void vp9_rc_set_frame_target(struct VP9_COMP *cpi, int target);
#ifdef __cplusplus
} // extern "C"
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index ebe5f80..e5230fe 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -55,6 +55,22 @@
MV_REFERENCE_FRAME ref_frame[2];
} REF_DEFINITION;
+struct rdcost_block_args {
+ MACROBLOCK *x;
+ ENTROPY_CONTEXT t_above[16];
+ ENTROPY_CONTEXT t_left[16];
+ int rate;
+ int64_t dist;
+ int64_t sse;
+ int this_rate;
+ int64_t this_dist;
+ int64_t this_sse;
+ int64_t this_rd;
+ int64_t best_rd;
+ int skip;
+ const int16_t *scan, *nb;
+};
+
const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
{NEARESTMV, {LAST_FRAME, NONE}},
{NEARESTMV, {ALTREF_FRAME, NONE}},
@@ -280,22 +296,24 @@
fill_token_costs(x->token_costs, cm->fc.coef_probs);
- for (i = 0; i < PARTITION_CONTEXTS; i++)
- vp9_cost_tokens(x->partition_cost[i], get_partition_probs(cm, i),
- vp9_partition_tree);
+ if (!cpi->sf.super_fast_rtc) {
+ for (i = 0; i < PARTITION_CONTEXTS; i++)
+ vp9_cost_tokens(x->partition_cost[i], get_partition_probs(cm, i),
+ vp9_partition_tree);
- fill_mode_costs(cpi);
+ fill_mode_costs(cpi);
- if (!frame_is_intra_only(cm)) {
- vp9_build_nmv_cost_table(x->nmvjointcost,
- cm->allow_high_precision_mv ? x->nmvcost_hp
- : x->nmvcost,
- &cm->fc.nmvc,
- cm->allow_high_precision_mv, 1, 1);
+ if (!frame_is_intra_only(cm)) {
+ vp9_build_nmv_cost_table(x->nmvjointcost,
+ cm->allow_high_precision_mv ? x->nmvcost_hp
+ : x->nmvcost,
+ &cm->fc.nmvc,
+ cm->allow_high_precision_mv, 1, 1);
- for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
- vp9_cost_tokens((int *)x->inter_mode_cost[i],
- cm->fc.inter_mode_probs[i], vp9_inter_mode_tree);
+ for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
+ vp9_cost_tokens((int *)x->inter_mode_cost[i],
+ cm->fc.inter_mode_probs[i], vp9_inter_mode_tree);
+ }
}
}
@@ -419,12 +437,22 @@
struct macroblock_plane *const p = &x->plane[i];
struct macroblockd_plane *const pd = &xd->plane[i];
const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
+
(void) cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride,
pd->dst.buf, pd->dst.stride, &sse);
+
if (i == 0)
x->pred_sse[ref] = sse;
-
- dist_sum += (int)sse;
+ if (cpi->sf.super_fast_rtc) {
+ dist_sum += (int)sse;
+ } else {
+ int rate;
+ int64_t dist;
+ model_rd_from_var_lapndz(sse, 1 << num_pels_log2_lookup[bs],
+ pd->dequant[1] >> 3, &rate, &dist);
+ rate_sum += rate;
+ dist_sum += (int)dist;
+ }
}
*out_rate_sum = rate_sum;
@@ -575,15 +603,15 @@
return cost;
}
-static void dist_block(int plane, int block, TX_SIZE tx_size, void *arg) {
+static void dist_block(int plane, int block, TX_SIZE tx_size,
+ struct rdcost_block_args* args) {
const int ss_txfrm_size = tx_size << 1;
- struct rdcost_block_args* args = arg;
MACROBLOCK* const x = args->x;
MACROBLOCKD* const xd = &x->e_mbd;
struct macroblock_plane *const p = &x->plane[plane];
struct macroblockd_plane *const pd = &xd->plane[plane];
int64_t this_sse;
- int shift = args->tx_size == TX_32X32 ? 0 : 2;
+ int shift = tx_size == TX_32X32 ? 0 : 2;
int16_t *const coeff = BLOCK_OFFSET(p->coeff, block);
int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
args->dist = vp9_block_error(coeff, dqcoeff, 16 << ss_txfrm_size,
@@ -600,14 +628,12 @@
}
static void rate_block(int plane, int block, BLOCK_SIZE plane_bsize,
- TX_SIZE tx_size, void *arg) {
- struct rdcost_block_args* args = arg;
-
+ TX_SIZE tx_size, struct rdcost_block_args* args) {
int x_idx, y_idx;
- txfrm_block_to_raster_xy(plane_bsize, args->tx_size, block, &x_idx, &y_idx);
+ txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x_idx, &y_idx);
args->rate = cost_coeffs(args->x, plane, block, args->t_above + x_idx,
- args->t_left + y_idx, args->tx_size,
+ args->t_left + y_idx, tx_size,
args->scan, args->nb);
}
@@ -684,24 +710,19 @@
}
}
-static void init_rdcost_stack(MACROBLOCK *x, TX_SIZE tx_size,
- const int num_4x4_w, const int num_4x4_h,
- const int64_t ref_rdcost,
+static void init_rdcost_stack(MACROBLOCK *x, const int64_t ref_rdcost,
struct rdcost_block_args *arg) {
vpx_memset(arg, 0, sizeof(struct rdcost_block_args));
arg->x = x;
- arg->tx_size = tx_size;
- arg->bw = num_4x4_w;
- arg->bh = num_4x4_h;
arg->best_rd = ref_rdcost;
}
static void txfm_rd_in_plane(MACROBLOCK *x,
- struct rdcost_block_args *rd_stack,
int *rate, int64_t *distortion,
int *skippable, int64_t *sse,
int64_t ref_best_rd, int plane,
BLOCK_SIZE bsize, TX_SIZE tx_size) {
+ struct rdcost_block_args rd_stack;
MACROBLOCKD *const xd = &x->e_mbd;
struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
@@ -709,30 +730,29 @@
const int num_4x4_h = num_4x4_blocks_high_lookup[bs];
const scan_order *so;
- init_rdcost_stack(x, tx_size, num_4x4_w, num_4x4_h,
- ref_best_rd, rd_stack);
+ init_rdcost_stack(x, ref_best_rd, &rd_stack);
if (plane == 0)
xd->mi_8x8[0]->mbmi.tx_size = tx_size;
- vp9_get_entropy_contexts(tx_size, rd_stack->t_above, rd_stack->t_left,
+ vp9_get_entropy_contexts(tx_size, rd_stack.t_above, rd_stack.t_left,
pd->above_context, pd->left_context,
num_4x4_w, num_4x4_h);
so = get_scan(xd, tx_size, pd->plane_type, 0);
- rd_stack->scan = so->scan;
- rd_stack->nb = so->neighbors;
+ rd_stack.scan = so->scan;
+ rd_stack.nb = so->neighbors;
- foreach_transformed_block_in_plane(xd, bsize, plane,
- block_rd_txfm, rd_stack);
- if (rd_stack->skip) {
+ vp9_foreach_transformed_block_in_plane(xd, bsize, plane,
+ block_rd_txfm, &rd_stack);
+ if (rd_stack.skip) {
*rate = INT_MAX;
*distortion = INT64_MAX;
*sse = INT64_MAX;
*skippable = 0;
} else {
- *distortion = rd_stack->this_dist;
- *rate = rd_stack->this_rate;
- *sse = rd_stack->this_sse;
+ *distortion = rd_stack.this_dist;
+ *rate = rd_stack.this_rate;
+ *sse = rd_stack.this_sse;
*skippable = vp9_is_skippable_in_plane(x, bsize, plane);
}
}
@@ -750,7 +770,7 @@
mbmi->tx_size = MIN(max_tx_size, largest_tx_size);
- txfm_rd_in_plane(x, &cpi->rdcost_stack, rate, distortion, skip,
+ txfm_rd_in_plane(x, rate, distortion, skip,
&sse[mbmi->tx_size], ref_best_rd, 0, bs,
mbmi->tx_size);
cpi->tx_stepdown_count[0]++;
@@ -881,7 +901,7 @@
// Actually encode using the chosen mode if a model was used, but do not
// update the r, d costs
- txfm_rd_in_plane(x, &cpi->rdcost_stack, rate, distortion, skip,
+ txfm_rd_in_plane(x, rate, distortion, skip,
&sse[mbmi->tx_size], ref_best_rd, 0, bs, mbmi->tx_size);
if (max_tx_size == TX_32X32 && best_tx == TX_32X32) {
@@ -904,7 +924,6 @@
int64_t d[TX_SIZES], sse[TX_SIZES];
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
- struct rdcost_block_args *rdcost_stack = &cpi->rdcost_stack;
const int b_inter_mode = is_inter_block(mbmi);
const TX_SIZE max_tx_size = max_txsize_lookup[bs];
TX_SIZE tx_size;
@@ -934,7 +953,7 @@
skip, sse, ref_best_rd, bs);
} else {
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
- txfm_rd_in_plane(x, rdcost_stack, &r[tx_size][0], &d[tx_size],
+ txfm_rd_in_plane(x, &r[tx_size][0], &d[tx_size],
&s[tx_size], &sse[tx_size],
ref_best_rd, 0, bs, tx_size);
choose_txfm_size_from_rd(cpi, x, r, rate, d, distortion, s,
@@ -1131,8 +1150,8 @@
int64_t d = INT64_MAX, this_rd = INT64_MAX;
i = idy * 2 + idx;
if (cpi->common.frame_type == KEY_FRAME) {
- const MB_PREDICTION_MODE A = above_block_mode(mic, above_mi, i);
- const MB_PREDICTION_MODE L = left_block_mode(mic, left_mi, i);
+ const MB_PREDICTION_MODE A = vp9_above_block_mode(mic, above_mi, i);
+ const MB_PREDICTION_MODE L = vp9_left_block_mode(mic, left_mi, i);
bmode_costs = mb->y_mode_costs[A][L];
}
@@ -1197,8 +1216,8 @@
continue;
if (cpi->common.frame_type == KEY_FRAME) {
- const MB_PREDICTION_MODE A = above_block_mode(mic, above_mi, 0);
- const MB_PREDICTION_MODE L = left_block_mode(mic, left_mi, 0);
+ const MB_PREDICTION_MODE A = vp9_above_block_mode(mic, above_mi, 0);
+ const MB_PREDICTION_MODE L = vp9_left_block_mode(mic, left_mi, 0);
bmode_costs = x->y_mode_costs[A][L];
}
@@ -1263,7 +1282,7 @@
*skippable = 1;
for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
- txfm_rd_in_plane(x, &cpi->rdcost_stack, &pnrate, &pndist, &pnskip, &pnsse,
+ txfm_rd_in_plane(x, &pnrate, &pndist, &pnskip, &pnsse,
ref_best_rd, plane, bsize, uv_txfm_size);
if (pnrate == INT_MAX)
goto term;
@@ -1749,7 +1768,8 @@
if (best_rd < label_mv_thresh)
break;
- if (cpi->compressor_speed) {
+ if (cpi->oxcf.mode != MODE_SECONDPASS_BEST &&
+ cpi->oxcf.mode != MODE_BESTQUALITY) {
// use previous block's result as next block's MV predictor.
if (i > 0) {
bsi->mvp.as_int = mi->bmi[i - 1].as_mv[0].as_int;
@@ -1813,7 +1833,8 @@
}
// Should we do a full search (best quality only)
- if (cpi->compressor_speed == 0) {
+ if (cpi->oxcf.mode == MODE_BESTQUALITY ||
+ cpi->oxcf.mode == MODE_SECONDPASS_BEST) {
/* Check if mvp_full is within the range. */
clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max,
x->mv_row_min, x->mv_row_max);
@@ -1840,7 +1861,8 @@
&bsi->ref_mv->as_mv,
cm->allow_high_precision_mv,
x->errorperbit, v_fn_ptr,
- 0, cpi->sf.subpel_iters_per_step,
+ cpi->sf.subpel_force_stop,
+ cpi->sf.subpel_iters_per_step,
x->nmvjointcost, x->mvcost,
&distortion,
&x->pred_sse[mbmi->ref_frame[0]]);
@@ -2309,7 +2331,7 @@
const VP9_COMMON *const cm = &cpi->common;
const int ref_idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
const int scaled_idx = cpi->scaled_ref_idx[ref_frame - 1];
- return (scaled_idx != ref_idx) ? &cm->yv12_fb[scaled_idx] : NULL;
+ return (scaled_idx != ref_idx) ? &cm->frame_bufs[scaled_idx].buf : NULL;
}
static INLINE int get_switchable_rate(const MACROBLOCK *x) {
@@ -2451,7 +2473,8 @@
cm->allow_high_precision_mv,
x->errorperbit,
&cpi->fn_ptr[bsize],
- 0, cpi->sf.subpel_iters_per_step,
+ cpi->sf.subpel_force_stop,
+ cpi->sf.subpel_iters_per_step,
x->nmvjointcost, x->mvcost,
&dis, &x->pred_sse[ref]);
}
@@ -2783,7 +2806,7 @@
int j;
int64_t rs_rd;
mbmi->interp_filter = i;
- vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
+ xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
rs = get_switchable_rate(x);
rs_rd = RDCOST(x->rdmult, x->rddiv, rs, 0);
@@ -2854,7 +2877,7 @@
// Set the appropriate filter
mbmi->interp_filter = cm->interp_filter != SWITCHABLE ?
cm->interp_filter : *best_filter;
- vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
+ xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
rs = cm->interp_filter == SWITCHABLE ? get_switchable_rate(x) : 0;
if (pred_exists) {
@@ -3277,13 +3300,14 @@
continue;
}
- set_ref_ptrs(cm, xd, ref_frame - 1, second_ref_frame - 1);
+ set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
mbmi->uv_mode = DC_PRED;
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
- mbmi->interp_filter = cm->interp_filter;
- vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
+ mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
+ : cm->interp_filter;
+ xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
if (comp_pred) {
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
@@ -3709,7 +3733,7 @@
vp9_zero(best_tx_diff);
}
- set_ref_ptrs(cm, xd, mbmi->ref_frame[0] - 1, mbmi->ref_frame[1] - 1);
+ set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
store_coding_context(x, ctx, best_mode_index,
&mbmi->ref_mvs[mbmi->ref_frame[0]][0],
&mbmi->ref_mvs[mbmi->ref_frame[1] < 0 ? 0 :
@@ -3902,13 +3926,14 @@
vp9_is_scaled(&cm->frame_refs[second_ref_frame - 1].sf))
continue;
- set_ref_ptrs(cm, xd, ref_frame - 1, second_ref_frame - 1);
+ set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
mbmi->uv_mode = DC_PRED;
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
- mbmi->interp_filter = cm->interp_filter;
- vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
+ mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
+ : cm->interp_filter;
+ xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
if (comp_pred) {
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
@@ -4031,8 +4056,7 @@
int newbest, rs;
int64_t rs_rd;
mbmi->interp_filter = switchable_filter_index;
- vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
-
+ xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
tmp_rd = rd_pick_best_mbsegmentation(cpi, x, tile,
&mbmi->ref_mvs[ref_frame][0],
second_ref,
@@ -4097,7 +4121,7 @@
mbmi->interp_filter = (cm->interp_filter == SWITCHABLE ?
tmp_best_filter : cm->interp_filter);
- vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
+ xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
if (!pred_exists) {
// Handles the special case when a filter that is not in the
// switchable list (bilinear, 6-tap) is indicated at the frame level
@@ -4442,7 +4466,7 @@
vp9_zero(best_tx_diff);
}
- set_ref_ptrs(cm, xd, mbmi->ref_frame[0] - 1, mbmi->ref_frame[1] - 1);
+ set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
store_coding_context(x, ctx, best_mode_index,
&mbmi->ref_mvs[mbmi->ref_frame[0]][0],
&mbmi->ref_mvs[mbmi->ref_frame[1] < 0 ? 0 :
diff --git a/vp9/encoder/vp9_subexp.c b/vp9/encoder/vp9_subexp.c
index def99d1..84fb35e 100644
--- a/vp9/encoder/vp9_subexp.c
+++ b/vp9/encoder/vp9_subexp.c
@@ -18,17 +18,6 @@
static int update_bits[255];
-static int count_uniform(int v, int n) {
- int l = get_unsigned_bits(n);
- int m;
- if (l == 0) return 0;
- m = (1 << l) - n;
- if (v < m)
- return l - 1;
- else
- return l;
-}
-
static int split_index(int i, int n, int modulus) {
int max1 = (n - 1 - modulus / 2) / modulus + 1;
if (i % modulus == modulus / 2)
@@ -81,29 +70,16 @@
return i;
}
-static int count_term_subexp(int word, int k, int num_syms) {
- int count = 0;
- int i = 0;
- int mk = 0;
- while (1) {
- int b = (i ? k + i - 1 : k);
- int a = (1 << b);
- if (num_syms <= mk + 3 * a) {
- count += count_uniform(word - mk, num_syms - mk);
- break;
- } else {
- int t = (word >= mk + a);
- count++;
- if (t) {
- i = i + 1;
- mk += a;
- } else {
- count += b;
- break;
- }
- }
- }
- return count;
+static int count_term_subexp(int word) {
+ if (word < 16)
+ return 5;
+ if (word < 32)
+ return 6;
+ if (word < 64)
+ return 8;
+ if (word < 129)
+ return 10;
+ return 11;
}
static int prob_diff_update_cost(vp9_prob newp, vp9_prob oldp) {
@@ -111,12 +87,9 @@
return update_bits[delp] * 256;
}
-static void encode_uniform(vp9_writer *w, int v, int n) {
- int l = get_unsigned_bits(n);
- int m;
- if (l == 0)
- return;
- m = (1 << l) - n;
+static void encode_uniform(vp9_writer *w, int v) {
+ const int l = 8;
+ const int m = (1 << l) - 191;
if (v < m) {
vp9_write_literal(w, v, l - 1);
} else {
@@ -125,38 +98,32 @@
}
}
-static void encode_term_subexp(vp9_writer *w, int word, int k, int num_syms) {
- int i = 0;
- int mk = 0;
- while (1) {
- int b = (i ? k + i - 1 : k);
- int a = (1 << b);
- if (num_syms <= mk + 3 * a) {
- encode_uniform(w, word - mk, num_syms - mk);
- break;
- } else {
- int t = (word >= mk + a);
- vp9_write_literal(w, t, 1);
- if (t) {
- i = i + 1;
- mk += a;
- } else {
- vp9_write_literal(w, word - mk, b);
- break;
- }
- }
+static INLINE int write_bit_gte(vp9_writer *w, int word, int test) {
+ vp9_write_literal(w, word >= test, 1);
+ return word >= test;
+}
+
+static void encode_term_subexp(vp9_writer *w, int word) {
+ if (!write_bit_gte(w, word, 16)) {
+ vp9_write_literal(w, word, 4);
+ } else if (!write_bit_gte(w, word, 32)) {
+ vp9_write_literal(w, word - 16, 4);
+ } else if (!write_bit_gte(w, word, 64)) {
+ vp9_write_literal(w, word - 32, 5);
+ } else {
+ encode_uniform(w, word - 64);
}
}
void vp9_write_prob_diff_update(vp9_writer *w, vp9_prob newp, vp9_prob oldp) {
const int delp = remap_prob(newp, oldp);
- encode_term_subexp(w, delp, SUBEXP_PARAM, 255);
+ encode_term_subexp(w, delp);
}
void vp9_compute_update_table() {
int i;
for (i = 0; i < 254; i++)
- update_bits[i] = count_term_subexp(i, SUBEXP_PARAM, 255);
+ update_bits[i] = count_term_subexp(i);
}
int vp9_prob_diff_update_savings_search(const unsigned int *ct,
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index c9a4246..e16467a 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -134,17 +134,16 @@
int sadpb = x->sadperbit16;
int bestsme = INT_MAX;
- int_mv best_ref_mv1;
- int_mv best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
- int_mv *ref_mv;
+ MV best_ref_mv1 = {0, 0};
+ MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
+ MV *ref_mv = &x->e_mbd.mi_8x8[0]->bmi[0].as_mv[0].as_mv;
// Save input state
struct buf_2d src = x->plane[0].src;
struct buf_2d pre = xd->plane[0].pre[0];
- best_ref_mv1.as_int = 0;
- best_ref_mv1_full.as_mv.col = best_ref_mv1.as_mv.col >> 3;
- best_ref_mv1_full.as_mv.row = best_ref_mv1.as_mv.row >> 3;
+ best_ref_mv1_full.col = best_ref_mv1.col >> 3;
+ best_ref_mv1_full.row = best_ref_mv1.row >> 3;
// Setup frame pointers
x->plane[0].src.buf = arf_frame_buf;
@@ -161,11 +160,9 @@
/*cpi->sf.search_method == HEX*/
// Ignore mv costing by sending NULL pointer instead of cost arrays
- ref_mv = &x->e_mbd.mi_8x8[0]->bmi[0].as_mv[0];
- bestsme = vp9_hex_search(x, &best_ref_mv1_full.as_mv,
- step_param, sadpb, 1,
+ bestsme = vp9_hex_search(x, &best_ref_mv1_full, step_param, sadpb, 1,
&cpi->fn_ptr[BLOCK_16X16],
- 0, &best_ref_mv1.as_mv, &ref_mv->as_mv);
+ 0, &best_ref_mv1, ref_mv);
#if ALT_REF_SUBPEL_ENABLED
// Try sub-pixel MC?
@@ -174,8 +171,8 @@
int distortion;
unsigned int sse;
// Ignore mv costing by sending NULL pointer instead of cost array
- bestsme = cpi->find_fractional_mv_step(x, &ref_mv->as_mv,
- &best_ref_mv1.as_mv,
+ bestsme = cpi->find_fractional_mv_step(x, ref_mv,
+ &best_ref_mv1,
cpi->common.allow_high_precision_mv,
x->errorperbit,
&cpi->fn_ptr[BLOCK_16X16],
@@ -392,7 +389,6 @@
const int num_frames_backward = distance;
const int num_frames_forward = vp9_lookahead_depth(cpi->lookahead)
- (num_frames_backward + 1);
-
struct scale_factors sf;
switch (blur_type) {
@@ -408,7 +404,6 @@
case 2:
// Forward Blur
-
frames_to_blur_forward = num_frames_forward;
if (frames_to_blur_forward >= max_frames)
@@ -471,22 +466,24 @@
strength, &sf);
}
-void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
- const int group_boost) {
+void vp9_configure_arnr_filter(VP9_COMP *cpi,
+ const unsigned int frames_to_arnr,
+ const int group_boost) {
int half_gf_int;
int frames_after_arf;
int frames_bwd = cpi->oxcf.arnr_max_frames - 1;
int frames_fwd = cpi->oxcf.arnr_max_frames - 1;
int q;
- // Define the arnr filter width for this group of frames:
- // We only filter frames that lie within a distance of half
- // the GF interval from the ARF frame. We also have to trap
- // cases where the filter extends beyond the end of clip.
- // Note: this_frame->frame has been updated in the loop
- // so it now points at the ARF frame.
+ // Define the arnr filter width for this group of frames. We only
+ // filter frames that lie within a distance of half the GF interval
+ // from the ARF frame. We also have to trap cases where the filter
+ // extends beyond the end of the lookahead buffer.
+ // Note: frames_to_arnr parameter is the offset of the arnr
+ // frame from the current frame.
half_gf_int = cpi->rc.baseline_gf_interval >> 1;
- frames_after_arf = (int)(cpi->twopass.total_stats.count - this_frame - 1);
+ frames_after_arf = vp9_lookahead_depth(cpi->lookahead)
+ - frames_to_arnr - 1;
switch (cpi->oxcf.arnr_type) {
case 1: // Backward filter
diff --git a/vp9/encoder/vp9_temporal_filter.h b/vp9/encoder/vp9_temporal_filter.h
index eea2f10..3028d78 100644
--- a/vp9/encoder/vp9_temporal_filter.h
+++ b/vp9/encoder/vp9_temporal_filter.h
@@ -16,8 +16,9 @@
#endif
void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance);
-void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
- const int group_boost);
+void vp9_configure_arnr_filter(VP9_COMP *cpi,
+ const unsigned int frames_to_arnr,
+ const int group_boost);
#ifdef __cplusplus
} // extern "C"
diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c
index b04e3fe..ed1301a 100644
--- a/vp9/encoder/vp9_tokenize.c
+++ b/vp9/encoder/vp9_tokenize.c
@@ -172,7 +172,8 @@
struct macroblockd_plane *pd = &xd->plane[plane];
int aoff, loff;
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff);
- set_contexts(xd, pd, plane_bsize, tx_size, p->eobs[block] > 0, aoff, loff);
+ vp9_set_contexts(xd, pd, plane_bsize, tx_size, p->eobs[block] > 0,
+ aoff, loff);
}
static INLINE void add_token(TOKENEXTRA **t, const vp9_prob *context_tree,
@@ -259,7 +260,7 @@
*tp = t;
- set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff);
+ vp9_set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff);
}
struct is_skippable_args {
@@ -277,15 +278,15 @@
static int sb_is_skippable(MACROBLOCK *x, BLOCK_SIZE bsize) {
int result = 1;
struct is_skippable_args args = {x, &result};
- foreach_transformed_block(&x->e_mbd, bsize, is_skippable, &args);
+ vp9_foreach_transformed_block(&x->e_mbd, bsize, is_skippable, &args);
return result;
}
int vp9_is_skippable_in_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
int result = 1;
struct is_skippable_args args = {x, &result};
- foreach_transformed_block_in_plane(&x->e_mbd, bsize, plane, is_skippable,
- &args);
+ vp9_foreach_transformed_block_in_plane(&x->e_mbd, bsize, plane, is_skippable,
+ &args);
return result;
}
@@ -301,7 +302,7 @@
struct tokenize_b_args arg = {cpi, xd, t, mbmi->tx_size, cpi->mb.token_cache};
if (mbmi->skip_coeff) {
if (!dry_run)
- cm->counts.mbskip[ctx][1] += skip_inc;
+ cm->counts.skip[ctx][1] += skip_inc;
reset_skip_context(xd, bsize);
if (dry_run)
*t = t_backup;
@@ -309,10 +310,10 @@
}
if (!dry_run) {
- cm->counts.mbskip[ctx][0] += skip_inc;
- foreach_transformed_block(xd, bsize, tokenize_b, &arg);
+ cm->counts.skip[ctx][0] += skip_inc;
+ vp9_foreach_transformed_block(xd, bsize, tokenize_b, &arg);
} else {
- foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
+ vp9_foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
*t = t_backup;
}
}
diff --git a/vp9/encoder/vp9_variance_c.c b/vp9/encoder/vp9_variance.c
similarity index 100%
rename from vp9/encoder/vp9_variance_c.c
rename to vp9/encoder/vp9_variance.c
diff --git a/vp9/encoder/vp9_writer.c b/vp9/encoder/vp9_writer.c
index 3d13d07..fda1b39 100644
--- a/vp9/encoder/vp9_writer.c
+++ b/vp9/encoder/vp9_writer.c
@@ -12,11 +12,6 @@
#include "vp9/encoder/vp9_writer.h"
#include "vp9/common/vp9_entropy.h"
-#if defined(SECTIONBITS_OUTPUT)
-unsigned __int64 Sectionbits[500];
-
-#endif
-
#ifdef ENTROPY_STATS
unsigned int active_section = 0;
#endif
diff --git a/vp9/encoder/vp9_writer.h b/vp9/encoder/vp9_writer.h
index 62f555c..defeec3 100644
--- a/vp9/encoder/vp9_writer.h
+++ b/vp9/encoder/vp9_writer.h
@@ -44,17 +44,6 @@
unsigned int lowvalue = br->lowvalue;
register unsigned int shift;
-#ifdef ENTROPY_STATS
-#if defined(SECTIONBITS_OUTPUT)
-
- if (bit)
- Sectionbits[active_section] += vp9_prob_cost[255 - probability];
- else
- Sectionbits[active_section] += vp9_prob_cost[probability];
-
-#endif
-#endif
-
split = 1 + (((range - 1) * probability) >> 8);
range = split;
diff --git a/vp9/encoder/x86/vp9_dct_avx2.c b/vp9/encoder/x86/vp9_dct_avx2.c
index d81b72b..ea031fb 100644
--- a/vp9/encoder/x86/vp9_dct_avx2.c
+++ b/vp9/encoder/x86/vp9_dct_avx2.c
@@ -163,7 +163,7 @@
res[3] = _mm_unpackhi_epi64(res[2], res[2]);
}
-void fdct4_1d_avx2(__m128i *in) {
+void fdct4_avx2(__m128i *in) {
const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64);
const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i k__cospi_p08_p24 = pair_set_epi16(cospi_8_64, cospi_24_64);
@@ -196,7 +196,7 @@
transpose_4x4_avx2(in);
}
-void fadst4_1d_avx2(__m128i *in) {
+void fadst4_avx2(__m128i *in) {
const __m128i k__sinpi_p01_p02 = pair_set_epi16(sinpi_1_9, sinpi_2_9);
const __m128i k__sinpi_p04_m01 = pair_set_epi16(sinpi_4_9, -sinpi_1_9);
const __m128i k__sinpi_p03_p04 = pair_set_epi16(sinpi_3_9, sinpi_4_9);
@@ -250,20 +250,20 @@
load_buffer_4x4_avx2(input, in, stride);
switch (tx_type) {
case 0: // DCT_DCT
- fdct4_1d_avx2(in);
- fdct4_1d_avx2(in);
+ fdct4_avx2(in);
+ fdct4_avx2(in);
break;
case 1: // ADST_DCT
- fadst4_1d_avx2(in);
- fdct4_1d_avx2(in);
+ fadst4_avx2(in);
+ fdct4_avx2(in);
break;
case 2: // DCT_ADST
- fdct4_1d_avx2(in);
- fadst4_1d_avx2(in);
+ fdct4_avx2(in);
+ fadst4_avx2(in);
break;
case 3: // ADST_ADST
- fadst4_1d_avx2(in);
- fadst4_1d_avx2(in);
+ fadst4_avx2(in);
+ fadst4_avx2(in);
break;
default:
assert(0);
@@ -658,7 +658,7 @@
// 07 17 27 37 47 57 67 77
}
-void fdct8_1d_avx2(__m128i *in) {
+void fdct8_avx2(__m128i *in) {
// constants
const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64);
const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
@@ -798,7 +798,7 @@
array_transpose_8x8_avx2(in, in);
}
-void fadst8_1d_avx2(__m128i *in) {
+void fadst8_avx2(__m128i *in) {
// Constants
const __m128i k__cospi_p02_p30 = pair_set_epi16(cospi_2_64, cospi_30_64);
const __m128i k__cospi_p30_m02 = pair_set_epi16(cospi_30_64, -cospi_2_64);
@@ -1034,20 +1034,20 @@
load_buffer_8x8_avx2(input, in, stride);
switch (tx_type) {
case 0: // DCT_DCT
- fdct8_1d_avx2(in);
- fdct8_1d_avx2(in);
+ fdct8_avx2(in);
+ fdct8_avx2(in);
break;
case 1: // ADST_DCT
- fadst8_1d_avx2(in);
- fdct8_1d_avx2(in);
+ fadst8_avx2(in);
+ fdct8_avx2(in);
break;
case 2: // DCT_ADST
- fdct8_1d_avx2(in);
- fadst8_1d_avx2(in);
+ fdct8_avx2(in);
+ fadst8_avx2(in);
break;
case 3: // ADST_ADST
- fadst8_1d_avx2(in);
- fadst8_1d_avx2(in);
+ fadst8_avx2(in);
+ fadst8_avx2(in);
break;
default:
assert(0);
@@ -1216,7 +1216,7 @@
step1_6 = _mm_sub_epi16(in01, in14);
step1_7 = _mm_sub_epi16(in00, in15);
}
- // Work on the first eight values; fdct8_1d(input, even_results);
+ // Work on the first eight values; fdct8(input, even_results);
{
// Add/substract
const __m128i q0 = _mm_add_epi16(input0, input7);
@@ -1730,7 +1730,7 @@
right_shift_8x8_avx2(res1 + 8, 2);
}
-void fdct16_1d_8col_avx2(__m128i *in) {
+void fdct16_8col_avx2(__m128i *in) {
// perform 16x16 1-D DCT for 8 columns
__m128i i[8], s[8], p[8], t[8], u[16], v[16];
const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64);
@@ -2052,7 +2052,7 @@
in[15] = _mm_packs_epi32(v[14], v[15]);
}
-void fadst16_1d_8col_avx2(__m128i *in) {
+void fadst16_8col_avx2(__m128i *in) {
// perform 16x16 1-D ADST for 8 columns
__m128i s[16], x[16], u[32], v[32];
const __m128i k__cospi_p01_p31 = pair_set_epi16(cospi_1_64, cospi_31_64);
@@ -2522,15 +2522,15 @@
in[15] = _mm_sub_epi16(kZero, s[1]);
}
-void fdct16_1d_avx2(__m128i *in0, __m128i *in1) {
- fdct16_1d_8col_avx2(in0);
- fdct16_1d_8col_avx2(in1);
+void fdct16_avx2(__m128i *in0, __m128i *in1) {
+ fdct16_8col_avx2(in0);
+ fdct16_8col_avx2(in1);
array_transpose_16x16_avx2(in0, in1);
}
-void fadst16_1d_avx2(__m128i *in0, __m128i *in1) {
- fadst16_1d_8col_avx2(in0);
- fadst16_1d_8col_avx2(in1);
+void fadst16_avx2(__m128i *in0, __m128i *in1) {
+ fadst16_8col_avx2(in0);
+ fadst16_8col_avx2(in1);
array_transpose_16x16_avx2(in0, in1);
}
@@ -2540,24 +2540,24 @@
load_buffer_16x16_avx2(input, in0, in1, stride);
switch (tx_type) {
case 0: // DCT_DCT
- fdct16_1d_avx2(in0, in1);
+ fdct16_avx2(in0, in1);
right_shift_16x16_avx2(in0, in1);
- fdct16_1d_avx2(in0, in1);
+ fdct16_avx2(in0, in1);
break;
case 1: // ADST_DCT
- fadst16_1d_avx2(in0, in1);
+ fadst16_avx2(in0, in1);
right_shift_16x16_avx2(in0, in1);
- fdct16_1d_avx2(in0, in1);
+ fdct16_avx2(in0, in1);
break;
case 2: // DCT_ADST
- fdct16_1d_avx2(in0, in1);
+ fdct16_avx2(in0, in1);
right_shift_16x16_avx2(in0, in1);
- fadst16_1d_avx2(in0, in1);
+ fadst16_avx2(in0, in1);
break;
case 3: // ADST_ADST
- fadst16_1d_avx2(in0, in1);
+ fadst16_avx2(in0, in1);
right_shift_16x16_avx2(in0, in1);
- fadst16_1d_avx2(in0, in1);
+ fadst16_avx2(in0, in1);
break;
default:
assert(0);
diff --git a/vp9/encoder/x86/vp9_dct_sse2.c b/vp9/encoder/x86/vp9_dct_sse2.c
index 65431bd..c876cc2 100644
--- a/vp9/encoder/x86/vp9_dct_sse2.c
+++ b/vp9/encoder/x86/vp9_dct_sse2.c
@@ -161,7 +161,7 @@
res[3] = _mm_unpackhi_epi64(res[2], res[2]);
}
-void fdct4_1d_sse2(__m128i *in) {
+void fdct4_sse2(__m128i *in) {
const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64);
const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i k__cospi_p08_p24 = pair_set_epi16(cospi_8_64, cospi_24_64);
@@ -194,7 +194,7 @@
transpose_4x4(in);
}
-void fadst4_1d_sse2(__m128i *in) {
+void fadst4_sse2(__m128i *in) {
const __m128i k__sinpi_p01_p02 = pair_set_epi16(sinpi_1_9, sinpi_2_9);
const __m128i k__sinpi_p04_m01 = pair_set_epi16(sinpi_4_9, -sinpi_1_9);
const __m128i k__sinpi_p03_p04 = pair_set_epi16(sinpi_3_9, sinpi_4_9);
@@ -248,20 +248,20 @@
load_buffer_4x4(input, in, stride);
switch (tx_type) {
case 0: // DCT_DCT
- fdct4_1d_sse2(in);
- fdct4_1d_sse2(in);
+ fdct4_sse2(in);
+ fdct4_sse2(in);
break;
case 1: // ADST_DCT
- fadst4_1d_sse2(in);
- fdct4_1d_sse2(in);
+ fadst4_sse2(in);
+ fdct4_sse2(in);
break;
case 2: // DCT_ADST
- fdct4_1d_sse2(in);
- fadst4_1d_sse2(in);
+ fdct4_sse2(in);
+ fadst4_sse2(in);
break;
case 3: // ADST_ADST
- fadst4_1d_sse2(in);
- fadst4_1d_sse2(in);
+ fadst4_sse2(in);
+ fadst4_sse2(in);
break;
default:
assert(0);
@@ -656,7 +656,7 @@
// 07 17 27 37 47 57 67 77
}
-void fdct8_1d_sse2(__m128i *in) {
+void fdct8_sse2(__m128i *in) {
// constants
const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64);
const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
@@ -796,7 +796,7 @@
array_transpose_8x8(in, in);
}
-void fadst8_1d_sse2(__m128i *in) {
+void fadst8_sse2(__m128i *in) {
// Constants
const __m128i k__cospi_p02_p30 = pair_set_epi16(cospi_2_64, cospi_30_64);
const __m128i k__cospi_p30_m02 = pair_set_epi16(cospi_30_64, -cospi_2_64);
@@ -1032,20 +1032,20 @@
load_buffer_8x8(input, in, stride);
switch (tx_type) {
case 0: // DCT_DCT
- fdct8_1d_sse2(in);
- fdct8_1d_sse2(in);
+ fdct8_sse2(in);
+ fdct8_sse2(in);
break;
case 1: // ADST_DCT
- fadst8_1d_sse2(in);
- fdct8_1d_sse2(in);
+ fadst8_sse2(in);
+ fdct8_sse2(in);
break;
case 2: // DCT_ADST
- fdct8_1d_sse2(in);
- fadst8_1d_sse2(in);
+ fdct8_sse2(in);
+ fadst8_sse2(in);
break;
case 3: // ADST_ADST
- fadst8_1d_sse2(in);
- fadst8_1d_sse2(in);
+ fadst8_sse2(in);
+ fadst8_sse2(in);
break;
default:
assert(0);
@@ -1214,7 +1214,7 @@
step1_6 = _mm_sub_epi16(in01, in14);
step1_7 = _mm_sub_epi16(in00, in15);
}
- // Work on the first eight values; fdct8_1d(input, even_results);
+ // Work on the first eight values; fdct8(input, even_results);
{
// Add/substract
const __m128i q0 = _mm_add_epi16(input0, input7);
@@ -1728,7 +1728,7 @@
right_shift_8x8(res1 + 8, 2);
}
-void fdct16_1d_8col(__m128i *in) {
+void fdct16_8col(__m128i *in) {
// perform 16x16 1-D DCT for 8 columns
__m128i i[8], s[8], p[8], t[8], u[16], v[16];
const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64);
@@ -2050,7 +2050,7 @@
in[15] = _mm_packs_epi32(v[14], v[15]);
}
-void fadst16_1d_8col(__m128i *in) {
+void fadst16_8col(__m128i *in) {
// perform 16x16 1-D ADST for 8 columns
__m128i s[16], x[16], u[32], v[32];
const __m128i k__cospi_p01_p31 = pair_set_epi16(cospi_1_64, cospi_31_64);
@@ -2520,15 +2520,15 @@
in[15] = _mm_sub_epi16(kZero, s[1]);
}
-void fdct16_1d_sse2(__m128i *in0, __m128i *in1) {
- fdct16_1d_8col(in0);
- fdct16_1d_8col(in1);
+void fdct16_sse2(__m128i *in0, __m128i *in1) {
+ fdct16_8col(in0);
+ fdct16_8col(in1);
array_transpose_16x16(in0, in1);
}
-void fadst16_1d_sse2(__m128i *in0, __m128i *in1) {
- fadst16_1d_8col(in0);
- fadst16_1d_8col(in1);
+void fadst16_sse2(__m128i *in0, __m128i *in1) {
+ fadst16_8col(in0);
+ fadst16_8col(in1);
array_transpose_16x16(in0, in1);
}
@@ -2538,24 +2538,24 @@
load_buffer_16x16(input, in0, in1, stride);
switch (tx_type) {
case 0: // DCT_DCT
- fdct16_1d_sse2(in0, in1);
+ fdct16_sse2(in0, in1);
right_shift_16x16(in0, in1);
- fdct16_1d_sse2(in0, in1);
+ fdct16_sse2(in0, in1);
break;
case 1: // ADST_DCT
- fadst16_1d_sse2(in0, in1);
+ fadst16_sse2(in0, in1);
right_shift_16x16(in0, in1);
- fdct16_1d_sse2(in0, in1);
+ fdct16_sse2(in0, in1);
break;
case 2: // DCT_ADST
- fdct16_1d_sse2(in0, in1);
+ fdct16_sse2(in0, in1);
right_shift_16x16(in0, in1);
- fadst16_1d_sse2(in0, in1);
+ fadst16_sse2(in0, in1);
break;
case 3: // ADST_ADST
- fadst16_1d_sse2(in0, in1);
+ fadst16_sse2(in0, in1);
right_shift_16x16(in0, in1);
- fadst16_1d_sse2(in0, in1);
+ fadst16_sse2(in0, in1);
break;
default:
assert(0);
diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk
index b1c029c..c691411 100644
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -14,6 +14,7 @@
VP9_COMMON_SRCS-yes += common/vp9_ppflags.h
VP9_COMMON_SRCS-yes += common/vp9_onyx.h
VP9_COMMON_SRCS-yes += common/vp9_alloccommon.c
+VP9_COMMON_SRCS-yes += common/vp9_blockd.c
VP9_COMMON_SRCS-yes += common/vp9_convolve.c
VP9_COMMON_SRCS-yes += common/vp9_convolve.h
VP9_COMMON_SRCS-yes += common/vp9_debugmodes.c
@@ -73,6 +74,7 @@
VP9_COMMON_SRCS-$(CONFIG_VP9_POSTPROC) += common/vp9_postproc.c
VP9_COMMON_SRCS-$(HAVE_MMX) += common/x86/vp9_loopfilter_mmx.asm
VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_subpixel_8t_sse2.asm
+VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_subpixel_bilinear_sse2.asm
VP9_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/vp9_subpixel_8t_ssse3.asm
ifeq ($(CONFIG_VP9_POSTPROC),yes)
VP9_COMMON_SRCS-$(HAVE_MMX) += common/x86/vp9_postproc_mmx.asm
@@ -123,16 +125,16 @@
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_loopfilter_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_loopfilter_16_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_dc_only_idct_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct4x4_1_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct4x4_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct8x8_1_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct8x8_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct16x16_1_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct16x16_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct32x32_1_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct32x32_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_iht4x4_add_neon$(ASM)
-VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_iht8x8_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct4x4_1_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct4x4_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct8x8_1_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct8x8_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct16x16_1_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct16x16_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct32x32_1_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_idct32x32_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_iht4x4_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_iht8x8_add_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_mb_lpf_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_copy_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_avg_neon$(ASM)
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 897ecd7..35d2020 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -316,9 +316,6 @@
// oxcf->kf_min_dist = cfg.kf_min_dis;
oxcf->key_freq = cfg.kf_max_dist;
- // oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
- // strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
-
oxcf->cpu_used = vp8_cfg.cpu_used;
oxcf->encode_breakout = vp8_cfg.static_thresh;
oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
@@ -352,7 +349,6 @@
printf("sharpness: %d\n", oxcf->sharpness);
printf("cpu_used: %d\n", oxcf->cpu_used);
printf("Mode: %d\n", oxcf->mode);
- // printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file);
printf("auto_key: %d\n", oxcf->auto_key);
printf("key_freq: %d\n", oxcf->key_freq);
printf("end_usage: %d\n", oxcf->end_usage);
@@ -563,10 +559,21 @@
unsigned int new_qc;
/* Use best quality mode if no deadline is given. */
- if (deadline)
- new_qc = MODE_GOODQUALITY;
- else
- new_qc = MODE_BESTQUALITY;
+ new_qc = MODE_BESTQUALITY;
+
+ if (deadline) {
+ uint64_t duration_us;
+
+ /* Convert duration parameter from stream timebase to microseconds */
+ duration_us = (uint64_t)duration * 1000000
+ * (uint64_t)ctx->cfg.g_timebase.num
+ / (uint64_t)ctx->cfg.g_timebase.den;
+
+ /* If the deadline is more that the duration this frame is to be shown,
+ * use good quality mode. Otherwise use realtime mode.
+ */
+ new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
+ }
if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
new_qc = MODE_FIRSTPASS;
@@ -1121,7 +1128,6 @@
VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
- 1, /* g_delete_first_pass_file */
"vp8.fpf" /* first pass filename */
#endif
}
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index 63003b9..131d6c7 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -66,7 +66,7 @@
VP9_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/vp9_ssim.c
VP9_CX_SRCS-yes += encoder/vp9_tokenize.c
VP9_CX_SRCS-yes += encoder/vp9_treewriter.c
-VP9_CX_SRCS-yes += encoder/vp9_variance_c.c
+VP9_CX_SRCS-yes += encoder/vp9_variance.c
VP9_CX_SRCS-yes += encoder/vp9_vaq.c
VP9_CX_SRCS-yes += encoder/vp9_vaq.h
ifeq ($(CONFIG_VP9_POSTPROC),yes)
diff --git a/vp9/vp9dx.mk b/vp9/vp9dx.mk
index b722200..de210f4 100644
--- a/vp9/vp9dx.mk
+++ b/vp9/vp9dx.mk
@@ -21,6 +21,8 @@
VP9_DX_SRCS-yes += decoder/vp9_decodeframe.c
VP9_DX_SRCS-yes += decoder/vp9_decodeframe.h
VP9_DX_SRCS-yes += decoder/vp9_detokenize.c
+VP9_DX_SRCS-yes += decoder/vp9_dthread.c
+VP9_DX_SRCS-yes += decoder/vp9_dthread.h
VP9_DX_SRCS-yes += decoder/vp9_reader.h
VP9_DX_SRCS-yes += decoder/vp9_reader.c
VP9_DX_SRCS-yes += decoder/vp9_read_bit_buffer.h
diff --git a/vp9_spatial_scalable_encoder.c b/vp9_spatial_scalable_encoder.c
index b637331..50f45c2 100644
--- a/vp9_spatial_scalable_encoder.c
+++ b/vp9_spatial_scalable_encoder.c
@@ -89,14 +89,6 @@
exit(EXIT_FAILURE);
}
-static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
- const char *detail = vpx_codec_error_detail(ctx);
-
- printf("%s: %s\n", s, vpx_codec_error(ctx));
- if (detail) printf(" %s\n", detail);
- exit(EXIT_FAILURE);
-}
-
static void parse_command_line(int argc, const char **argv_,
AppInput *app_input, SvcContext *svc_ctx,
vpx_codec_enc_cfg_t *enc_cfg) {
@@ -201,8 +193,6 @@
vpx_codec_err_t res;
int pts = 0; /* PTS starts at 0 */
int frame_duration = 1; /* 1 timebase tick per frame */
- vpx_codec_cx_pkt_t packet = {0};
- packet.kind = VPX_CODEC_CX_FRAME_PKT;
memset(&svc_ctx, 0, sizeof(svc_ctx));
svc_ctx.log_print = 1;
@@ -242,9 +232,7 @@
die_codec(&codec, "Failed to encode frame");
}
if (vpx_svc_get_frame_size(&svc_ctx) > 0) {
- packet.data.frame.pts = pts;
- packet.data.frame.sz = vpx_svc_get_frame_size(&svc_ctx);
- ivf_write_frame_header(outfile, &packet);
+ ivf_write_frame_header(outfile, pts, vpx_svc_get_frame_size(&svc_ctx));
(void)fwrite(vpx_svc_get_buffer(&svc_ctx), 1,
vpx_svc_get_frame_size(&svc_ctx), outfile);
}
diff --git a/vpxdec.c b/vpxdec.c
index 2a79665..98d1550 100644
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -39,7 +39,7 @@
static const struct {
char const *name;
- const vpx_codec_iface_t *(*iface)(void);
+ vpx_codec_iface_t *(*iface)(void);
uint32_t fourcc;
} ifaces[] = {
#if CONFIG_VP8_DECODER
@@ -187,8 +187,8 @@
if (!feof(infile))
warn("Failed to read RAW frame size\n");
} else {
- const int kCorruptFrameThreshold = 256 * 1024 * 1024;
- const int kFrameTooSmallThreshold = 256 * 1024;
+ const size_t kCorruptFrameThreshold = 256 * 1024 * 1024;
+ const size_t kFrameTooSmallThreshold = 256 * 1024;
frame_size = mem_get_le32(raw_hdr);
if (frame_size > kCorruptFrameThreshold) {
@@ -816,17 +816,34 @@
}
if (single_file) {
+ if (use_y4m) {
+ char buf[Y4M_BUFFER_SIZE] = {0};
+ size_t len = 0;
+ if (frame_out == 1) {
+ // Y4M file header
+ len = y4m_write_file_header(buf, sizeof(buf),
+ vpx_input_ctx.width,
+ vpx_input_ctx.height,
+ &vpx_input_ctx.framerate, img->fmt);
+ if (do_md5) {
+ MD5Update(&md5_ctx, (md5byte *)buf, len);
+ } else {
+ fputs(buf, outfile);
+ }
+ }
+
+ // Y4M frame header
+ len = y4m_write_frame_header(buf, sizeof(buf));
+ if (do_md5) {
+ MD5Update(&md5_ctx, (md5byte *)buf, len);
+ } else {
+ fputs(buf, outfile);
+ }
+ }
+
if (do_md5) {
update_image_md5(img, planes, &md5_ctx);
} else {
- if (use_y4m) {
- if (frame_out == 1) {
- y4m_write_file_header(outfile,
- vpx_input_ctx.width, vpx_input_ctx.height,
- &vpx_input_ctx.framerate, img->fmt);
- }
- y4m_write_frame_header(outfile);
- }
write_image_file(img, planes, outfile);
}
} else {
diff --git a/vpxenc.c b/vpxenc.c
index f19300a..cf3831c 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -38,6 +38,7 @@
#include "./tools_common.h"
#include "vpx_ports/mem_ops.h"
#include "vpx_ports/vpx_timer.h"
+#include "./rate_hist.h"
#include "./vpxstats.h"
#include "./warnings.h"
#include "./webmenc.h"
@@ -61,8 +62,8 @@
static const struct codec_item {
char const *name;
- const vpx_codec_iface_t *(*iface)(void);
- const vpx_codec_iface_t *(*dx_iface)(void);
+ vpx_codec_iface_t *(*iface)(void);
+ vpx_codec_iface_t *(*dx_iface)(void);
unsigned int fourcc;
} codecs[] = {
#if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
@@ -472,292 +473,27 @@
exit(EXIT_FAILURE);
}
-
-#define HIST_BAR_MAX 40
-struct hist_bucket {
- int low, high, count;
-};
-
-
-static int merge_hist_buckets(struct hist_bucket *bucket,
- int *buckets_,
- int max_buckets) {
- int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
- int buckets = *buckets_;
- int i;
-
- /* Find the extrema for this list of buckets */
- big_bucket = small_bucket = 0;
- for (i = 0; i < buckets; i++) {
- if (bucket[i].count < bucket[small_bucket].count)
- small_bucket = i;
- if (bucket[i].count > bucket[big_bucket].count)
- big_bucket = i;
- }
-
- /* If we have too many buckets, merge the smallest with an adjacent
- * bucket.
- */
- while (buckets > max_buckets) {
- int last_bucket = buckets - 1;
-
- /* merge the small bucket with an adjacent one. */
- if (small_bucket == 0)
- merge_bucket = 1;
- else if (small_bucket == last_bucket)
- merge_bucket = last_bucket - 1;
- else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
- merge_bucket = small_bucket - 1;
- else
- merge_bucket = small_bucket + 1;
-
- assert(abs(merge_bucket - small_bucket) <= 1);
- assert(small_bucket < buckets);
- assert(big_bucket < buckets);
- assert(merge_bucket < buckets);
-
- if (merge_bucket < small_bucket) {
- bucket[merge_bucket].high = bucket[small_bucket].high;
- bucket[merge_bucket].count += bucket[small_bucket].count;
- } else {
- bucket[small_bucket].high = bucket[merge_bucket].high;
- bucket[small_bucket].count += bucket[merge_bucket].count;
- merge_bucket = small_bucket;
- }
-
- assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
-
- buckets--;
-
- /* Remove the merge_bucket from the list, and find the new small
- * and big buckets while we're at it
- */
- big_bucket = small_bucket = 0;
- for (i = 0; i < buckets; i++) {
- if (i > merge_bucket)
- bucket[i] = bucket[i + 1];
-
- if (bucket[i].count < bucket[small_bucket].count)
- small_bucket = i;
- if (bucket[i].count > bucket[big_bucket].count)
- big_bucket = i;
- }
-
- }
-
- *buckets_ = buckets;
- return bucket[big_bucket].count;
-}
-
-
-static void show_histogram(const struct hist_bucket *bucket,
- int buckets,
- int total,
- int scale) {
- const char *pat1, *pat2;
- int i;
-
- switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) {
- case 1:
- case 2:
- pat1 = "%4d %2s: ";
- pat2 = "%4d-%2d: ";
- break;
- case 3:
- pat1 = "%5d %3s: ";
- pat2 = "%5d-%3d: ";
- break;
- case 4:
- pat1 = "%6d %4s: ";
- pat2 = "%6d-%4d: ";
- break;
- case 5:
- pat1 = "%7d %5s: ";
- pat2 = "%7d-%5d: ";
- break;
- case 6:
- pat1 = "%8d %6s: ";
- pat2 = "%8d-%6d: ";
- break;
- case 7:
- pat1 = "%9d %7s: ";
- pat2 = "%9d-%7d: ";
- break;
- default:
- pat1 = "%12d %10s: ";
- pat2 = "%12d-%10d: ";
- break;
- }
-
- for (i = 0; i < buckets; i++) {
- int len;
- int j;
- float pct;
-
- pct = (float)(100.0 * bucket[i].count / total);
- len = HIST_BAR_MAX * bucket[i].count / scale;
- if (len < 1)
- len = 1;
- assert(len <= HIST_BAR_MAX);
-
- if (bucket[i].low == bucket[i].high)
- fprintf(stderr, pat1, bucket[i].low, "");
- else
- fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
-
- for (j = 0; j < HIST_BAR_MAX; j++)
- fprintf(stderr, j < len ? "=" : " ");
- fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
- }
-}
-
-
-static void show_q_histogram(const int counts[64], int max_buckets) {
- struct hist_bucket bucket[64];
- int buckets = 0;
- int total = 0;
- int scale;
- int i;
-
-
- for (i = 0; i < 64; i++) {
- if (counts[i]) {
- bucket[buckets].low = bucket[buckets].high = i;
- bucket[buckets].count = counts[i];
- buckets++;
- total += counts[i];
- }
- }
-
- fprintf(stderr, "\nQuantizer Selection:\n");
- scale = merge_hist_buckets(bucket, &buckets, max_buckets);
- show_histogram(bucket, buckets, total, scale);
-}
-
-
-#define RATE_BINS (100)
-struct rate_hist {
- int64_t *pts;
- int *sz;
- int samples;
- int frames;
- struct hist_bucket bucket[RATE_BINS];
- int total;
-};
-
-
-static void init_rate_histogram(struct rate_hist *hist,
- const vpx_codec_enc_cfg_t *cfg,
- const vpx_rational_t *fps) {
- int i;
-
- /* Determine the number of samples in the buffer. Use the file's framerate
- * to determine the number of frames in rc_buf_sz milliseconds, with an
- * adjustment (5/4) to account for alt-refs
- */
- hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
-
- /* prevent division by zero */
- if (hist->samples == 0)
- hist->samples = 1;
-
- hist->pts = calloc(hist->samples, sizeof(*hist->pts));
- hist->sz = calloc(hist->samples, sizeof(*hist->sz));
- for (i = 0; i < RATE_BINS; i++) {
- hist->bucket[i].low = INT_MAX;
- hist->bucket[i].high = 0;
- hist->bucket[i].count = 0;
- }
-}
-
-
-static void destroy_rate_histogram(struct rate_hist *hist) {
- free(hist->pts);
- free(hist->sz);
-}
-
-
-static void update_rate_histogram(struct rate_hist *hist,
- const vpx_codec_enc_cfg_t *cfg,
- const vpx_codec_cx_pkt_t *pkt) {
- int i, idx;
- int64_t now, then, sum_sz = 0, avg_bitrate;
-
- now = pkt->data.frame.pts * 1000
- * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
-
- idx = hist->frames++ % hist->samples;
- hist->pts[idx] = now;
- hist->sz[idx] = (int)pkt->data.frame.sz;
-
- if (now < cfg->rc_buf_initial_sz)
- return;
-
- then = now;
-
- /* Sum the size over the past rc_buf_sz ms */
- for (i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--) {
- int i_idx = (i - 1) % hist->samples;
-
- then = hist->pts[i_idx];
- if (now - then > cfg->rc_buf_sz)
- break;
- sum_sz += hist->sz[i_idx];
- }
-
- if (now == then)
- return;
-
- avg_bitrate = sum_sz * 8 * 1000 / (now - then);
- idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000));
- if (idx < 0)
- idx = 0;
- if (idx > RATE_BINS - 1)
- idx = RATE_BINS - 1;
- if (hist->bucket[idx].low > avg_bitrate)
- hist->bucket[idx].low = (int)avg_bitrate;
- if (hist->bucket[idx].high < avg_bitrate)
- hist->bucket[idx].high = (int)avg_bitrate;
- hist->bucket[idx].count++;
- hist->total++;
-}
-
-
-static void show_rate_histogram(struct rate_hist *hist,
- const vpx_codec_enc_cfg_t *cfg,
- int max_buckets) {
- int i, scale;
- int buckets = 0;
-
- for (i = 0; i < RATE_BINS; i++) {
- if (hist->bucket[i].low == INT_MAX)
- continue;
- hist->bucket[buckets++] = hist->bucket[i];
- }
-
- fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
- scale = merge_hist_buckets(hist->bucket, &buckets, max_buckets);
- show_histogram(hist->bucket, buckets, hist->total, scale);
-}
-
#define mmin(a, b) ((a) < (b) ? (a) : (b))
-static void find_mismatch(vpx_image_t *img1, vpx_image_t *img2,
+static void find_mismatch(const vpx_image_t *const img1,
+ const vpx_image_t *const img2,
int yloc[4], int uloc[4], int vloc[4]) {
- const unsigned int bsize = 64;
- const unsigned int bsizey = bsize >> img1->y_chroma_shift;
- const unsigned int bsizex = bsize >> img1->x_chroma_shift;
- const int c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
- const int c_h = (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
- unsigned int match = 1;
- unsigned int i, j;
+ const uint32_t bsize = 64;
+ const uint32_t bsizey = bsize >> img1->y_chroma_shift;
+ const uint32_t bsizex = bsize >> img1->x_chroma_shift;
+ const uint32_t c_w =
+ (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
+ const uint32_t c_h =
+ (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
+ int match = 1;
+ uint32_t i, j;
yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1;
for (i = 0, match = 1; match && i < img1->d_h; i += bsize) {
for (j = 0; match && j < img1->d_w; j += bsize) {
int k, l;
- int si = mmin(i + bsize, img1->d_h) - i;
- int sj = mmin(j + bsize, img1->d_w) - j;
- for (k = 0; match && k < si; k++)
- for (l = 0; match && l < sj; l++) {
+ const int si = mmin(i + bsize, img1->d_h) - i;
+ const int sj = mmin(j + bsize, img1->d_w) - j;
+ for (k = 0; match && k < si; ++k) {
+ for (l = 0; match && l < sj; ++l) {
if (*(img1->planes[VPX_PLANE_Y] +
(i + k) * img1->stride[VPX_PLANE_Y] + j + l) !=
*(img2->planes[VPX_PLANE_Y] +
@@ -772,6 +508,7 @@
break;
}
}
+ }
}
}
@@ -779,10 +516,10 @@
for (i = 0, match = 1; match && i < c_h; i += bsizey) {
for (j = 0; match && j < c_w; j += bsizex) {
int k, l;
- int si = mmin(i + bsizey, c_h - i);
- int sj = mmin(j + bsizex, c_w - j);
- for (k = 0; match && k < si; k++)
- for (l = 0; match && l < sj; l++) {
+ const int si = mmin(i + bsizey, c_h - i);
+ const int sj = mmin(j + bsizex, c_w - j);
+ for (k = 0; match && k < si; ++k) {
+ for (l = 0; match && l < sj; ++l) {
if (*(img1->planes[VPX_PLANE_U] +
(i + k) * img1->stride[VPX_PLANE_U] + j + l) !=
*(img2->planes[VPX_PLANE_U] +
@@ -792,21 +529,22 @@
uloc[2] = *(img1->planes[VPX_PLANE_U] +
(i + k) * img1->stride[VPX_PLANE_U] + j + l);
uloc[3] = *(img2->planes[VPX_PLANE_U] +
- (i + k) * img2->stride[VPX_PLANE_V] + j + l);
+ (i + k) * img2->stride[VPX_PLANE_U] + j + l);
match = 0;
break;
}
}
+ }
}
}
vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1;
for (i = 0, match = 1; match && i < c_h; i += bsizey) {
for (j = 0; match && j < c_w; j += bsizex) {
int k, l;
- int si = mmin(i + bsizey, c_h - i);
- int sj = mmin(j + bsizex, c_w - j);
- for (k = 0; match && k < si; k++)
- for (l = 0; match && l < sj; l++) {
+ const int si = mmin(i + bsizey, c_h - i);
+ const int sj = mmin(j + bsizex, c_w - j);
+ for (k = 0; match && k < si; ++k) {
+ for (l = 0; match && l < sj; ++l) {
if (*(img1->planes[VPX_PLANE_V] +
(i + k) * img1->stride[VPX_PLANE_V] + j + l) !=
*(img2->planes[VPX_PLANE_V] +
@@ -821,34 +559,37 @@
break;
}
}
+ }
}
}
}
-static int compare_img(vpx_image_t *img1, vpx_image_t *img2)
-{
- const int c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
- const int c_h = (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
+static int compare_img(const vpx_image_t *const img1,
+ const vpx_image_t *const img2) {
+ const uint32_t c_w =
+ (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
+ const uint32_t c_h =
+ (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
+ uint32_t i;
int match = 1;
- unsigned int i;
match &= (img1->fmt == img2->fmt);
match &= (img1->d_w == img2->d_w);
match &= (img1->d_h == img2->d_h);
- for (i = 0; i < img1->d_h; i++)
- match &= (memcmp(img1->planes[VPX_PLANE_Y]+i*img1->stride[VPX_PLANE_Y],
- img2->planes[VPX_PLANE_Y]+i*img2->stride[VPX_PLANE_Y],
+ for (i = 0; i < img1->d_h; ++i)
+ match &= (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
+ img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
img1->d_w) == 0);
- for (i = 0; i < c_h; i++)
- match &= (memcmp(img1->planes[VPX_PLANE_U]+i*img1->stride[VPX_PLANE_U],
- img2->planes[VPX_PLANE_U]+i*img2->stride[VPX_PLANE_U],
+ for (i = 0; i < c_h; ++i)
+ match &= (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
+ img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U],
c_w) == 0);
- for (i = 0; i < c_h; i++)
- match &= (memcmp(img1->planes[VPX_PLANE_V]+i*img1->stride[VPX_PLANE_U],
- img2->planes[VPX_PLANE_V]+i*img2->stride[VPX_PLANE_U],
+ for (i = 0; i < c_h; ++i)
+ match &= (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V],
+ img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V],
c_w) == 0);
return match;
@@ -884,7 +625,7 @@
struct stream_state *next;
struct stream_config config;
FILE *file;
- struct rate_hist rate_hist;
+ struct rate_hist *rate_hist;
struct EbmlGlobal ebml;
uint32_t hash;
uint64_t psnr_sse_total;
@@ -1576,7 +1317,7 @@
if (!global->quiet)
fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz);
- update_rate_histogram(&stream->rate_hist, cfg, pkt);
+ update_rate_histogram(stream->rate_hist, cfg, pkt);
if (stream->config.write_webm) {
/* Update the hash */
if (!stream->ebml.debug)
@@ -1590,7 +1331,7 @@
ivf_header_pos = ftello(stream->file);
fsize = pkt->data.frame.sz;
- ivf_write_frame_header(stream->file, pkt);
+ ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize);
} else {
fsize += pkt->data.frame.sz;
@@ -1881,9 +1622,9 @@
: VPX_IMG_FMT_YV12,
input.width, input.height, 32);
- FOREACH_STREAM(init_rate_histogram(&stream->rate_hist,
- &stream->config.cfg,
- &global.framerate));
+ FOREACH_STREAM(stream->rate_hist =
+ init_rate_histogram(&stream->config.cfg,
+ &global.framerate));
}
FOREACH_STREAM(setup_pass(stream, &global, pass));
@@ -2020,10 +1761,10 @@
global.show_q_hist_buckets));
if (global.show_rate_hist_buckets)
- FOREACH_STREAM(show_rate_histogram(&stream->rate_hist,
+ FOREACH_STREAM(show_rate_histogram(stream->rate_hist,
&stream->config.cfg,
global.show_rate_hist_buckets));
- FOREACH_STREAM(destroy_rate_histogram(&stream->rate_hist));
+ FOREACH_STREAM(destroy_rate_histogram(stream->rate_hist));
#if CONFIG_INTERNAL_STATS
/* TODO(jkoleszar): This doesn't belong in this executable. Do it for now,
diff --git a/y4menc.c b/y4menc.c
index 8321b43..8b1c95e 100644
--- a/y4menc.c
+++ b/y4menc.c
@@ -10,21 +10,18 @@
#include "./y4menc.h"
-void y4m_write_file_header(FILE *file, int width, int height,
- const struct VpxRational *framerate,
- vpx_img_fmt_t fmt) {
- const char *color = fmt == VPX_IMG_FMT_444A ? "C444alpha\n" :
- fmt == VPX_IMG_FMT_I444 ? "C444\n" :
- fmt == VPX_IMG_FMT_I422 ? "C422\n" :
- "C420jpeg\n";
+int y4m_write_file_header(char *buf, size_t len, int width, int height,
+ const struct VpxRational *framerate,
+ vpx_img_fmt_t fmt) {
+ const char *const color = fmt == VPX_IMG_FMT_444A ? "C444alpha\n" :
+ fmt == VPX_IMG_FMT_I444 ? "C444\n" :
+ fmt == VPX_IMG_FMT_I422 ? "C422\n" :
+ "C420jpeg\n";
- // Note: We can't output an aspect ratio here because IVF doesn't
- // store one, and neither does VP8.
- // That will have to wait until these tools support WebM natively.*/
- fprintf(file, "YUV4MPEG2 W%u H%u F%u:%u I%c %s", width, height,
- framerate->numerator, framerate->denominator, 'p', color);
+ return snprintf(buf, len, "YUV4MPEG2 W%u H%u F%u:%u I%c %s", width, height,
+ framerate->numerator, framerate->denominator, 'p', color);
}
-void y4m_write_frame_header(FILE *file) {
- fprintf(file, "FRAME\n");
+int y4m_write_frame_header(char *buf, size_t len) {
+ return snprintf(buf, len, "FRAME\n");
}
diff --git a/y4menc.h b/y4menc.h
index 95f7909..0fabf56 100644
--- a/y4menc.h
+++ b/y4menc.h
@@ -11,8 +11,6 @@
#ifndef Y4MENC_H_
#define Y4MENC_H_
-#include <stdio.h>
-
#include "./tools_common.h"
#include "vpx/vpx_decoder.h"
@@ -21,12 +19,12 @@
extern "C" {
#endif
-void y4m_write_file_header(FILE *file, int width, int height,
- const struct VpxRational *framerate,
- vpx_img_fmt_t fmt);
+#define Y4M_BUFFER_SIZE 128
-void y4m_write_frame_header(FILE *file);
-
+int y4m_write_file_header(char *buf, size_t len, int width, int height,
+ const struct VpxRational *framerate,
+ vpx_img_fmt_t fmt);
+int y4m_write_frame_header(char *buf, size_t len);
#ifdef __cplusplus
} // extern "C"