Compare commits

..

1 Commits

Author SHA1 Message Date
wangch
eea111f16a Test gerrit. 2017-12-05 18:07:21 -05:00
259 changed files with 9116 additions and 12474 deletions

View File

@ -1,12 +1,12 @@
--- ---
Language: Cpp Language: Cpp
# BasedOnStyle: Google # BasedOnStyle: Google
# Generated with clang-format 5.0.0 # Generated with clang-format 4.0.1
AccessModifierOffset: -1 AccessModifierOffset: -1
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left AlignEscapedNewlinesLeft: true
AlignOperands: true AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
@ -33,20 +33,14 @@ BraceWrapping:
BeforeCatch: false BeforeCatch: false
BeforeElse: false BeforeElse: false
IndentBraces: false IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 80 ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:' CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
@ -54,11 +48,7 @@ Cpp11BracedListStyle: false
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories: IncludeCategories:
- Regex: '^<.*\.h>' - Regex: '^<.*\.h>'
Priority: 1 Priority: 1
@ -80,7 +70,6 @@ NamespaceIndentation: None
ObjCBlockIndentWidth: 2 ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300 PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120 PenaltyBreakFirstLessLess: 120
@ -90,7 +79,6 @@ PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right PointerAlignment: Right
ReflowComments: true ReflowComments: true
SortIncludes: false SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true

View File

@ -3,7 +3,6 @@ Aex Converse <aconverse@google.com>
Aex Converse <aconverse@google.com> <alex.converse@gmail.com> Aex Converse <aconverse@google.com> <alex.converse@gmail.com>
Alexis Ballier <aballier@gentoo.org> <alexis.ballier@gmail.com> Alexis Ballier <aballier@gentoo.org> <alexis.ballier@gmail.com>
Alpha Lam <hclam@google.com> <hclam@chromium.org> Alpha Lam <hclam@google.com> <hclam@chromium.org>
Chris Cunningham <chcunningham@chromium.org>
Daniele Castagna <dcastagna@chromium.org> <dcastagna@google.com> Daniele Castagna <dcastagna@chromium.org> <dcastagna@google.com>
Deb Mukherjee <debargha@google.com> Deb Mukherjee <debargha@google.com>
Erik Niemeyer <erik.a.niemeyer@intel.com> <erik.a.niemeyer@gmail.com> Erik Niemeyer <erik.a.niemeyer@intel.com> <erik.a.niemeyer@gmail.com>
@ -22,21 +21,18 @@ Marco Paniconi <marpan@google.com>
Marco Paniconi <marpan@google.com> <marpan@chromium.org> Marco Paniconi <marpan@google.com> <marpan@chromium.org>
Pascal Massimino <pascal.massimino@gmail.com> Pascal Massimino <pascal.massimino@gmail.com>
Paul Wilkins <paulwilkins@google.com> Paul Wilkins <paulwilkins@google.com>
Peter Boström <pbos@chromium.org> <pbos@google.com>
Peter de Rivaz <peter.derivaz@gmail.com> Peter de Rivaz <peter.derivaz@gmail.com>
Peter de Rivaz <peter.derivaz@gmail.com> <peter.derivaz@argondesign.com> Peter de Rivaz <peter.derivaz@gmail.com> <peter.derivaz@argondesign.com>
Ralph Giles <giles@xiph.org> <giles@entropywave.com> Ralph Giles <giles@xiph.org> <giles@entropywave.com>
Ralph Giles <giles@xiph.org> <giles@mozilla.com> Ralph Giles <giles@xiph.org> <giles@mozilla.com>
Ronald S. Bultje <rsbultje@gmail.com> <rbultje@google.com> Ronald S. Bultje <rsbultje@gmail.com> <rbultje@google.com>
Sami Pietilä <samipietila@google.com> Sami Pietilä <samipietila@google.com>
Shiyou Yin <yinshiyou-hf@loongson.cn>
Tamar Levy <tamar.levy@intel.com> Tamar Levy <tamar.levy@intel.com>
Tamar Levy <tamar.levy@intel.com> <levytamar82@gmail.com> Tamar Levy <tamar.levy@intel.com> <levytamar82@gmail.com>
Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com> Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com>
Timothy B. Terriberry <tterribe@xiph.org> <tterriberry@mozilla.com> Timothy B. Terriberry <tterribe@xiph.org> <tterriberry@mozilla.com>
Tom Finegan <tomfinegan@google.com> Tom Finegan <tomfinegan@google.com>
Tom Finegan <tomfinegan@google.com> <tomfinegan@chromium.org> Tom Finegan <tomfinegan@google.com> <tomfinegan@chromium.org>
Urvang Joshi <urvang@google.com> <urvang@chromium.org>
Yaowu Xu <yaowu@google.com> <adam@xuyaowu.com> Yaowu Xu <yaowu@google.com> <adam@xuyaowu.com>
Yaowu Xu <yaowu@google.com> <yaowu@xuyaowu.com> Yaowu Xu <yaowu@google.com> <yaowu@xuyaowu.com>
Yaowu Xu <yaowu@google.com> <Yaowu Xu> Yaowu Xu <yaowu@google.com> <Yaowu Xu>

16
AUTHORS
View File

@ -3,13 +3,13 @@
Aaron Watry <awatry@gmail.com> Aaron Watry <awatry@gmail.com>
Abo Talib Mahfoodh <ab.mahfoodh@gmail.com> Abo Talib Mahfoodh <ab.mahfoodh@gmail.com>
Adam Xu <adam@xuyaowu.com>
Adrian Grange <agrange@google.com> Adrian Grange <agrange@google.com>
Aex Converse <aconverse@google.com> Aex Converse <aconverse@google.com>
Ahmad Sharif <asharif@google.com> Ahmad Sharif <asharif@google.com>
Aleksey Vasenev <margtu-fivt@ya.ru> Aleksey Vasenev <margtu-fivt@ya.ru>
Alexander Potapenko <glider@google.com> Alexander Potapenko <glider@google.com>
Alexander Voronov <avoronov@graphics.cs.msu.ru> Alexander Voronov <avoronov@graphics.cs.msu.ru>
Alexandra Hájková <alexandra.khirnova@gmail.com>
Alexis Ballier <aballier@gentoo.org> Alexis Ballier <aballier@gentoo.org>
Alok Ahuja <waveletcoeff@gmail.com> Alok Ahuja <waveletcoeff@gmail.com>
Alpha Lam <hclam@google.com> Alpha Lam <hclam@google.com>
@ -17,7 +17,6 @@ A.Mahfoodh <ab.mahfoodh@gmail.com>
Ami Fischman <fischman@chromium.org> Ami Fischman <fischman@chromium.org>
Andoni Morales Alastruey <ylatuya@gmail.com> Andoni Morales Alastruey <ylatuya@gmail.com>
Andres Mejia <mcitadel@gmail.com> Andres Mejia <mcitadel@gmail.com>
Andrew Lewis <andrewlewis@google.com>
Andrew Russell <anrussell@google.com> Andrew Russell <anrussell@google.com>
Angie Chiang <angiebird@google.com> Angie Chiang <angiebird@google.com>
Aron Rosenberg <arosenberg@logitech.com> Aron Rosenberg <arosenberg@logitech.com>
@ -25,9 +24,7 @@ Attila Nagy <attilanagy@google.com>
Brion Vibber <bvibber@wikimedia.org> Brion Vibber <bvibber@wikimedia.org>
changjun.yang <changjun.yang@intel.com> changjun.yang <changjun.yang@intel.com>
Charles 'Buck' Krasic <ckrasic@google.com> Charles 'Buck' Krasic <ckrasic@google.com>
Cheng Chen <chengchen@google.com>
chm <chm@rock-chips.com> chm <chm@rock-chips.com>
Chris Cunningham <chcunningham@chromium.org>
Christian Duvivier <cduvivier@google.com> Christian Duvivier <cduvivier@google.com>
Daniele Castagna <dcastagna@chromium.org> Daniele Castagna <dcastagna@chromium.org>
Daniel Kang <ddkang@google.com> Daniel Kang <ddkang@google.com>
@ -49,12 +46,10 @@ Geza Lore <gezalore@gmail.com>
Ghislain MARY <ghislainmary2@gmail.com> Ghislain MARY <ghislainmary2@gmail.com>
Giuseppe Scrivano <gscrivano@gnu.org> Giuseppe Scrivano <gscrivano@gnu.org>
Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com> Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com>
Gregor Jasny <gjasny@gmail.com>
Guillaume Martres <gmartres@google.com> Guillaume Martres <gmartres@google.com>
Guillermo Ballester Valor <gbvalor@gmail.com> Guillermo Ballester Valor <gbvalor@gmail.com>
Hangyu Kuang <hkuang@google.com> Hangyu Kuang <hkuang@google.com>
Hanno Böck <hanno@hboeck.de> Hanno Böck <hanno@hboeck.de>
Han Shen <shenhan@google.com>
Henrik Lundin <hlundin@google.com> Henrik Lundin <hlundin@google.com>
Hui Su <huisu@google.com> Hui Su <huisu@google.com>
Ivan Krasin <krasin@chromium.org> Ivan Krasin <krasin@chromium.org>
@ -88,7 +83,6 @@ Justin Clift <justin@salasaga.org>
Justin Lebar <justin.lebar@gmail.com> Justin Lebar <justin.lebar@gmail.com>
Kaustubh Raste <kaustubh.raste@imgtec.com> Kaustubh Raste <kaustubh.raste@imgtec.com>
KO Myung-Hun <komh@chollian.net> KO Myung-Hun <komh@chollian.net>
Kyle Siefring <kylesiefring@gmail.com>
Lawrence Velázquez <larryv@macports.org> Lawrence Velázquez <larryv@macports.org>
Linfeng Zhang <linfengz@google.com> Linfeng Zhang <linfengz@google.com>
Lou Quillio <louquillio@google.com> Lou Quillio <louquillio@google.com>
@ -107,7 +101,6 @@ Mikhal Shemer <mikhal@google.com>
Min Chen <chenm003@gmail.com> Min Chen <chenm003@gmail.com>
Minghai Shang <minghai@google.com> Minghai Shang <minghai@google.com>
Min Ye <yeemmi@google.com> Min Ye <yeemmi@google.com>
Moriyoshi Koizumi <mozo@mozo.jp>
Morton Jonuschat <yabawock@gmail.com> Morton Jonuschat <yabawock@gmail.com>
Nathan E. Egge <negge@mozilla.com> Nathan E. Egge <negge@mozilla.com>
Nico Weber <thakis@chromium.org> Nico Weber <thakis@chromium.org>
@ -118,15 +111,12 @@ Paul Wilkins <paulwilkins@google.com>
Pavol Rusnak <stick@gk2.sk> Pavol Rusnak <stick@gk2.sk>
Paweł Hajdan <phajdan@google.com> Paweł Hajdan <phajdan@google.com>
Pengchong Jin <pengchong@google.com> Pengchong Jin <pengchong@google.com>
Peter Boström <pbos@chromium.org> Peter Boström <pbos@google.com>
Peter Collingbourne <pcc@chromium.org>
Peter de Rivaz <peter.derivaz@gmail.com> Peter de Rivaz <peter.derivaz@gmail.com>
Philip Jägenstedt <philipj@opera.com> Philip Jägenstedt <philipj@opera.com>
Priit Laes <plaes@plaes.org> Priit Laes <plaes@plaes.org>
Rafael Ávila de Espíndola <rafael.espindola@gmail.com> Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
Rafaël Carré <funman@videolan.org> Rafaël Carré <funman@videolan.org>
Rafael de Lucena Valle <rafaeldelucena@gmail.com>
Rahul Chaudhry <rahulchaudhry@google.com>
Ralph Giles <giles@xiph.org> Ralph Giles <giles@xiph.org>
Ranjit Kumar Tulabandu <ranjit.tulabandu@ittiam.com> Ranjit Kumar Tulabandu <ranjit.tulabandu@ittiam.com>
Rob Bradford <rob@linux.intel.com> Rob Bradford <rob@linux.intel.com>
@ -145,7 +135,6 @@ Shiyou Yin <yinshiyou-hf@loongson.cn>
Shunyao Li <shunyaoli@google.com> Shunyao Li <shunyaoli@google.com>
Stefan Holmer <holmer@google.com> Stefan Holmer <holmer@google.com>
Suman Sunkara <sunkaras@google.com> Suman Sunkara <sunkaras@google.com>
Sylvestre Ledru <sylvestre@mozilla.com>
Taekhyun Kim <takim@nvidia.com> Taekhyun Kim <takim@nvidia.com>
Takanori MATSUURA <t.matsuu@gmail.com> Takanori MATSUURA <t.matsuu@gmail.com>
Tamar Levy <tamar.levy@intel.com> Tamar Levy <tamar.levy@intel.com>
@ -158,7 +147,6 @@ Tom Finegan <tomfinegan@google.com>
Tristan Matthews <le.businessman@gmail.com> Tristan Matthews <le.businessman@gmail.com>
Urvang Joshi <urvang@google.com> Urvang Joshi <urvang@google.com>
Vignesh Venkatasubramanian <vigneshv@google.com> Vignesh Venkatasubramanian <vigneshv@google.com>
Vlad Tsyrklevich <vtsyrklevich@chromium.org>
Yaowu Xu <yaowu@google.com> Yaowu Xu <yaowu@google.com>
Yi Luo <luoyi@google.com> Yi Luo <luoyi@google.com>
Yongzhe Wang <yongzhe@google.com> Yongzhe Wang <yongzhe@google.com>

View File

@ -1,28 +1,3 @@
2017-01-04 v1.7.0 "Mandarin Duck"
This release focused on high bit depth performance (10/12 bit) and vp9
encoding improvements.
- Upgrading:
This release is ABI incompatible due to new vp9 encoder features.
Frame parallel decoding for vp9 has been removed.
- Enhancements:
vp9 encoding supports additional threads with --row-mt. This can be greater
than the number of tiles.
Two new vp9 encoder options have been added:
--corpus-complexity
--tune-content=film
Additional tooling for respecting the vp9 "level" profiles has been added.
- Bug fixes:
A variety of fuzzing issues.
vp8 threading fix for ARM.
Codec control VP9_SET_SKIP_LOOP_FILTER fixed.
Reject invalid multi resolution configurations.
2017-01-09 v1.6.1 "Long Tailed Duck" 2017-01-09 v1.6.1 "Long Tailed Duck"
This release improves upon the VP9 encoder and speeds up the encoding and This release improves upon the VP9 encoder and speeds up the encoding and
decoding processes. decoding processes.

39
README
View File

@ -1,4 +1,4 @@
README - 24 January 2018 README - 26 January 2017
Welcome to the WebM VP8/VP9 Codec SDK! Welcome to the WebM VP8/VP9 Codec SDK!
@ -9,26 +9,22 @@ COMPILING THE APPLICATIONS/LIBRARIES:
1. Prerequisites 1. Prerequisites
* All x86 targets require the Yasm[1] assembler be installed[2]. * All x86 targets require the Yasm[1] assembler be installed.
* All Windows builds require that Cygwin[3] be installed. * All Windows builds require that Cygwin[2] be installed.
* Building the documentation requires Doxygen[4]. If you do not * Building the documentation requires Doxygen[3]. If you do not
have this package, the install-docs option will be disabled. have this package, the install-docs option will be disabled.
* Downloading the data for the unit tests requires curl[5] and sha1sum. * Downloading the data for the unit tests requires curl[4] and sha1sum.
sha1sum is provided via the GNU coreutils, installed by default on sha1sum is provided via the GNU coreutils, installed by default on
many *nix platforms, as well as MinGW and Cygwin. If coreutils is not many *nix platforms, as well as MinGW and Cygwin. If coreutils is not
available, a compatible version of sha1sum can be built from available, a compatible version of sha1sum can be built from
source[6]. These requirements are optional if not running the unit source[5]. These requirements are optional if not running the unit
tests. tests.
[1]: http://www.tortall.net/projects/yasm [1]: http://www.tortall.net/projects/yasm
[2]: For Visual Studio the base yasm binary (not vsyasm) should be in the [2]: http://www.cygwin.com
PATH for Visual Studio. For VS2017 it is sufficient to rename [3]: http://www.doxygen.org
yasm-<version>-<arch>.exe to yasm.exe and place it in: [4]: http://curl.haxx.se
Program Files (x86)/Microsoft Visual Studio/2017/<level>/Common7/Tools/ [5]: http://www.microbrew.org/tools/md5sha1sum/
[3]: http://www.cygwin.com
[4]: http://www.doxygen.org
[5]: http://curl.haxx.se
[6]: http://www.microbrew.org/tools/md5sha1sum/
2. Out-of-tree builds 2. Out-of-tree builds
Out of tree builds are a supported method of building the application. For Out of tree builds are a supported method of building the application. For
@ -45,16 +41,7 @@ COMPILING THE APPLICATIONS/LIBRARIES:
used to get a list of supported options: used to get a list of supported options:
$ ../libvpx/configure --help $ ../libvpx/configure --help
4. Compiler analyzers 4. Cross development
Compilers have added sanitizers which instrument binaries with information
about address calculation, memory usage, threading, undefined behavior, and
other common errors. To simplify building libvpx with some of these features
use tools/set_analyzer_env.sh before running configure. It will set the
compiler and necessary flags for building as well as environment variables
read by the analyzer when testing the binaries.
$ source ../libvpx/tools/set_analyzer_env.sh address
5. Cross development
For cross development, the most notable option is the --target option. The For cross development, the most notable option is the --target option. The
most up-to-date list of supported targets can be found at the bottom of the most up-to-date list of supported targets can be found at the bottom of the
--help output of the configure script. As of this writing, the list of --help output of the configure script. As of this writing, the list of
@ -76,8 +63,6 @@ COMPILING THE APPLICATIONS/LIBRARIES:
armv8-linux-gcc armv8-linux-gcc
mips32-linux-gcc mips32-linux-gcc
mips64-linux-gcc mips64-linux-gcc
ppc64-linux-gcc
ppc64le-linux-gcc
sparc-solaris-gcc sparc-solaris-gcc
x86-android-gcc x86-android-gcc
x86-darwin8-gcc x86-darwin8-gcc
@ -136,7 +121,7 @@ COMPILING THE APPLICATIONS/LIBRARIES:
environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be
passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS. passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS.
6. Configuration errors 5. Configuration errors
If the configuration step fails, the first step is to look in the error log. If the configuration step fails, the first step is to look in the error log.
This defaults to config.log. This should give a good indication of what went This defaults to config.log. This should give a good indication of what went
wrong. If not, contact us for support. wrong. If not, contact us for support.

2
build/.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*-vs8/*.rules -crlf
*-msvs/*.rules -crlf

1
build/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
x86*-win32-vs*

View File

@ -23,11 +23,9 @@ use lib $FindBin::Bin;
use thumb; use thumb;
my $thumb = 0; my $thumb = 0;
my $elf = 1;
foreach my $arg (@ARGV) { foreach my $arg (@ARGV) {
$thumb = 1 if ($arg eq "-thumb"); $thumb = 1 if ($arg eq "-thumb");
$elf = 0 if ($arg eq "-noelf");
} }
print "@ This file was created from a .asm file\n"; print "@ This file was created from a .asm file\n";
@ -142,11 +140,7 @@ while (<STDIN>)
# Make function visible to linker, and make additional symbol with # Make function visible to linker, and make additional symbol with
# prepended underscore # prepended underscore
if ($elf) { s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
} else {
s/EXPORT\s+\|([\$\w]*)\|/.global $1/;
}
s/IMPORT\s+\|([\$\w]*)\|/.global $1/; s/IMPORT\s+\|([\$\w]*)\|/.global $1/;
s/EXPORT\s+([\$\w]*)/.global $1/; s/EXPORT\s+([\$\w]*)/.global $1/;
@ -187,16 +181,11 @@ while (<STDIN>)
# eabi_attributes numerical equivalents can be found in the # eabi_attributes numerical equivalents can be found in the
# "ARM IHI 0045C" document. # "ARM IHI 0045C" document.
if ($elf) { # REQUIRE8 Stack is required to be 8-byte aligned
# REQUIRE8 Stack is required to be 8-byte aligned s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
# PRESERVE8 Stack 8-byte align is preserved # PRESERVE8 Stack 8-byte align is preserved
s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g; s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
} else {
s/\sREQUIRE8//;
s/\sPRESERVE8//;
}
# Use PROC and ENDP to give the symbols a .size directive. # Use PROC and ENDP to give the symbols a .size directive.
# This makes them show up properly in debugging tools like gdb and valgrind. # This makes them show up properly in debugging tools like gdb and valgrind.
@ -213,7 +202,7 @@ while (<STDIN>)
my $proc; my $proc;
s/\bENDP\b/@ $&/; s/\bENDP\b/@ $&/;
$proc = pop(@proc_stack); $proc = pop(@proc_stack);
$_ = "\t.size $proc, .-$proc".$_ if ($proc and $elf); $_ = "\t.size $proc, .-$proc".$_ if ($proc);
} }
# EQU directive # EQU directive
@ -236,4 +225,4 @@ while (<STDIN>)
} }
# Mark that this object doesn't need an executable stack. # Mark that this object doesn't need an executable stack.
printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n") if $elf; printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n");

View File

@ -757,10 +757,6 @@ process_common_toolchain() {
tgt_isa=x86_64 tgt_isa=x86_64
tgt_os=darwin16 tgt_os=darwin16
;; ;;
*darwin17*)
tgt_isa=x86_64
tgt_os=darwin17
;;
x86_64*mingw32*) x86_64*mingw32*)
tgt_os=win64 tgt_os=win64
;; ;;
@ -889,10 +885,6 @@ process_common_toolchain() {
add_cflags "-mmacosx-version-min=10.12" add_cflags "-mmacosx-version-min=10.12"
add_ldflags "-mmacosx-version-min=10.12" add_ldflags "-mmacosx-version-min=10.12"
;; ;;
*-darwin17-*)
add_cflags "-mmacosx-version-min=10.13"
add_ldflags "-mmacosx-version-min=10.13"
;;
*-iphonesimulator-*) *-iphonesimulator-*)
add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}" add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}"
add_ldflags "-miphoneos-version-min=${IOS_VERSION_MIN}" add_ldflags "-miphoneos-version-min=${IOS_VERSION_MIN}"
@ -941,6 +933,7 @@ process_common_toolchain() {
setup_gnu_toolchain setup_gnu_toolchain
arch_int=${tgt_isa##armv} arch_int=${tgt_isa##armv}
arch_int=${arch_int%%te} arch_int=${arch_int%%te}
check_add_asflags --defsym ARCHITECTURE=${arch_int}
tune_cflags="-mtune=" tune_cflags="-mtune="
if [ ${tgt_isa} = "armv7" ] || [ ${tgt_isa} = "armv7s" ]; then if [ ${tgt_isa} = "armv7" ] || [ ${tgt_isa} = "armv7s" ]; then
if [ -z "${float_abi}" ]; then if [ -z "${float_abi}" ]; then
@ -967,19 +960,6 @@ EOF
enabled debug && add_asflags -g enabled debug && add_asflags -g
asm_conversion_cmd="${source_path}/build/make/ads2gas.pl" asm_conversion_cmd="${source_path}/build/make/ads2gas.pl"
case ${tgt_os} in
win*)
asm_conversion_cmd="$asm_conversion_cmd -noelf"
AS="$CC -c"
EXE_SFX=.exe
enable_feature thumb
;;
*)
check_add_asflags --defsym ARCHITECTURE=${arch_int}
;;
esac
if enabled thumb; then if enabled thumb; then
asm_conversion_cmd="$asm_conversion_cmd -thumb" asm_conversion_cmd="$asm_conversion_cmd -thumb"
check_add_cflags -mthumb check_add_cflags -mthumb
@ -1222,9 +1202,6 @@ EOF
;; ;;
x86*) x86*)
case ${tgt_os} in case ${tgt_os} in
android)
soft_enable realtime_only
;;
win*) win*)
enabled gcc && add_cflags -fno-common enabled gcc && add_cflags -fno-common
;; ;;
@ -1394,8 +1371,7 @@ EOF
add_cflags ${sim_arch} add_cflags ${sim_arch}
add_ldflags ${sim_arch} add_ldflags ${sim_arch}
if [ "$(disabled external_build)" ] && if [ "$(show_darwin_sdk_major_version iphonesimulator)" -gt 8 ]; then
[ "$(show_darwin_sdk_major_version iphonesimulator)" -gt 8 ]; then
# yasm v1.3.0 doesn't know what -fembed-bitcode means, so turning it # yasm v1.3.0 doesn't know what -fembed-bitcode means, so turning it
# on is pointless (unless building a C-only lib). Warn the user, but # on is pointless (unless building a C-only lib). Warn the user, but
# do nothing here. # do nothing here.

View File

@ -41,15 +41,6 @@ fix_path() {
# Corrects the paths in file_list in one pass for efficiency. # Corrects the paths in file_list in one pass for efficiency.
# $1 is the name of the array to be modified. # $1 is the name of the array to be modified.
fix_file_list() { fix_file_list() {
if [ "${FIXPATH}" = "echo_path" ] ; then
# When used with echo_path, fix_file_list is a no-op. Avoid warning about
# unsupported 'declare -n' when it is not important.
return 0
elif [ "${BASH_VERSINFO}" -lt 4 ] ; then
echo "Cygwin path conversion has failed. Please use a version of bash"
echo "which supports nameref (-n), introduced in bash 4.3"
return 1
fi
declare -n array_ref=$1 declare -n array_ref=$1
files=$(fix_path "${array_ref[@]}") files=$(fix_path "${array_ref[@]}")
local IFS=$'\n' local IFS=$'\n'

View File

@ -1,13 +1,4 @@
#!/usr/bin/env perl #!/usr/bin/env perl
##
## Copyright (c) 2017 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.
##
no strict 'refs'; no strict 'refs';
use warnings; use warnings;
@ -209,7 +200,6 @@ sub filter {
sub common_top() { sub common_top() {
my $include_guard = uc($opts{sym})."_H_"; my $include_guard = uc($opts{sym})."_H_";
print <<EOF; print <<EOF;
// This file is generated. Do not edit.
#ifndef ${include_guard} #ifndef ${include_guard}
#define ${include_guard} #define ${include_guard}

View File

@ -54,6 +54,13 @@ sub FixThumbInstructions($$)
# "addne r0, r0, r2". # "addne r0, r0, r2".
s/^(\s*)((ldr|str)(ne)?[bhd]?)(\s+)(\w+),(\s*\w+,)?\s*\[(\w+)\],\s*(\w+)/$1$2$5$6,$7 [$8]\n$1add$4$5$8, $8, $9/g; s/^(\s*)((ldr|str)(ne)?[bhd]?)(\s+)(\w+),(\s*\w+,)?\s*\[(\w+)\],\s*(\w+)/$1$2$5$6,$7 [$8]\n$1add$4$5$8, $8, $9/g;
# Convert a conditional addition to the pc register into a series of
# instructions. This converts "addlt pc, pc, r3, lsl #2" into
# "itttt lt", "movlt.n r12, pc", "addlt.w r12, #12",
# "addlt.w r12, r12, r3, lsl #2", "movlt.n pc, r12".
# This assumes that r12 is free at this point.
s/^(\s*)addlt(\s+)pc,\s*pc,\s*(\w+),\s*lsl\s*#(\d+)/$1itttt$2lt\n$1movlt.n$2r12, pc\n$1addlt.w$2r12, #12\n$1addlt.w$2r12, r12, $3, lsl #($4-$branch_shift_offset)\n$1movlt.n$2pc, r12/g;
# Convert "mov pc, lr" into "bx lr", since the former only works # Convert "mov pc, lr" into "bx lr", since the former only works
# for switching from arm to thumb (and only in armv7), but not # for switching from arm to thumb (and only in armv7), but not
# from thumb to arm. # from thumb to arm.

View File

@ -60,7 +60,6 @@ if [ ${bare} ]; then
echo "${changelog_version}${git_version_id}" > $$.tmp echo "${changelog_version}${git_version_id}" > $$.tmp
else else
cat<<EOF>$$.tmp cat<<EOF>$$.tmp
// This file is generated. Do not edit.
#define VERSION_MAJOR $major_version #define VERSION_MAJOR $major_version
#define VERSION_MINOR $minor_version #define VERSION_MINOR $minor_version
#define VERSION_PATCH $patch_version #define VERSION_PATCH $patch_version

View File

@ -1,4 +1,5 @@
# This file is used by git cl to get repository specific information. # This file is used by gcl to get repository specific information.
GERRIT_HOST: True GERRIT_HOST: chromium-review.googlesource.com
GERRIT_PORT: 29418
CODE_REVIEW_SERVER: chromium-review.googlesource.com CODE_REVIEW_SERVER: chromium-review.googlesource.com
GERRIT_SQUASH_UPLOADS: False GERRIT_SQUASH_UPLOADS: False

11
configure vendored
View File

@ -101,13 +101,11 @@ EOF
all_platforms="${all_platforms} arm64-android-gcc" all_platforms="${all_platforms} arm64-android-gcc"
all_platforms="${all_platforms} arm64-darwin-gcc" all_platforms="${all_platforms} arm64-darwin-gcc"
all_platforms="${all_platforms} arm64-linux-gcc" all_platforms="${all_platforms} arm64-linux-gcc"
all_platforms="${all_platforms} arm64-win64-gcc"
all_platforms="${all_platforms} armv7-android-gcc" #neon Cortex-A8 all_platforms="${all_platforms} armv7-android-gcc" #neon Cortex-A8
all_platforms="${all_platforms} armv7-darwin-gcc" #neon Cortex-A8 all_platforms="${all_platforms} armv7-darwin-gcc" #neon Cortex-A8
all_platforms="${all_platforms} armv7-linux-rvct" #neon Cortex-A8 all_platforms="${all_platforms} armv7-linux-rvct" #neon Cortex-A8
all_platforms="${all_platforms} armv7-linux-gcc" #neon Cortex-A8 all_platforms="${all_platforms} armv7-linux-gcc" #neon Cortex-A8
all_platforms="${all_platforms} armv7-none-rvct" #neon Cortex-A8 all_platforms="${all_platforms} armv7-none-rvct" #neon Cortex-A8
all_platforms="${all_platforms} armv7-win32-gcc"
all_platforms="${all_platforms} armv7-win32-vs11" all_platforms="${all_platforms} armv7-win32-vs11"
all_platforms="${all_platforms} armv7-win32-vs12" all_platforms="${all_platforms} armv7-win32-vs12"
all_platforms="${all_platforms} armv7-win32-vs14" all_platforms="${all_platforms} armv7-win32-vs14"
@ -131,7 +129,6 @@ all_platforms="${all_platforms} x86-darwin13-gcc"
all_platforms="${all_platforms} x86-darwin14-gcc" all_platforms="${all_platforms} x86-darwin14-gcc"
all_platforms="${all_platforms} x86-darwin15-gcc" all_platforms="${all_platforms} x86-darwin15-gcc"
all_platforms="${all_platforms} x86-darwin16-gcc" all_platforms="${all_platforms} x86-darwin16-gcc"
all_platforms="${all_platforms} x86-darwin17-gcc"
all_platforms="${all_platforms} x86-iphonesimulator-gcc" all_platforms="${all_platforms} x86-iphonesimulator-gcc"
all_platforms="${all_platforms} x86-linux-gcc" all_platforms="${all_platforms} x86-linux-gcc"
all_platforms="${all_platforms} x86-linux-icc" all_platforms="${all_platforms} x86-linux-icc"
@ -152,7 +149,6 @@ all_platforms="${all_platforms} x86_64-darwin13-gcc"
all_platforms="${all_platforms} x86_64-darwin14-gcc" all_platforms="${all_platforms} x86_64-darwin14-gcc"
all_platforms="${all_platforms} x86_64-darwin15-gcc" all_platforms="${all_platforms} x86_64-darwin15-gcc"
all_platforms="${all_platforms} x86_64-darwin16-gcc" all_platforms="${all_platforms} x86_64-darwin16-gcc"
all_platforms="${all_platforms} x86_64-darwin17-gcc"
all_platforms="${all_platforms} x86_64-iphonesimulator-gcc" all_platforms="${all_platforms} x86_64-iphonesimulator-gcc"
all_platforms="${all_platforms} x86_64-linux-gcc" all_platforms="${all_platforms} x86_64-linux-gcc"
all_platforms="${all_platforms} x86_64-linux-icc" all_platforms="${all_platforms} x86_64-linux-icc"
@ -277,6 +273,7 @@ HAVE_LIST="
unistd_h unistd_h
" "
EXPERIMENT_LIST=" EXPERIMENT_LIST="
spatial_svc
fp_mb_stats fp_mb_stats
emulate_hardware emulate_hardware
" "
@ -609,10 +606,8 @@ process_toolchain() {
# https://bugs.chromium.org/p/webm/issues/detail?id=1069 # https://bugs.chromium.org/p/webm/issues/detail?id=1069
check_add_cflags -Wextra check_add_cflags -Wextra
# check_add_cflags also adds to cxxflags. gtest does not do well with # check_add_cflags also adds to cxxflags. gtest does not do well with
# these flags so add them explicitly to CFLAGS only. # -Wundef so add it explicitly to CFLAGS only.
check_cflags -Wundef && add_cflags_only -Wundef check_cflags -Wundef && add_cflags_only -Wundef
check_cflags -Wframe-larger-than=52000 && \
add_cflags_only -Wframe-larger-than=52000
if enabled mips || [ -z "${INLINE}" ]; then if enabled mips || [ -z "${INLINE}" ]; then
enabled extra_warnings || check_add_cflags -Wno-unused-function enabled extra_warnings || check_add_cflags -Wno-unused-function
fi fi
@ -670,7 +665,7 @@ process_toolchain() {
gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh
enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror" enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror"
all_targets="${all_targets} solution" all_targets="${all_targets} solution"
INLINE="__inline" INLINE="__forceinline"
;; ;;
esac esac

View File

@ -109,17 +109,18 @@ ifeq ($(CONFIG_WEBM_IO),yes)
endif endif
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1 vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
vpxenc.DESCRIPTION = Full featured encoder vpxenc.DESCRIPTION = Full featured encoder
ifeq ($(CONFIG_SPATIAL_SVC),yes)
EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_spatial_svc_encoder.c EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_spatial_svc_encoder.c
vp9_spatial_svc_encoder.SRCS += args.c args.h vp9_spatial_svc_encoder.SRCS += args.c args.h
vp9_spatial_svc_encoder.SRCS += ivfenc.c ivfenc.h vp9_spatial_svc_encoder.SRCS += ivfenc.c ivfenc.h
vp9_spatial_svc_encoder.SRCS += tools_common.c tools_common.h vp9_spatial_svc_encoder.SRCS += tools_common.c tools_common.h
vp9_spatial_svc_encoder.SRCS += video_common.h vp9_spatial_svc_encoder.SRCS += video_common.h
vp9_spatial_svc_encoder.SRCS += video_writer.h video_writer.c vp9_spatial_svc_encoder.SRCS += video_writer.h video_writer.c
vp9_spatial_svc_encoder.SRCS += vpx_ports/msvc.h vp9_spatial_svc_encoder.SRCS += vpx_ports/msvc.h
vp9_spatial_svc_encoder.SRCS += vpxstats.c vpxstats.h vp9_spatial_svc_encoder.SRCS += vpxstats.c vpxstats.h
vp9_spatial_svc_encoder.GUID = 4A38598D-627D-4505-9C7B-D4020C84100D vp9_spatial_svc_encoder.GUID = 4A38598D-627D-4505-9C7B-D4020C84100D
vp9_spatial_svc_encoder.DESCRIPTION = VP9 Spatial SVC Encoder vp9_spatial_svc_encoder.DESCRIPTION = VP9 Spatial SVC Encoder
endif
ifneq ($(CONFIG_SHARED),yes) ifneq ($(CONFIG_SHARED),yes)
EXAMPLES-$(CONFIG_VP9_ENCODER) += resize_util.c EXAMPLES-$(CONFIG_VP9_ENCODER) += resize_util.c

View File

@ -429,9 +429,8 @@ static void set_rate_control_stats(struct RateControlStats *rc,
rc->layer_framerate[layer] = framerate / cfg->ts_rate_decimator[tl]; rc->layer_framerate[layer] = framerate / cfg->ts_rate_decimator[tl];
if (tl > 0) { if (tl > 0) {
rc->layer_pfb[layer] = rc->layer_pfb[layer] =
1000.0 * 1000.0 * (cfg->layer_target_bitrate[layer] -
(cfg->layer_target_bitrate[layer] - cfg->layer_target_bitrate[layer - 1]) /
cfg->layer_target_bitrate[layer - 1]) /
(rc->layer_framerate[layer] - rc->layer_framerate[layer - 1]); (rc->layer_framerate[layer] - rc->layer_framerate[layer - 1]);
} else { } else {
rc->layer_pfb[layer] = 1000.0 * cfg->layer_target_bitrate[layer] / rc->layer_pfb[layer] = 1000.0 * cfg->layer_target_bitrate[layer] /
@ -503,8 +502,10 @@ static void printout_rate_control_summary(struct RateControlStats *rc,
printf("Average, rms-variance, and percent-fluct: %f %f %f \n", printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
rc->avg_st_encoding_bitrate, sqrt(rc->variance_st_encoding_bitrate), rc->avg_st_encoding_bitrate, sqrt(rc->variance_st_encoding_bitrate),
perc_fluctuation); perc_fluctuation);
printf("Num of input, num of encoded (super) frames: %d %d \n", frame_cnt, if (frame_cnt != tot_num_frames)
tot_num_frames); die("Error: Number of input frames not equal to output encoded frames != "
"%d tot_num_frames = %d\n",
frame_cnt, tot_num_frames);
} }
vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz, vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
@ -560,10 +561,9 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
// bypass/flexible mode. The pattern corresponds to the pattern // bypass/flexible mode. The pattern corresponds to the pattern
// VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in // VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
// non-flexible mode. // non-flexible mode.
void set_frame_flags_bypass_mode(int tl, int num_spatial_layers, void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers,
int is_key_frame, int is_key_frame,
vpx_svc_ref_frame_config_t *ref_frame_config) { vpx_svc_ref_frame_config_t *ref_frame_config) {
int sl;
for (sl = 0; sl < num_spatial_layers; ++sl) { for (sl = 0; sl < num_spatial_layers; ++sl) {
if (!tl) { if (!tl) {
if (!sl) { if (!sl) {
@ -573,8 +573,8 @@ void set_frame_flags_bypass_mode(int tl, int num_spatial_layers,
} else { } else {
if (is_key_frame) { if (is_key_frame) {
ref_frame_config->frame_flags[sl] = ref_frame_config->frame_flags[sl] =
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
} else { } else {
ref_frame_config->frame_flags[sl] = ref_frame_config->frame_flags[sl] =
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
@ -588,24 +588,14 @@ void set_frame_flags_bypass_mode(int tl, int num_spatial_layers,
} else { } else {
ref_frame_config->frame_flags[sl] = ref_frame_config->frame_flags[sl] =
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
if (sl == num_spatial_layers - 1)
ref_frame_config->frame_flags[sl] =
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
} }
} }
if (tl == 0) { if (tl == 0) {
ref_frame_config->lst_fb_idx[sl] = sl; ref_frame_config->lst_fb_idx[sl] = sl;
if (sl) { if (sl)
if (is_key_frame) { ref_frame_config->gld_fb_idx[sl] = sl - 1;
ref_frame_config->lst_fb_idx[sl] = sl - 1; else
ref_frame_config->gld_fb_idx[sl] = sl;
} else {
ref_frame_config->gld_fb_idx[sl] = sl - 1;
}
} else {
ref_frame_config->gld_fb_idx[sl] = 0; ref_frame_config->gld_fb_idx[sl] = 0;
}
ref_frame_config->alt_fb_idx[sl] = 0; ref_frame_config->alt_fb_idx[sl] = 0;
} else if (tl == 1) { } else if (tl == 1) {
ref_frame_config->lst_fb_idx[sl] = sl; ref_frame_config->lst_fb_idx[sl] = sl;
@ -632,7 +622,7 @@ int main(int argc, const char **argv) {
int end_of_stream = 0; int end_of_stream = 0;
int frames_received = 0; int frames_received = 0;
#if OUTPUT_RC_STATS #if OUTPUT_RC_STATS
VpxVideoWriter *outfile[VPX_SS_MAX_LAYERS] = { NULL }; VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = { NULL };
struct RateControlStats rc; struct RateControlStats rc;
vpx_svc_layer_id_t layer_id; vpx_svc_layer_id_t layer_id;
vpx_svc_ref_frame_config_t ref_frame_config; vpx_svc_ref_frame_config_t ref_frame_config;
@ -644,8 +634,7 @@ int main(int argc, const char **argv) {
struct vpx_usec_timer timer; struct vpx_usec_timer timer;
int64_t cx_time = 0; int64_t cx_time = 0;
memset(&svc_ctx, 0, sizeof(svc_ctx)); memset(&svc_ctx, 0, sizeof(svc_ctx));
memset(&app_input, 0, sizeof(AppInput)); svc_ctx.log_print = 1;
memset(&info, 0, sizeof(VpxVideoInfo));
exec_name = argv[0]; exec_name = argv[0];
parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg); parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
@ -672,10 +661,6 @@ int main(int argc, const char **argv) {
die("Failed to initialize encoder\n"); die("Failed to initialize encoder\n");
#if OUTPUT_RC_STATS #if OUTPUT_RC_STATS
rc.window_count = 1;
rc.window_size = 15; // Silence a static analysis warning.
rc.avg_st_encoding_bitrate = 0.0;
rc.variance_st_encoding_bitrate = 0.0;
if (svc_ctx.output_rc_stat) { if (svc_ctx.output_rc_stat) {
set_rate_control_stats(&rc, &enc_cfg); set_rate_control_stats(&rc, &enc_cfg);
framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num; framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num;
@ -694,16 +679,16 @@ int main(int argc, const char **argv) {
die("Failed to open %s for writing\n", app_input.output_filename); die("Failed to open %s for writing\n", app_input.output_filename);
} }
#if OUTPUT_RC_STATS #if OUTPUT_RC_STATS
// Write out spatial layer stream. // For now, just write temporal layer streams.
// TODO(marpan/jianj): allow for writing each spatial and temporal stream. // TODO(marpan): do spatial by re-writing superframe.
if (svc_ctx.output_rc_stat) { if (svc_ctx.output_rc_stat) {
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
char file_name[PATH_MAX]; char file_name[PATH_MAX];
snprintf(file_name, sizeof(file_name), "%s_s%d.ivf", snprintf(file_name, sizeof(file_name), "%s_t%d.ivf",
app_input.output_filename, sl); app_input.output_filename, tl);
outfile[sl] = vpx_video_writer_open(file_name, kContainerIVF, &info); outfile[tl] = vpx_video_writer_open(file_name, kContainerIVF, &info);
if (!outfile[sl]) die("Failed to open %s for writing", file_name); if (!outfile[tl]) die("Failed to open %s for writing", file_name);
} }
} }
#endif #endif
@ -714,7 +699,7 @@ int main(int argc, const char **argv) {
if (svc_ctx.speed != -1) if (svc_ctx.speed != -1)
vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed); vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
if (svc_ctx.threads) { if (svc_ctx.threads) {
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, get_msb(svc_ctx.threads)); vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
if (svc_ctx.threads > 1) if (svc_ctx.threads > 1)
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 1); vpx_codec_control(&codec, VP9E_SET_ROW_MT, 1);
else else
@ -726,10 +711,6 @@ int main(int argc, const char **argv) {
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1); vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 900); vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 900);
vpx_codec_control(&codec, VP9E_SET_SVC_INTER_LAYER_PRED, 0);
vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, 0);
// Encode frames // Encode frames
while (!end_of_stream) { while (!end_of_stream) {
vpx_codec_iter_t iter = NULL; vpx_codec_iter_t iter = NULL;
@ -757,9 +738,7 @@ int main(int argc, const char **argv) {
// the encode for the whole superframe. The encoder will internally loop // the encode for the whole superframe. The encoder will internally loop
// over all the spatial layers for the current superframe. // over all the spatial layers for the current superframe.
vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id); vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
// TODO(jianj): Fix the parameter passing for "is_key_frame" in set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id,
// set_frame_flags_bypass_model() for case of periodic key frames.
set_frame_flags_bypass_mode(layer_id.temporal_layer_id,
svc_ctx.spatial_layers, frame_cnt == 0, svc_ctx.spatial_layers, frame_cnt == 0,
&ref_frame_config); &ref_frame_config);
vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG, vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG,
@ -770,17 +749,6 @@ int main(int argc, const char **argv) {
++rc.layer_input_frames[sl * enc_cfg.ts_number_layers + ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
layer_id.temporal_layer_id]; layer_id.temporal_layer_id];
} }
} else {
// For the fixed pattern SVC, temporal layer is given by superframe count.
unsigned int tl = 0;
if (enc_cfg.ts_number_layers == 2)
tl = (frame_cnt % 2 != 0);
else if (enc_cfg.ts_number_layers == 3) {
if (frame_cnt % 2 != 0) tl = 2;
if ((frame_cnt > 1) && ((frame_cnt - 2) % 4 == 0)) tl = 1;
}
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl)
++rc.layer_input_frames[sl * enc_cfg.ts_number_layers + tl];
} }
vpx_usec_timer_start(&timer); vpx_usec_timer_start(&timer);
@ -790,6 +758,7 @@ int main(int argc, const char **argv) {
vpx_usec_timer_mark(&timer); vpx_usec_timer_mark(&timer);
cx_time += vpx_usec_timer_elapsed(&timer); cx_time += vpx_usec_timer_elapsed(&timer);
printf("%s", vpx_svc_get_message(&svc_ctx));
fflush(stdout); fflush(stdout);
if (res != VPX_CODEC_OK) { if (res != VPX_CODEC_OK) {
die_codec(&codec, "Failed to encode frame"); die_codec(&codec, "Failed to encode frame");
@ -802,10 +771,7 @@ int main(int argc, const char **argv) {
if (cx_pkt->data.frame.sz > 0) { if (cx_pkt->data.frame.sz > 0) {
#if OUTPUT_RC_STATS #if OUTPUT_RC_STATS
uint64_t sizes[8]; uint64_t sizes[8];
uint64_t sizes_parsed[8];
int count = 0; int count = 0;
vp9_zero(sizes);
vp9_zero(sizes_parsed);
#endif #endif
vpx_video_writer_write_frame(writer, cx_pkt->data.frame.buf, vpx_video_writer_write_frame(writer, cx_pkt->data.frame.buf,
cx_pkt->data.frame.sz, cx_pkt->data.frame.sz,
@ -815,50 +781,42 @@ int main(int argc, const char **argv) {
if (svc_ctx.output_rc_stat) { if (svc_ctx.output_rc_stat) {
vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id); vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id);
parse_superframe_index(cx_pkt->data.frame.buf, parse_superframe_index(cx_pkt->data.frame.buf,
cx_pkt->data.frame.sz, sizes_parsed, cx_pkt->data.frame.sz, sizes, &count);
&count);
if (enc_cfg.ss_number_layers == 1) if (enc_cfg.ss_number_layers == 1)
sizes[0] = cx_pkt->data.frame.sz; sizes[0] = cx_pkt->data.frame.sz;
// Note computing input_layer_frames here won't account for frame
// drops in rate control stats.
// TODO(marpan): Fix this for non-bypass mode so we can get stats
// for dropped frames.
if (svc_ctx.temporal_layering_mode != if (svc_ctx.temporal_layering_mode !=
VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
int num_layers_encoded = 0;
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
sizes[sl] = 0; ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
if (cx_pkt->data.frame.spatial_layer_encoded[sl]) { layer_id.temporal_layer_id];
sizes[sl] = sizes_parsed[num_layers_encoded];
num_layers_encoded++;
}
}
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
unsigned int sl2;
uint64_t tot_size = 0;
for (sl2 = 0; sl2 <= sl; ++sl2) {
if (cx_pkt->data.frame.spatial_layer_encoded[sl2])
tot_size += sizes[sl2];
}
if (tot_size > 0)
vpx_video_writer_write_frame(
outfile[sl], cx_pkt->data.frame.buf, (size_t)(tot_size),
cx_pkt->data.frame.pts);
} }
} }
for (tl = layer_id.temporal_layer_id;
tl < enc_cfg.ts_number_layers; ++tl) {
vpx_video_writer_write_frame(
outfile[tl], cx_pkt->data.frame.buf, cx_pkt->data.frame.sz,
cx_pkt->data.frame.pts);
}
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
if (cx_pkt->data.frame.spatial_layer_encoded[sl]) { for (tl = layer_id.temporal_layer_id;
for (tl = layer_id.temporal_layer_id; tl < enc_cfg.ts_number_layers; ++tl) {
tl < enc_cfg.ts_number_layers; ++tl) { const int layer = sl * enc_cfg.ts_number_layers + tl;
const int layer = sl * enc_cfg.ts_number_layers + tl; ++rc.layer_tot_enc_frames[layer];
++rc.layer_tot_enc_frames[layer]; rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl]; // Keep count of rate control stats per layer, for non-key
// Keep count of rate control stats per layer, for non-key // frames.
// frames. if (tl == (unsigned int)layer_id.temporal_layer_id &&
if (tl == (unsigned int)layer_id.temporal_layer_id && !(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) { rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl];
rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl]; rc.layer_avg_rate_mismatch[layer] +=
rc.layer_avg_rate_mismatch[layer] += fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) /
fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) / rc.layer_pfb[layer];
rc.layer_pfb[layer]; ++rc.layer_enc_frames[layer];
++rc.layer_enc_frames[layer];
}
} }
} }
} }
@ -867,9 +825,9 @@ int main(int argc, const char **argv) {
// window of size rc->window, shifted by rc->window / 2. // window of size rc->window, shifted by rc->window / 2.
// Ignore first window segment, due to key frame. // Ignore first window segment, due to key frame.
if (frame_cnt > (unsigned int)rc.window_size) { if (frame_cnt > (unsigned int)rc.window_size) {
tl = layer_id.temporal_layer_id;
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
if (cx_pkt->data.frame.spatial_layer_encoded[sl]) sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
} }
if (frame_cnt % rc.window_size == 0) { if (frame_cnt % rc.window_size == 0) {
rc.window_count += 1; rc.window_count += 1;
@ -884,6 +842,7 @@ int main(int argc, const char **argv) {
// Second shifted window. // Second shifted window.
if (frame_cnt > if (frame_cnt >
(unsigned int)(rc.window_size + rc.window_size / 2)) { (unsigned int)(rc.window_size + rc.window_size / 2)) {
tl = layer_id.temporal_layer_id;
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate; sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
} }
@ -950,8 +909,8 @@ int main(int argc, const char **argv) {
} }
#if OUTPUT_RC_STATS #if OUTPUT_RC_STATS
if (svc_ctx.output_rc_stat) { if (svc_ctx.output_rc_stat) {
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
vpx_video_writer_close(outfile[sl]); vpx_video_writer_close(outfile[tl]);
} }
} }
#endif #endif
@ -960,7 +919,7 @@ int main(int argc, const char **argv) {
1000000 * (double)frame_cnt / (double)cx_time); 1000000 * (double)frame_cnt / (double)cx_time);
vpx_img_free(&raw); vpx_img_free(&raw);
// display average size, psnr // display average size, psnr
vpx_svc_dump_statistics(&svc_ctx); printf("%s", vpx_svc_dump_statistics(&svc_ctx));
vpx_svc_release(&svc_ctx); vpx_svc_release(&svc_ctx);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -22,34 +22,23 @@
#include "../vpx_ports/vpx_timer.h" #include "../vpx_ports/vpx_timer.h"
#include "vpx/vp8cx.h" #include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h" #include "vpx/vpx_encoder.h"
#include "vpx_ports/bitops.h"
#include "../tools_common.h" #include "../tools_common.h"
#include "../video_writer.h" #include "../video_writer.h"
#define ROI_MAP 0 #define VP8_ROI_MAP 0
#define zero(Dest) memset(&Dest, 0, sizeof(Dest));
static const char *exec_name; static const char *exec_name;
void usage_exit(void) { exit(EXIT_FAILURE); } void usage_exit(void) { exit(EXIT_FAILURE); }
// Denoiser states for vp8, for temporal denoising. // Denoiser states, for temporal denoising.
enum denoiserStateVp8 { enum denoiserState {
kVp8DenoiserOff, kDenoiserOff,
kVp8DenoiserOnYOnly, kDenoiserOnYOnly,
kVp8DenoiserOnYUV, kDenoiserOnYUV,
kVp8DenoiserOnYUVAggressive, kDenoiserOnYUVAggressive,
kVp8DenoiserOnAdaptive kDenoiserOnAdaptive
};
// Denoiser states for vp9, for temporal denoising.
enum denoiserStateVp9 {
kVp9DenoiserOff,
kVp9DenoiserOnYOnly,
// For SVC: denoise the top two spatial layers.
kVp9DenoiserOnYTwoSpatialLayers
}; };
static int mode_to_num_layers[13] = { 1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3, 3 }; static int mode_to_num_layers[13] = { 1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3, 3 };
@ -102,10 +91,9 @@ static void set_rate_control_metrics(struct RateControlMetrics *rc,
for (i = 0; i < cfg->ts_number_layers; ++i) { for (i = 0; i < cfg->ts_number_layers; ++i) {
if (i > 0) { if (i > 0) {
rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i]; rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
rc->layer_pfb[i] = rc->layer_pfb[i] = 1000.0 * (rc->layer_target_bitrate[i] -
1000.0 * rc->layer_target_bitrate[i - 1]) /
(rc->layer_target_bitrate[i] - rc->layer_target_bitrate[i - 1]) / (rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
(rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
} }
rc->layer_input_frames[i] = 0; rc->layer_input_frames[i] = 0;
rc->layer_enc_frames[i] = 0; rc->layer_enc_frames[i] = 0;
@ -168,60 +156,38 @@ static void printout_rate_control_summary(struct RateControlMetrics *rc,
die("Error: Number of input frames not equal to output! \n"); die("Error: Number of input frames not equal to output! \n");
} }
#if ROI_MAP #if VP8_ROI_MAP
static void set_roi_map(const char *enc_name, vpx_codec_enc_cfg_t *cfg, static void vp8_set_roi_map(vpx_codec_enc_cfg_t *cfg, vpx_roi_map_t *roi) {
vpx_roi_map_t *roi) {
unsigned int i, j; unsigned int i, j;
int block_size = 0; memset(roi, 0, sizeof(*roi));
uint8_t is_vp8 = strncmp(enc_name, "vp8", 3) == 0 ? 1 : 0;
uint8_t is_vp9 = strncmp(enc_name, "vp9", 3) == 0 ? 1 : 0;
if (!is_vp8 && !is_vp9) {
die("unsupported codec.");
}
zero(*roi);
block_size = is_vp9 && !is_vp8 ? 8 : 16;
// ROI is based on the segments (4 for vp8, 8 for vp9), smallest unit for // ROI is based on the segments (4 for vp8, 8 for vp9), smallest unit for
// segment is 16x16 for vp8, 8x8 for vp9. // segment is 16x16 for vp8, 8x8 for vp9.
roi->rows = (cfg->g_h + block_size - 1) / block_size; roi->rows = (cfg->g_h + 15) / 16;
roi->cols = (cfg->g_w + block_size - 1) / block_size; roi->cols = (cfg->g_w + 15) / 16;
// Applies delta QP on the segment blocks, varies from -63 to 63. // Applies delta QP on the segment blocks, varies from -63 to 63.
// Setting to negative means lower QP (better quality). // Setting to negative means lower QP (better quality).
// Below we set delta_q to the extreme (-63) to show strong effect. // Below we set delta_q to the extreme (-63) to show strong effect.
// VP8 uses the first 4 segments. VP9 uses all 8 segments. roi->delta_q[0] = 0;
zero(roi->delta_q);
roi->delta_q[1] = -63; roi->delta_q[1] = -63;
roi->delta_q[2] = 0;
roi->delta_q[3] = 0;
// Applies delta loopfilter strength on the segment blocks, varies from -63 to // Applies delta loopfilter strength on the segment blocks, varies from -63 to
// 63. Setting to positive means stronger loopfilter. VP8 uses the first 4 // 63. Setting to positive means stronger loopfilter.
// segments. VP9 uses all 8 segments. roi->delta_lf[0] = 0;
zero(roi->delta_lf); roi->delta_lf[1] = 0;
roi->delta_lf[2] = 0;
roi->delta_lf[3] = 0;
if (is_vp8) { // Applies skip encoding threshold on the segment blocks, varies from 0 to
// Applies skip encoding threshold on the segment blocks, varies from 0 to // UINT_MAX. Larger value means more skipping of encoding is possible.
// UINT_MAX. Larger value means more skipping of encoding is possible. // This skip threshold only applies on delta frames.
// This skip threshold only applies on delta frames. roi->static_threshold[0] = 0;
zero(roi->static_threshold); roi->static_threshold[1] = 0;
} roi->static_threshold[2] = 0;
roi->static_threshold[3] = 0;
if (is_vp9) {
// Apply skip segment. Setting to 1 means this block will be copied from
// previous frame.
zero(roi->skip);
}
if (is_vp9) {
// Apply ref frame segment.
// -1 : Do not apply this segment.
// 0 : Froce using intra.
// 1 : Force using last.
// 2 : Force using golden.
// 3 : Force using alfref but not used in non-rd pickmode for 0 lag.
memset(roi->ref_frame, -1, sizeof(roi->ref_frame));
roi->ref_frame[1] = 1;
}
// Use 2 states: 1 is center square, 0 is the rest. // Use 2 states: 1 is center square, 0 is the rest.
roi->roi_map = roi->roi_map =
@ -589,7 +555,7 @@ int main(int argc, char **argv) {
int layering_mode = 0; int layering_mode = 0;
int layer_flags[VPX_TS_MAX_PERIODICITY] = { 0 }; int layer_flags[VPX_TS_MAX_PERIODICITY] = { 0 };
int flag_periodicity = 1; int flag_periodicity = 1;
#if ROI_MAP #if VP8_ROI_MAP
vpx_roi_map_t roi; vpx_roi_map_t roi;
#endif #endif
vpx_svc_layer_id_t layer_id = { 0, 0 }; vpx_svc_layer_id_t layer_id = { 0, 0 };
@ -609,8 +575,6 @@ int main(int argc, char **argv) {
double sum_bitrate2 = 0.0; double sum_bitrate2 = 0.0;
double framerate = 30.0; double framerate = 30.0;
zero(rc.layer_target_bitrate);
exec_name = argv[0]; exec_name = argv[0];
// Check usage and arguments. // Check usage and arguments.
if (argc < min_args) { if (argc < min_args) {
@ -791,11 +755,11 @@ int main(int argc, char **argv) {
if (strncmp(encoder->name, "vp8", 3) == 0) { if (strncmp(encoder->name, "vp8", 3) == 0) {
vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed); vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed);
vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kVp8DenoiserOff); vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1); vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP8E_SET_GF_CBR_BOOST_PCT, 0); vpx_codec_control(&codec, VP8E_SET_GF_CBR_BOOST_PCT, 0);
#if ROI_MAP #if VP8_ROI_MAP
set_roi_map(encoder->name, &cfg, &roi); vp8_set_roi_map(&cfg, &roi);
if (vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi)) if (vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))
die_codec(&codec, "Failed to set ROI map"); die_codec(&codec, "Failed to set ROI map");
#endif #endif
@ -808,16 +772,10 @@ int main(int argc, char **argv) {
vpx_codec_control(&codec, VP9E_SET_GF_CBR_BOOST_PCT, 0); vpx_codec_control(&codec, VP9E_SET_GF_CBR_BOOST_PCT, 0);
vpx_codec_control(&codec, VP9E_SET_FRAME_PARALLEL_DECODING, 0); vpx_codec_control(&codec, VP9E_SET_FRAME_PARALLEL_DECODING, 0);
vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0); vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kVp9DenoiserOff); vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kDenoiserOff);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1); vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0); vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, get_msb(cfg.g_threads)); vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
#if ROI_MAP
set_roi_map(encoder->name, &cfg, &roi);
if (vpx_codec_control(&codec, VP9E_SET_ROI_MAP, &roi))
die_codec(&codec, "Failed to set ROI map");
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 0);
#endif
// TODO(marpan/jianj): There is an issue with row-mt for low resolutons at // TODO(marpan/jianj): There is an issue with row-mt for low resolutons at
// high speed settings, disable its use for those cases for now. // high speed settings, disable its use for those cases for now.
if (cfg.g_threads > 1 && ((cfg.g_w > 320 && cfg.g_h > 240) || speed < 7)) if (cfg.g_threads > 1 && ((cfg.g_w > 320 && cfg.g_h > 240) || speed < 7))
@ -945,8 +903,5 @@ int main(int argc, char **argv) {
for (i = 0; i < cfg.ts_number_layers; ++i) vpx_video_writer_close(outfile[i]); for (i = 0; i < cfg.ts_number_layers; ++i) vpx_video_writer_close(outfile[i]);
vpx_img_free(&raw); vpx_img_free(&raw);
#if ROI_MAP
free(roi.roi_map);
#endif
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -943,6 +943,18 @@ GENERATE_XML = NO
XML_OUTPUT = xml XML_OUTPUT = xml
# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_SCHEMA =
# The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will # If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting # dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that # and cross-referencing information) to the XML output. Note that

22
libs.mk
View File

@ -88,7 +88,7 @@ ifeq ($(CONFIG_VP9_ENCODER),yes)
CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_CX_EXPORTS)) CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_CX_EXPORTS))
CODEC_SRCS-yes += $(VP9_PREFIX)vp9cx.mk vpx/vp8.h vpx/vp8cx.h CODEC_SRCS-yes += $(VP9_PREFIX)vp9cx.mk vpx/vp8.h vpx/vp8cx.h
INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
INSTALL-LIBS-yes += include/vpx/svc_context.h INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h
INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/% INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/%
CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
CODEC_DOC_SECTIONS += vp9 vp9_encoder CODEC_DOC_SECTIONS += vp9 vp9_encoder
@ -153,7 +153,9 @@ INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += vpx_dsp/x86/bitdepth_conversion_sse2.asm
endif endif
CODEC_EXPORTS-yes += vpx/exports_com CODEC_EXPORTS-yes += vpx/exports_com
CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc
CODEC_EXPORTS-$(CONFIG_VP9_ENCODER) += vpx/exports_spatial_svc ifeq ($(CONFIG_SPATIAL_SVC),yes)
CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_spatial_svc
endif
CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec
INSTALL-LIBS-yes += include/vpx/vpx_codec.h INSTALL-LIBS-yes += include/vpx/vpx_codec.h
@ -204,8 +206,6 @@ vpx.def: $(call enabled,CODEC_EXPORTS)
--out=$@ $^ --out=$@ $^
CLEAN-OBJS += vpx.def CLEAN-OBJS += vpx.def
vpx.$(VCPROJ_SFX): VCPROJ_SRCS=$(filter-out $(addprefix %, $(ASM_INCLUDES)), $^)
vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def
@echo " [CREATE] $@" @echo " [CREATE] $@"
$(qexec)$(GEN_VCPROJ) \ $(qexec)$(GEN_VCPROJ) \
@ -218,15 +218,7 @@ vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def
--ver=$(CONFIG_VS_VERSION) \ --ver=$(CONFIG_VS_VERSION) \
--src-path-bare="$(SRC_PATH_BARE)" \ --src-path-bare="$(SRC_PATH_BARE)" \
--out=$@ $(CFLAGS) \ --out=$@ $(CFLAGS) \
$(filter $(SRC_PATH_BARE)/vp8/%.c, $(VCPROJ_SRCS)) \ $(filter-out $(addprefix %, $(ASM_INCLUDES)), $^) \
$(filter $(SRC_PATH_BARE)/vp8/%.h, $(VCPROJ_SRCS)) \
$(filter $(SRC_PATH_BARE)/vp9/%.c, $(VCPROJ_SRCS)) \
$(filter $(SRC_PATH_BARE)/vp9/%.h, $(VCPROJ_SRCS)) \
$(filter $(SRC_PATH_BARE)/vpx/%, $(VCPROJ_SRCS)) \
$(filter $(SRC_PATH_BARE)/vpx_dsp/%, $(VCPROJ_SRCS)) \
$(filter-out $(addprefix $(SRC_PATH_BARE)/, \
vp8/%.c vp8/%.h vp9/%.c vp9/%.h vpx/% vpx_dsp/%), \
$(VCPROJ_SRCS)) \
--src-path-bare="$(SRC_PATH_BARE)" \ --src-path-bare="$(SRC_PATH_BARE)" \
PROJECTS-yes += vpx.$(VCPROJ_SFX) PROJECTS-yes += vpx.$(VCPROJ_SFX)
@ -241,8 +233,8 @@ OBJS-yes += $(LIBVPX_OBJS)
LIBS-$(if yes,$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a LIBS-$(if yes,$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
$(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS) $(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS)
SO_VERSION_MAJOR := 5 SO_VERSION_MAJOR := 4
SO_VERSION_MINOR := 0 SO_VERSION_MINOR := 1
SO_VERSION_PATCH := 0 SO_VERSION_PATCH := 0
ifeq ($(filter darwin%,$(TGT_OS)),$(TGT_OS)) ifeq ($(filter darwin%,$(TGT_OS)),$(TGT_OS))
LIBVPX_SO := libvpx.$(SO_VERSION_MAJOR).dylib LIBVPX_SO := libvpx.$(SO_VERSION_MAJOR).dylib

View File

@ -91,7 +91,7 @@ class AverageTestBase : public ::testing::Test {
}; };
typedef unsigned int (*AverageFunction)(const uint8_t *s, int pitch); typedef unsigned int (*AverageFunction)(const uint8_t *s, int pitch);
typedef ::testing::tuple<int, int, int, int, AverageFunction> AvgFunc; typedef std::tr1::tuple<int, int, int, int, AverageFunction> AvgFunc;
class AverageTest : public AverageTestBase, class AverageTest : public AverageTestBase,
public ::testing::WithParamInterface<AvgFunc> { public ::testing::WithParamInterface<AvgFunc> {
@ -122,7 +122,7 @@ class AverageTest : public AverageTestBase,
typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref, typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref,
const int ref_stride, const int height); const int ref_stride, const int height);
typedef ::testing::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam; typedef std::tr1::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam;
class IntProRowTest : public AverageTestBase, class IntProRowTest : public AverageTestBase,
public ::testing::WithParamInterface<IntProRowParam> { public ::testing::WithParamInterface<IntProRowParam> {
@ -164,7 +164,7 @@ class IntProRowTest : public AverageTestBase,
typedef int16_t (*IntProColFunc)(uint8_t const *ref, const int width); typedef int16_t (*IntProColFunc)(uint8_t const *ref, const int width);
typedef ::testing::tuple<int, IntProColFunc, IntProColFunc> IntProColParam; typedef std::tr1::tuple<int, IntProColFunc, IntProColFunc> IntProColParam;
class IntProColTest : public AverageTestBase, class IntProColTest : public AverageTestBase,
public ::testing::WithParamInterface<IntProColParam> { public ::testing::WithParamInterface<IntProColParam> {
@ -189,7 +189,7 @@ class IntProColTest : public AverageTestBase,
}; };
typedef int (*SatdFunc)(const tran_low_t *coeffs, int length); typedef int (*SatdFunc)(const tran_low_t *coeffs, int length);
typedef ::testing::tuple<int, SatdFunc> SatdTestParam; typedef std::tr1::tuple<int, SatdFunc> SatdTestParam;
class SatdTest : public ::testing::Test, class SatdTest : public ::testing::Test,
public ::testing::WithParamInterface<SatdTestParam> { public ::testing::WithParamInterface<SatdTestParam> {
@ -235,7 +235,7 @@ class SatdTest : public ::testing::Test,
typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff, typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff,
const tran_low_t *dqcoeff, int block_size); const tran_low_t *dqcoeff, int block_size);
typedef ::testing::tuple<int, BlockErrorFunc> BlockErrorTestFPParam; typedef std::tr1::tuple<int, BlockErrorFunc> BlockErrorTestFPParam;
class BlockErrorTestFP class BlockErrorTestFP
: public ::testing::Test, : public ::testing::Test,
@ -428,7 +428,7 @@ TEST_P(BlockErrorTestFP, DISABLED_Speed) {
printf("blocksize: %4d time: %4d us\n", blocksize, elapsed_time); printf("blocksize: %4d time: %4d us\n", blocksize, elapsed_time);
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
C, AverageTest, C, AverageTest,

View File

@ -141,7 +141,7 @@ class BlockinessTestBase : public ::testing::Test {
}; };
#if CONFIG_VP9_ENCODER #if CONFIG_VP9_ENCODER
typedef ::testing::tuple<int, int> BlockinessParam; typedef std::tr1::tuple<int, int> BlockinessParam;
class BlockinessVP9Test class BlockinessVP9Test
: public BlockinessTestBase, : public BlockinessTestBase,
public ::testing::WithParamInterface<BlockinessParam> { public ::testing::WithParamInterface<BlockinessParam> {
@ -208,14 +208,14 @@ TEST_P(BlockinessVP9Test, WorstCaseBlockiness) {
} }
#endif // CONFIG_VP9_ENCODER #endif // CONFIG_VP9_ENCODER
using ::testing::make_tuple; using std::tr1::make_tuple;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// C functions // C functions
#if CONFIG_VP9_ENCODER #if CONFIG_VP9_ENCODER
const BlockinessParam c_vp9_tests[] = { const BlockinessParam c_vp9_tests[] = {
make_tuple(320, 240), make_tuple(318, 242), make_tuple(318, 238) make_tuple(320, 240), make_tuple(318, 242), make_tuple(318, 238),
}; };
INSTANTIATE_TEST_CASE_P(C, BlockinessVP9Test, ::testing::ValuesIn(c_vp9_tests)); INSTANTIATE_TEST_CASE_P(C, BlockinessVP9Test, ::testing::ValuesIn(c_vp9_tests));
#endif #endif

View File

@ -171,9 +171,8 @@ TEST_F(ByteAlignmentTest, SwitchByteAlignment) {
TEST_P(ByteAlignmentTest, TestAlignment) { TEST_P(ByteAlignmentTest, TestAlignment) {
const ByteAlignmentTestParam t = GetParam(); const ByteAlignmentTestParam t = GetParam();
SetByteAlignment(t.byte_alignment, t.expected_value); SetByteAlignment(t.byte_alignment, t.expected_value);
if (t.decode_remaining) { if (t.decode_remaining)
ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(t.byte_alignment)); ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(t.byte_alignment));
}
} }
INSTANTIATE_TEST_CASE_P(Alignments, ByteAlignmentTest, INSTANTIATE_TEST_CASE_P(Alignments, ByteAlignmentTest,

View File

@ -11,13 +11,19 @@
#define TEST_CLEAR_SYSTEM_STATE_H_ #define TEST_CLEAR_SYSTEM_STATE_H_
#include "./vpx_config.h" #include "./vpx_config.h"
#include "vpx_ports/system_state.h" #if ARCH_X86 || ARCH_X86_64
#include "vpx_ports/x86.h"
#endif
namespace libvpx_test { namespace libvpx_test {
// Reset system to a known state. This function should be used for all non-API // Reset system to a known state. This function should be used for all non-API
// test cases. // test cases.
inline void ClearSystemState() { vpx_clear_system_state(); } inline void ClearSystemState() {
#if ARCH_X86 || ARCH_X86_64
vpx_reset_mmx_state();
#endif
}
} // namespace libvpx_test } // namespace libvpx_test
#endif // TEST_CLEAR_SYSTEM_STATE_H_ #endif // TEST_CLEAR_SYSTEM_STATE_H_

View File

@ -53,22 +53,23 @@ class CodecFactory {
template <class T1> template <class T1>
class CodecTestWithParam class CodecTestWithParam
: public ::testing::TestWithParam< : public ::testing::TestWithParam<
::testing::tuple<const libvpx_test::CodecFactory *, T1> > {}; std::tr1::tuple<const libvpx_test::CodecFactory *, T1> > {};
template <class T1, class T2> template <class T1, class T2>
class CodecTestWith2Params class CodecTestWith2Params
: public ::testing::TestWithParam< : public ::testing::TestWithParam<
::testing::tuple<const libvpx_test::CodecFactory *, T1, T2> > {}; std::tr1::tuple<const libvpx_test::CodecFactory *, T1, T2> > {};
template <class T1, class T2, class T3> template <class T1, class T2, class T3>
class CodecTestWith3Params class CodecTestWith3Params
: public ::testing::TestWithParam< : public ::testing::TestWithParam<
::testing::tuple<const libvpx_test::CodecFactory *, T1, T2, T3> > {}; std::tr1::tuple<const libvpx_test::CodecFactory *, T1, T2, T3> > {};
template <class T1, class T2, class T3, class T4> template <class T1, class T2, class T3, class T4>
class CodecTestWith4Params class CodecTestWith4Params
: public ::testing::TestWithParam< ::testing::tuple< : public ::testing::TestWithParam<
const libvpx_test::CodecFactory *, T1, T2, T3, T4> > {}; std::tr1::tuple<const libvpx_test::CodecFactory *, T1, T2, T3, T4> > {
};
/* /*
* VP8 Codec Definitions * VP8 Codec Definitions

View File

@ -127,7 +127,7 @@ class ConsistencyTestBase : public ::testing::Test {
}; };
#if CONFIG_VP9_ENCODER #if CONFIG_VP9_ENCODER
typedef ::testing::tuple<int, int> ConsistencyParam; typedef std::tr1::tuple<int, int> ConsistencyParam;
class ConsistencyVP9Test class ConsistencyVP9Test
: public ConsistencyTestBase, : public ConsistencyTestBase,
public ::testing::WithParamInterface<ConsistencyParam> { public ::testing::WithParamInterface<ConsistencyParam> {
@ -198,14 +198,14 @@ TEST_P(ConsistencyVP9Test, ConsistencyIsZero) {
} }
#endif // CONFIG_VP9_ENCODER #endif // CONFIG_VP9_ENCODER
using ::testing::make_tuple; using std::tr1::make_tuple;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// C functions // C functions
#if CONFIG_VP9_ENCODER #if CONFIG_VP9_ENCODER
const ConsistencyParam c_vp9_tests[] = { const ConsistencyParam c_vp9_tests[] = {
make_tuple(320, 240), make_tuple(318, 242), make_tuple(318, 238) make_tuple(320, 240), make_tuple(318, 242), make_tuple(318, 238),
}; };
INSTANTIATE_TEST_CASE_P(C, ConsistencyVP9Test, INSTANTIATE_TEST_CASE_P(C, ConsistencyVP9Test,
::testing::ValuesIn(c_vp9_tests)); ::testing::ValuesIn(c_vp9_tests));

View File

@ -77,7 +77,7 @@ struct ConvolveFunctions {
int use_highbd_; // 0 if high bitdepth not used, else the actual bit depth. int use_highbd_; // 0 if high bitdepth not used, else the actual bit depth.
}; };
typedef ::testing::tuple<int, int, const ConvolveFunctions *> ConvolveParam; typedef std::tr1::tuple<int, int, const ConvolveFunctions *> ConvolveParam;
#define ALL_SIZES(convolve_fn) \ #define ALL_SIZES(convolve_fn) \
make_tuple(4, 4, &convolve_fn), make_tuple(8, 4, &convolve_fn), \ make_tuple(4, 4, &convolve_fn), make_tuple(8, 4, &convolve_fn), \
@ -450,9 +450,7 @@ class ConvolveTest : public ::testing::TestWithParam<ConvolveParam> {
void CheckGuardBlocks() { void CheckGuardBlocks() {
for (int i = 0; i < kOutputBufferSize; ++i) { for (int i = 0; i < kOutputBufferSize; ++i) {
if (IsIndexInBorder(i)) { if (IsIndexInBorder(i)) EXPECT_EQ(255, output_[i]);
EXPECT_EQ(255, output_[i]);
}
} }
} }
@ -1042,7 +1040,7 @@ TEST_P(ConvolveTest, CheckScalingFiltering) {
} }
#endif #endif
using ::testing::make_tuple; using std::tr1::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
#define WRAP(func, bd) \ #define WRAP(func, bd) \
@ -1379,16 +1377,4 @@ const ConvolveParam kArrayConvolve_vsx[] = { ALL_SIZES(convolve8_vsx) };
INSTANTIATE_TEST_CASE_P(VSX, ConvolveTest, INSTANTIATE_TEST_CASE_P(VSX, ConvolveTest,
::testing::ValuesIn(kArrayConvolve_vsx)); ::testing::ValuesIn(kArrayConvolve_vsx));
#endif // HAVE_VSX #endif // HAVE_VSX
#if HAVE_MMI
const ConvolveFunctions convolve8_mmi(
vpx_convolve_copy_c, vpx_convolve_avg_c, vpx_convolve8_horiz_mmi,
vpx_convolve8_avg_horiz_c, vpx_convolve8_vert_mmi,
vpx_convolve8_avg_vert_mmi, vpx_convolve8_mmi, vpx_convolve8_avg_mmi,
vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
vpx_scaled_avg_vert_c, vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
const ConvolveParam kArrayConvolve_mmi[] = { ALL_SIZES(convolve8_mmi) };
INSTANTIATE_TEST_CASE_P(MMI, ConvolveTest,
::testing::ValuesIn(kArrayConvolve_mmi));
#endif // HAVE_MMI
} // namespace } // namespace

1740
test/datarate_test.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -229,10 +229,9 @@ typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
int tx_type); int tx_type);
typedef ::testing::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct16x16Param;
Dct16x16Param; typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param;
typedef ::testing::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param; typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t>
typedef ::testing::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t>
Idct16x16Param; Idct16x16Param;
void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride, void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride,
@ -745,7 +744,7 @@ TEST_P(InvTrans16x16DCT, CompareReference) {
CompareInvReference(ref_txfm_, thresh_); CompareInvReference(ref_txfm_, thresh_);
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(

View File

@ -66,7 +66,7 @@ void reference_32x32_dct_2d(const int16_t input[kNumCoeffs],
typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride); typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride); typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
typedef ::testing::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t> typedef std::tr1::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t>
Trans32x32Param; Trans32x32Param;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
@ -292,7 +292,7 @@ TEST_P(Trans32x32Test, InverseAccuracy) {
} }
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(

View File

@ -26,10 +26,10 @@
#include "vpx/vpx_integer.h" #include "vpx/vpx_integer.h"
#include "vpx_dsp/vpx_dsp_common.h" #include "vpx_dsp/vpx_dsp_common.h"
using ::testing::make_tuple;
using ::testing::tuple;
using libvpx_test::ACMRandom; using libvpx_test::ACMRandom;
using libvpx_test::Buffer; using libvpx_test::Buffer;
using std::tr1::tuple;
using std::tr1::make_tuple;
namespace { namespace {
typedef void (*PartialFdctFunc)(const int16_t *in, tran_low_t *out, int stride); typedef void (*PartialFdctFunc)(const int16_t *in, tran_low_t *out, int stride);

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
#include "./ivfenc.h" #include "./ivfenc.h"
#include "./vpx_version.h" #include "./vpx_version.h"
using ::testing::make_tuple; using std::tr1::make_tuple;
namespace { namespace {
@ -34,7 +34,7 @@ const char kNewEncodeOutputFile[] = "new_encode.ivf";
/* /*
DecodePerfTest takes a tuple of filename + number of threads to decode with DecodePerfTest takes a tuple of filename + number of threads to decode with
*/ */
typedef ::testing::tuple<const char *, unsigned> DecodePerfParam; typedef std::tr1::tuple<const char *, unsigned> DecodePerfParam;
const DecodePerfParam kVP9DecodePerfVectors[] = { const DecodePerfParam kVP9DecodePerfVectors[] = {
make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1), make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1),

View File

@ -52,10 +52,9 @@ void DecoderTest::HandlePeekResult(Decoder *const decoder,
/* Vp8's implementation of PeekStream returns an error if the frame you /* Vp8's implementation of PeekStream returns an error if the frame you
* pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first * pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first
* frame, which must be a keyframe. */ * frame, which must be a keyframe. */
if (video->frame_number() == 0) { if (video->frame_number() == 0)
ASSERT_EQ(VPX_CODEC_OK, res_peek) ASSERT_EQ(VPX_CODEC_OK, res_peek)
<< "Peek return failed: " << vpx_codec_err_to_string(res_peek); << "Peek return failed: " << vpx_codec_err_to_string(res_peek);
}
} else { } else {
/* The Vp9 implementation of PeekStream returns an error only if the /* The Vp9 implementation of PeekStream returns an error only if the
* data passed to it isn't a valid Vp9 chunk. */ * data passed to it isn't a valid Vp9 chunk. */

View File

@ -106,90 +106,4 @@ TEST(EncodeAPI, ImageSizeSetting) {
} }
#endif #endif
// Set up 2 spatial streams with 2 temporal layers per stream, and generate
// invalid configuration by setting the temporal layer rate allocation
// (ts_target_bitrate[]) to 0 for both layers. This should fail independent of
// CONFIG_MULTI_RES_ENCODING.
TEST(EncodeAPI, MultiResEncode) {
static const vpx_codec_iface_t *kCodecs[] = {
#if CONFIG_VP8_ENCODER
&vpx_codec_vp8_cx_algo,
#endif
#if CONFIG_VP9_ENCODER
&vpx_codec_vp9_cx_algo,
#endif
};
const int width = 1280;
const int height = 720;
const int width_down = width / 2;
const int height_down = height / 2;
const int target_bitrate = 1000;
const int framerate = 30;
for (int c = 0; c < NELEMENTS(kCodecs); ++c) {
const vpx_codec_iface_t *const iface = kCodecs[c];
vpx_codec_ctx_t enc[2];
vpx_codec_enc_cfg_t cfg[2];
vpx_rational_t dsf[2] = { { 2, 1 }, { 2, 1 } };
memset(enc, 0, sizeof(enc));
for (int i = 0; i < 2; i++) {
vpx_codec_enc_config_default(iface, &cfg[i], 0);
}
/* Highest-resolution encoder settings */
cfg[0].g_w = width;
cfg[0].g_h = height;
cfg[0].rc_dropframe_thresh = 0;
cfg[0].rc_end_usage = VPX_CBR;
cfg[0].rc_resize_allowed = 0;
cfg[0].rc_min_quantizer = 2;
cfg[0].rc_max_quantizer = 56;
cfg[0].rc_undershoot_pct = 100;
cfg[0].rc_overshoot_pct = 15;
cfg[0].rc_buf_initial_sz = 500;
cfg[0].rc_buf_optimal_sz = 600;
cfg[0].rc_buf_sz = 1000;
cfg[0].g_error_resilient = 1; /* Enable error resilient mode */
cfg[0].g_lag_in_frames = 0;
cfg[0].kf_mode = VPX_KF_AUTO;
cfg[0].kf_min_dist = 3000;
cfg[0].kf_max_dist = 3000;
cfg[0].rc_target_bitrate = target_bitrate; /* Set target bitrate */
cfg[0].g_timebase.num = 1; /* Set fps */
cfg[0].g_timebase.den = framerate;
memcpy(&cfg[1], &cfg[0], sizeof(cfg[0]));
cfg[1].rc_target_bitrate = 500;
cfg[1].g_w = width_down;
cfg[1].g_h = height_down;
for (int i = 0; i < 2; i++) {
cfg[i].ts_number_layers = 2;
cfg[i].ts_periodicity = 2;
cfg[i].ts_rate_decimator[0] = 2;
cfg[i].ts_rate_decimator[1] = 1;
cfg[i].ts_layer_id[0] = 0;
cfg[i].ts_layer_id[1] = 1;
// Invalid parameters.
cfg[i].ts_target_bitrate[0] = 0;
cfg[i].ts_target_bitrate[1] = 0;
}
// VP9 should report incapable, VP8 invalid for all configurations.
const char kVP9Name[] = "WebM Project VP9";
const bool is_vp9 = strncmp(kVP9Name, vpx_codec_iface_name(iface),
sizeof(kVP9Name) - 1) == 0;
EXPECT_EQ(is_vp9 ? VPX_CODEC_INCAPABLE : VPX_CODEC_INVALID_PARAM,
vpx_codec_enc_init_multi(&enc[0], iface, &cfg[0], 2, 0, &dsf[0]));
for (int i = 0; i < 2; i++) {
vpx_codec_destroy(&enc[i]);
}
}
}
} // namespace } // namespace

View File

@ -201,8 +201,6 @@ void EncoderTest::RunLoop(VideoSource *video) {
PreEncodeFrameHook(video, encoder.get()); PreEncodeFrameHook(video, encoder.get());
encoder->EncodeFrame(video, frame_flags_); encoder->EncodeFrame(video, frame_flags_);
PostEncodeFrameHook();
CxDataIterator iter = encoder->GetCxData(); CxDataIterator iter = encoder->GetCxData();
bool has_cxdata = false; bool has_cxdata = false;

View File

@ -128,31 +128,24 @@ class Encoder {
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
} }
void Control(int ctrl_id, struct vpx_svc_ref_frame_config *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
void Control(int ctrl_id, struct vpx_svc_parameters *arg) { void Control(int ctrl_id, struct vpx_svc_parameters *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
} }
void Control(int ctrl_id, struct vpx_svc_frame_drop *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
void Control(int ctrl_id, vpx_active_map_t *arg) { void Control(int ctrl_id, vpx_active_map_t *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
} }
#endif
#if CONFIG_VP8_ENCODER
void Control(int ctrl_id, vpx_roi_map_t *arg) { void Control(int ctrl_id, vpx_roi_map_t *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
} }
#endif #endif
void Config(const vpx_codec_enc_cfg_t *cfg) { void Config(const vpx_codec_enc_cfg_t *cfg) {
const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg); const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
@ -226,8 +219,6 @@ class EncoderTest {
virtual void PreEncodeFrameHook(VideoSource * /*video*/, virtual void PreEncodeFrameHook(VideoSource * /*video*/,
Encoder * /*encoder*/) {} Encoder * /*encoder*/) {}
virtual void PostEncodeFrameHook() {}
// Hook to be called on every compressed data packet. // Hook to be called on every compressed data packet.
virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {} virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {}

View File

@ -43,9 +43,9 @@ typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
int tx_type); int tx_type);
typedef ::testing::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param; typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param;
typedef ::testing::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param; typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param;
typedef ::testing::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct8x8Param; typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct8x8Param;
void reference_8x8_dct_1d(const double in[8], double out[8]) { void reference_8x8_dct_1d(const double in[8], double out[8]) {
const double kInvSqrt2 = 0.707106781186547524400844362104; const double kInvSqrt2 = 0.707106781186547524400844362104;
@ -628,7 +628,7 @@ TEST_P(InvTrans8x8DCT, CompareReference) {
CompareInvReference(ref_txfm_, thresh_); CompareInvReference(ref_txfm_, thresh_);
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
@ -675,7 +675,6 @@ INSTANTIATE_TEST_CASE_P(NEON, FwdTrans8x8DCT,
::testing::Values(make_tuple(&vpx_fdct8x8_neon, ::testing::Values(make_tuple(&vpx_fdct8x8_neon,
&vpx_idct8x8_64_add_neon, &vpx_idct8x8_64_add_neon,
0, VPX_BITS_8))); 0, VPX_BITS_8)));
#if !CONFIG_VP9_HIGHBITDEPTH #if !CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
NEON, FwdTrans8x8HT, NEON, FwdTrans8x8HT,

View File

@ -174,4 +174,4 @@ INSTANTIATE_TEST_CASE_P(MSA, IDCTTest,
INSTANTIATE_TEST_CASE_P(MMI, IDCTTest, INSTANTIATE_TEST_CASE_P(MMI, IDCTTest,
::testing::Values(vp8_short_idct4x4llm_mmi)); ::testing::Values(vp8_short_idct4x4llm_mmi));
#endif // HAVE_MMI #endif // HAVE_MMI
} // namespace }

View File

@ -123,7 +123,6 @@ TEST_P(InvalidFileTest, ReturnCode) { RunTest(); }
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
const DecodeParam kVP8InvalidFileTests[] = { const DecodeParam kVP8InvalidFileTests[] = {
{ 1, "invalid-bug-1443.ivf" }, { 1, "invalid-bug-1443.ivf" },
{ 1, "invalid-token-partition.ivf" },
}; };
VP8_INSTANTIATE_TEST_CASE(InvalidFileTest, VP8_INSTANTIATE_TEST_CASE(InvalidFileTest,

View File

@ -68,9 +68,7 @@ TEST_P(KeyframeTest, TestRandomVideoSource) {
// In realtime mode - auto placed keyframes are exceedingly rare, don't // In realtime mode - auto placed keyframes are exceedingly rare, don't
// bother with this check if(GetParam() > 0) // bother with this check if(GetParam() > 0)
if (GET_PARAM(1) > 0) { if (GET_PARAM(1) > 0) EXPECT_GT(kf_count_, 1);
EXPECT_GT(kf_count_, 1);
}
} }
TEST_P(KeyframeTest, TestDisableKeyframes) { TEST_P(KeyframeTest, TestDisableKeyframes) {
@ -130,9 +128,8 @@ TEST_P(KeyframeTest, TestAutoKeyframe) {
// In realtime mode - auto placed keyframes are exceedingly rare, don't // In realtime mode - auto placed keyframes are exceedingly rare, don't
// bother with this check // bother with this check
if (GET_PARAM(1) > 0) { if (GET_PARAM(1) > 0)
EXPECT_EQ(2u, kf_pts_list_.size()) << " Not the right number of keyframes "; EXPECT_EQ(2u, kf_pts_list_.size()) << " Not the right number of keyframes ";
}
// Verify that keyframes match the file keyframes in the file. // Verify that keyframes match the file keyframes in the file.
for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin(); for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();

View File

@ -56,8 +56,8 @@ typedef void (*dual_loop_op_t)(Pixel *s, int p, const uint8_t *blimit0,
const uint8_t *thresh1); const uint8_t *thresh1);
#endif // CONFIG_VP9_HIGHBITDEPTH #endif // CONFIG_VP9_HIGHBITDEPTH
typedef ::testing::tuple<loop_op_t, loop_op_t, int> loop8_param_t; typedef std::tr1::tuple<loop_op_t, loop_op_t, int> loop8_param_t;
typedef ::testing::tuple<dual_loop_op_t, dual_loop_op_t, int> dualloop8_param_t; typedef std::tr1::tuple<dual_loop_op_t, dual_loop_op_t, int> dualloop8_param_t;
void InitInput(Pixel *s, Pixel *ref_s, ACMRandom *rnd, const uint8_t limit, void InitInput(Pixel *s, Pixel *ref_s, ACMRandom *rnd, const uint8_t limit,
const int mask, const int32_t p, const int i) { const int mask, const int32_t p, const int i) {
@ -114,18 +114,6 @@ void InitInput(Pixel *s, Pixel *ref_s, ACMRandom *rnd, const uint8_t limit,
} }
} }
uint8_t GetOuterThresh(ACMRandom *rnd) {
return static_cast<uint8_t>(rnd->RandRange(3 * MAX_LOOP_FILTER + 5));
}
uint8_t GetInnerThresh(ACMRandom *rnd) {
return static_cast<uint8_t>(rnd->RandRange(MAX_LOOP_FILTER + 1));
}
uint8_t GetHevThresh(ACMRandom *rnd) {
return static_cast<uint8_t>(rnd->RandRange(MAX_LOOP_FILTER + 1) >> 4);
}
class Loop8Test6Param : public ::testing::TestWithParam<loop8_param_t> { class Loop8Test6Param : public ::testing::TestWithParam<loop8_param_t> {
public: public:
virtual ~Loop8Test6Param() {} virtual ~Loop8Test6Param() {}
@ -174,15 +162,15 @@ TEST_P(Loop8Test6Param, OperationCheck) {
int first_failure = -1; int first_failure = -1;
for (int i = 0; i < count_test_block; ++i) { for (int i = 0; i < count_test_block; ++i) {
int err_count = 0; int err_count = 0;
uint8_t tmp = GetOuterThresh(&rnd); uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetInnerThresh(&rnd); tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetHevThresh(&rnd); tmp = rnd.Rand8();
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
@ -233,15 +221,15 @@ TEST_P(Loop8Test6Param, ValueCheck) {
for (int i = 0; i < count_test_block; ++i) { for (int i = 0; i < count_test_block; ++i) {
int err_count = 0; int err_count = 0;
uint8_t tmp = GetOuterThresh(&rnd); uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetInnerThresh(&rnd); tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetHevThresh(&rnd); tmp = rnd.Rand8();
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
@ -283,27 +271,27 @@ TEST_P(Loop8Test9Param, OperationCheck) {
int first_failure = -1; int first_failure = -1;
for (int i = 0; i < count_test_block; ++i) { for (int i = 0; i < count_test_block; ++i) {
int err_count = 0; int err_count = 0;
uint8_t tmp = GetOuterThresh(&rnd); uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetInnerThresh(&rnd); tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetHevThresh(&rnd); tmp = rnd.Rand8();
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetOuterThresh(&rnd); tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetInnerThresh(&rnd); tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetHevThresh(&rnd); tmp = rnd.Rand8();
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
@ -346,27 +334,27 @@ TEST_P(Loop8Test9Param, ValueCheck) {
int first_failure = -1; int first_failure = -1;
for (int i = 0; i < count_test_block; ++i) { for (int i = 0; i < count_test_block; ++i) {
int err_count = 0; int err_count = 0;
uint8_t tmp = GetOuterThresh(&rnd); uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetInnerThresh(&rnd); tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetHevThresh(&rnd); tmp = rnd.Rand8();
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetOuterThresh(&rnd); tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetInnerThresh(&rnd); tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
tmp = GetHevThresh(&rnd); tmp = rnd.Rand8();
DECLARE_ALIGNED(16, const uint8_t, DECLARE_ALIGNED(16, const uint8_t,
thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp }; tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
@ -402,7 +390,7 @@ TEST_P(Loop8Test9Param, ValueCheck) {
<< "First failed at test case " << first_failure; << "First failed at test case " << first_failure;
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
#if HAVE_SSE2 #if HAVE_SSE2
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH

View File

@ -51,8 +51,8 @@ void highbd_wrapper(const tran_low_t *in, uint8_t *out, int stride, int bd) {
} }
#endif #endif
typedef ::testing::tuple<FwdTxfmFunc, InvTxfmWithBdFunc, InvTxfmWithBdFunc, typedef std::tr1::tuple<FwdTxfmFunc, InvTxfmWithBdFunc, InvTxfmWithBdFunc,
TX_SIZE, int, int, int> TX_SIZE, int, int, int>
PartialInvTxfmParam; PartialInvTxfmParam;
const int kMaxNumCoeffs = 1024; const int kMaxNumCoeffs = 1024;
const int kCountTestBlock = 1000; const int kCountTestBlock = 1000;
@ -324,7 +324,7 @@ TEST_P(PartialIDctTest, DISABLED_Speed) {
<< "Error: partial inverse transform produces different results"; << "Error: partial inverse transform produces different results";
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
const PartialInvTxfmParam c_partial_idct_tests[] = { const PartialInvTxfmParam c_partial_idct_tests[] = {
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH

View File

@ -24,14 +24,14 @@
namespace { namespace {
using ::testing::make_tuple;
using libvpx_test::ACMRandom; using libvpx_test::ACMRandom;
using std::tr1::make_tuple;
typedef void (*PredictFunc)(uint8_t *src_ptr, int src_pixels_per_line, typedef void (*PredictFunc)(uint8_t *src_ptr, int src_pixels_per_line,
int xoffset, int yoffset, uint8_t *dst_ptr, int xoffset, int yoffset, uint8_t *dst_ptr,
int dst_pitch); int dst_pitch);
typedef ::testing::tuple<int, int, PredictFunc> PredictParam; typedef std::tr1::tuple<int, int, PredictFunc> PredictParam;
class PredictTestBase : public ::testing::TestWithParam<PredictParam> { class PredictTestBase : public ::testing::TestWithParam<PredictParam> {
public: public:

View File

@ -33,10 +33,10 @@ const int kNumBlockEntries = 16;
typedef void (*VP8Quantize)(BLOCK *b, BLOCKD *d); typedef void (*VP8Quantize)(BLOCK *b, BLOCKD *d);
typedef ::testing::tuple<VP8Quantize, VP8Quantize> VP8QuantizeParam; typedef std::tr1::tuple<VP8Quantize, VP8Quantize> VP8QuantizeParam;
using ::testing::make_tuple;
using libvpx_test::ACMRandom; using libvpx_test::ACMRandom;
using std::tr1::make_tuple;
// Create and populate a VP8_COMP instance which has a complete set of // Create and populate a VP8_COMP instance which has a complete set of
// quantization inputs as well as a second MACROBLOCKD for output. // quantization inputs as well as a second MACROBLOCKD for output.

View File

@ -28,7 +28,7 @@
// See platform implementations of RegisterStateCheckXXX for details. // See platform implementations of RegisterStateCheckXXX for details.
// //
#if defined(_WIN64) && ARCH_X86_64 #if defined(_WIN64)
#undef NOMINMAX #undef NOMINMAX
#define NOMINMAX #define NOMINMAX
@ -138,7 +138,7 @@ class RegisterStateCheck {};
} // namespace libvpx_test } // namespace libvpx_test
#endif // _WIN64 && ARCH_X86_64 #endif // _WIN64
#if ARCH_X86 || ARCH_X86_64 #if ARCH_X86 || ARCH_X86_64
#if defined(__GNUC__) #if defined(__GNUC__)

View File

@ -277,29 +277,12 @@ class ResizeTest
SetMode(GET_PARAM(1)); SetMode(GET_PARAM(1));
} }
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
ASSERT_NE(static_cast<int>(pkt->data.frame.width[0]), 0);
ASSERT_NE(static_cast<int>(pkt->data.frame.height[0]), 0);
encode_frame_width_.push_back(pkt->data.frame.width[0]);
encode_frame_height_.push_back(pkt->data.frame.height[0]);
}
unsigned int GetFrameWidth(size_t idx) const {
return encode_frame_width_[idx];
}
unsigned int GetFrameHeight(size_t idx) const {
return encode_frame_height_[idx];
}
virtual void DecompressedFrameHook(const vpx_image_t &img, virtual void DecompressedFrameHook(const vpx_image_t &img,
vpx_codec_pts_t pts) { vpx_codec_pts_t pts) {
frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h)); frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
} }
std::vector<FrameInfo> frame_info_list_; std::vector<FrameInfo> frame_info_list_;
std::vector<unsigned int> encode_frame_width_;
std::vector<unsigned int> encode_frame_height_;
}; };
TEST_P(ResizeTest, TestExternalResizeWorks) { TEST_P(ResizeTest, TestExternalResizeWorks) {
@ -313,9 +296,6 @@ TEST_P(ResizeTest, TestExternalResizeWorks) {
const unsigned int frame = static_cast<unsigned>(info->pts); const unsigned int frame = static_cast<unsigned>(info->pts);
unsigned int expected_w; unsigned int expected_w;
unsigned int expected_h; unsigned int expected_h;
const size_t idx = info - frame_info_list_.begin();
ASSERT_EQ(info->w, GetFrameWidth(idx));
ASSERT_EQ(info->h, GetFrameHeight(idx));
ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w, ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
&expected_h, 0); &expected_h, 0);
EXPECT_EQ(expected_w, info->w) EXPECT_EQ(expected_w, info->w)
@ -484,23 +464,8 @@ class ResizeRealtimeTest
++mismatch_nframes_; ++mismatch_nframes_;
} }
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
ASSERT_NE(static_cast<int>(pkt->data.frame.width[0]), 0);
ASSERT_NE(static_cast<int>(pkt->data.frame.height[0]), 0);
encode_frame_width_.push_back(pkt->data.frame.width[0]);
encode_frame_height_.push_back(pkt->data.frame.height[0]);
}
unsigned int GetMismatchFrames() { return mismatch_nframes_; } unsigned int GetMismatchFrames() { return mismatch_nframes_; }
unsigned int GetFrameWidth(size_t idx) const {
return encode_frame_width_[idx];
}
unsigned int GetFrameHeight(size_t idx) const {
return encode_frame_height_[idx];
}
void DefaultConfig() { void DefaultConfig() {
cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 600; cfg_.rc_buf_optimal_sz = 600;
@ -528,8 +493,6 @@ class ResizeRealtimeTest
bool change_bitrate_; bool change_bitrate_;
double mismatch_psnr_; double mismatch_psnr_;
int mismatch_nframes_; int mismatch_nframes_;
std::vector<unsigned int> encode_frame_width_;
std::vector<unsigned int> encode_frame_height_;
}; };
TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) { TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
@ -619,9 +582,6 @@ TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
int resize_count = 0; int resize_count = 0;
for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin(); for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { info != frame_info_list_.end(); ++info) {
const size_t idx = info - frame_info_list_.begin();
ASSERT_EQ(info->w, GetFrameWidth(idx));
ASSERT_EQ(info->h, GetFrameHeight(idx));
if (info->w != last_w || info->h != last_h) { if (info->w != last_w || info->h != last_h) {
resize_count++; resize_count++;
if (resize_count == 1) { if (resize_count == 1) {

View File

@ -23,7 +23,6 @@
#include "vpx/vpx_codec.h" #include "vpx/vpx_codec.h"
#include "vpx_mem/vpx_mem.h" #include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h" #include "vpx_ports/mem.h"
#include "vpx_ports/vpx_timer.h"
template <typename Function> template <typename Function>
struct TestParams { struct TestParams {
@ -85,7 +84,7 @@ class SADTestBase : public ::testing::TestWithParam<ParamType> {
#endif // CONFIG_VP9_HIGHBITDEPTH #endif // CONFIG_VP9_HIGHBITDEPTH
} }
mask_ = (1 << bit_depth_) - 1; mask_ = (1 << bit_depth_) - 1;
source_stride_ = (params_.width + 63) & ~63; source_stride_ = (params_.width + 31) & ~31;
reference_stride_ = params_.width * 2; reference_stride_ = params_.width * 2;
rnd_.Reset(ACMRandom::DeterministicSeed()); rnd_.Reset(ACMRandom::DeterministicSeed());
} }
@ -109,7 +108,7 @@ class SADTestBase : public ::testing::TestWithParam<ParamType> {
protected: protected:
// Handle blocks up to 4 blocks 64x64 with stride up to 128 // Handle blocks up to 4 blocks 64x64 with stride up to 128
static const int kDataAlignment = 32; static const int kDataAlignment = 16;
static const int kDataBlockSize = 64 * 128; static const int kDataBlockSize = 64 * 128;
static const int kDataBufferSize = 4 * kDataBlockSize; static const int kDataBufferSize = 4 * kDataBlockSize;
@ -464,38 +463,6 @@ TEST_P(SADx4Test, SrcAlignedByWidth) {
source_data_ = tmp_source_data; source_data_ = tmp_source_data;
} }
TEST_P(SADx4Test, DISABLED_Speed) {
int tmp_stride = reference_stride_;
reference_stride_ -= 1;
FillRandom(source_data_, source_stride_);
FillRandom(GetReference(0), reference_stride_);
FillRandom(GetReference(1), reference_stride_);
FillRandom(GetReference(2), reference_stride_);
FillRandom(GetReference(3), reference_stride_);
const int kCountSpeedTestBlock = 500000000 / (params_.width * params_.height);
uint32_t reference_sad[4], exp_sad[4];
vpx_usec_timer timer;
memset(reference_sad, 0, sizeof(reference_sad));
SADs(exp_sad);
vpx_usec_timer_start(&timer);
for (int i = 0; i < kCountSpeedTestBlock; ++i) {
for (int block = 0; block < 4; ++block) {
reference_sad[block] = ReferenceSAD(block);
}
}
vpx_usec_timer_mark(&timer);
for (int block = 0; block < 4; ++block) {
EXPECT_EQ(reference_sad[block], exp_sad[block]) << "block " << block;
}
const int elapsed_time =
static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
printf("sad%dx%dx4 (%2dbit) time: %5d ms\n", params_.width, params_.height,
bit_depth_, elapsed_time);
reference_stride_ = tmp_stride;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// C functions // C functions
const SadMxNParam c_tests[] = { const SadMxNParam c_tests[] = {

View File

@ -28,7 +28,7 @@ namespace {
const int kNumIterations = 10000; const int kNumIterations = 10000;
typedef uint64_t (*SSI16Func)(const int16_t *src, int stride, int size); typedef uint64_t (*SSI16Func)(const int16_t *src, int stride, int size);
typedef ::testing::tuple<SSI16Func, SSI16Func> SumSquaresParam; typedef std::tr1::tuple<SSI16Func, SSI16Func> SumSquaresParam;
class SumSquaresTest : public ::testing::TestWithParam<SumSquaresParam> { class SumSquaresTest : public ::testing::TestWithParam<SumSquaresParam> {
public: public:
@ -102,7 +102,7 @@ TEST_P(SumSquaresTest, ExtremeValues) {
} }
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
#if HAVE_SSE2 #if HAVE_SSE2
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
@ -112,9 +112,8 @@ INSTANTIATE_TEST_CASE_P(
#endif // HAVE_SSE2 #endif // HAVE_SSE2
#if HAVE_MSA #if HAVE_MSA
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(MSA, SumSquaresTest, ::testing::Values(make_tuple(
MSA, SumSquaresTest, &vpx_sum_squares_2d_i16_c,
::testing::Values(make_tuple(&vpx_sum_squares_2d_i16_c, &vpx_sum_squares_2d_i16_msa)));
&vpx_sum_squares_2d_i16_msa)));
#endif // HAVE_MSA #endif // HAVE_MSA
} // namespace } // namespace

View File

@ -18,7 +18,7 @@ namespace {
const int kTestMode = 0; const int kTestMode = 0;
typedef ::testing::tuple<libvpx_test::TestMode, int> SuperframeTestParam; typedef std::tr1::tuple<libvpx_test::TestMode, int> SuperframeTestParam;
class SuperframeTest class SuperframeTest
: public ::libvpx_test::EncoderTest, : public ::libvpx_test::EncoderTest,
@ -31,7 +31,7 @@ class SuperframeTest
virtual void SetUp() { virtual void SetUp() {
InitializeConfig(); InitializeConfig();
const SuperframeTestParam input = GET_PARAM(1); const SuperframeTestParam input = GET_PARAM(1);
const libvpx_test::TestMode mode = ::testing::get<kTestMode>(input); const libvpx_test::TestMode mode = std::tr1::get<kTestMode>(input);
SetMode(mode); SetMode(mode);
sf_count_ = 0; sf_count_ = 0;
sf_count_max_ = INT_MAX; sf_count_max_ = INT_MAX;

File diff suppressed because it is too large Load Diff

789
test/svc_test.cc Normal file
View File

@ -0,0 +1,789 @@
/*
* Copyright (c) 2013 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 <string>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/decode_test_driver.h"
#include "test/i420_video_source.h"
#include "vp9/decoder/vp9_decoder.h"
#include "vpx/svc_context.h"
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
namespace {
using libvpx_test::CodecFactory;
using libvpx_test::Decoder;
using libvpx_test::DxDataIterator;
using libvpx_test::VP9CodecFactory;
class SvcTest : public ::testing::Test {
protected:
static const uint32_t kWidth = 352;
static const uint32_t kHeight = 288;
SvcTest()
: codec_iface_(0), test_file_name_("hantro_collage_w352h288.yuv"),
codec_initialized_(false), decoder_(0) {
memset(&svc_, 0, sizeof(svc_));
memset(&codec_, 0, sizeof(codec_));
memset(&codec_enc_, 0, sizeof(codec_enc_));
}
virtual ~SvcTest() {}
virtual void SetUp() {
svc_.log_level = SVC_LOG_DEBUG;
svc_.log_print = 0;
codec_iface_ = vpx_codec_vp9_cx();
const vpx_codec_err_t res =
vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0);
EXPECT_EQ(VPX_CODEC_OK, res);
codec_enc_.g_w = kWidth;
codec_enc_.g_h = kHeight;
codec_enc_.g_timebase.num = 1;
codec_enc_.g_timebase.den = 60;
codec_enc_.kf_min_dist = 100;
codec_enc_.kf_max_dist = 100;
vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
VP9CodecFactory codec_factory;
decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
tile_columns_ = 0;
tile_rows_ = 0;
}
virtual void TearDown() {
ReleaseEncoder();
delete (decoder_);
}
void InitializeEncoder() {
const vpx_codec_err_t res =
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_OK, res);
vpx_codec_control(&codec_, VP8E_SET_CPUUSED, 4); // Make the test faster
vpx_codec_control(&codec_, VP9E_SET_TILE_COLUMNS, tile_columns_);
vpx_codec_control(&codec_, VP9E_SET_TILE_ROWS, tile_rows_);
codec_initialized_ = true;
}
void ReleaseEncoder() {
vpx_svc_release(&svc_);
if (codec_initialized_) vpx_codec_destroy(&codec_);
codec_initialized_ = false;
}
void GetStatsData(std::string *const stats_buf) {
vpx_codec_iter_t iter = NULL;
const vpx_codec_cx_pkt_t *cx_pkt;
while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
if (cx_pkt->kind == VPX_CODEC_STATS_PKT) {
EXPECT_GT(cx_pkt->data.twopass_stats.sz, 0U);
ASSERT_TRUE(cx_pkt->data.twopass_stats.buf != NULL);
stats_buf->append(static_cast<char *>(cx_pkt->data.twopass_stats.buf),
cx_pkt->data.twopass_stats.sz);
}
}
}
void Pass1EncodeNFrames(const int n, const int layers,
std::string *const stats_buf) {
vpx_codec_err_t res;
ASSERT_GT(n, 0);
ASSERT_GT(layers, 0);
svc_.spatial_layers = layers;
codec_enc_.g_pass = VPX_RC_FIRST_PASS;
InitializeEncoder();
libvpx_test::I420VideoSource video(
test_file_name_, codec_enc_.g_w, codec_enc_.g_h,
codec_enc_.g_timebase.den, codec_enc_.g_timebase.num, 0, 30);
video.Begin();
for (int i = 0; i < n; ++i) {
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
GetStatsData(stats_buf);
video.Next();
}
// Flush encoder and test EOS packet.
res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(), video.duration(),
VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
GetStatsData(stats_buf);
ReleaseEncoder();
}
void StoreFrames(const size_t max_frame_received,
struct vpx_fixed_buf *const outputs,
size_t *const frame_received) {
vpx_codec_iter_t iter = NULL;
const vpx_codec_cx_pkt_t *cx_pkt;
while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
if (cx_pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
const size_t frame_size = cx_pkt->data.frame.sz;
EXPECT_GT(frame_size, 0U);
ASSERT_TRUE(cx_pkt->data.frame.buf != NULL);
ASSERT_LT(*frame_received, max_frame_received);
if (*frame_received == 0)
EXPECT_EQ(1, !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY));
outputs[*frame_received].buf = malloc(frame_size + 16);
ASSERT_TRUE(outputs[*frame_received].buf != NULL);
memcpy(outputs[*frame_received].buf, cx_pkt->data.frame.buf,
frame_size);
outputs[*frame_received].sz = frame_size;
++(*frame_received);
}
}
}
void Pass2EncodeNFrames(std::string *const stats_buf, const int n,
const int layers,
struct vpx_fixed_buf *const outputs) {
vpx_codec_err_t res;
size_t frame_received = 0;
ASSERT_TRUE(outputs != NULL);
ASSERT_GT(n, 0);
ASSERT_GT(layers, 0);
svc_.spatial_layers = layers;
codec_enc_.rc_target_bitrate = 500;
if (codec_enc_.g_pass == VPX_RC_LAST_PASS) {
ASSERT_TRUE(stats_buf != NULL);
ASSERT_GT(stats_buf->size(), 0U);
codec_enc_.rc_twopass_stats_in.buf = &(*stats_buf)[0];
codec_enc_.rc_twopass_stats_in.sz = stats_buf->size();
}
InitializeEncoder();
libvpx_test::I420VideoSource video(
test_file_name_, codec_enc_.g_w, codec_enc_.g_h,
codec_enc_.g_timebase.den, codec_enc_.g_timebase.num, 0, 30);
video.Begin();
for (int i = 0; i < n; ++i) {
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
StoreFrames(n, outputs, &frame_received);
video.Next();
}
// Flush encoder.
res = vpx_svc_encode(&svc_, &codec_, NULL, 0, video.duration(),
VPX_DL_GOOD_QUALITY);
EXPECT_EQ(VPX_CODEC_OK, res);
StoreFrames(n, outputs, &frame_received);
EXPECT_EQ(frame_received, static_cast<size_t>(n));
ReleaseEncoder();
}
void DecodeNFrames(const struct vpx_fixed_buf *const inputs, const int n) {
int decoded_frames = 0;
int received_frames = 0;
ASSERT_TRUE(inputs != NULL);
ASSERT_GT(n, 0);
for (int i = 0; i < n; ++i) {
ASSERT_TRUE(inputs[i].buf != NULL);
ASSERT_GT(inputs[i].sz, 0U);
const vpx_codec_err_t res_dec = decoder_->DecodeFrame(
static_cast<const uint8_t *>(inputs[i].buf), inputs[i].sz);
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
++decoded_frames;
DxDataIterator dec_iter = decoder_->GetDxData();
while (dec_iter.Next() != NULL) {
++received_frames;
}
}
EXPECT_EQ(decoded_frames, n);
EXPECT_EQ(received_frames, n);
}
void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
const int num_super_frames,
const int remained_spatial_layers) {
ASSERT_TRUE(inputs != NULL);
ASSERT_GT(num_super_frames, 0);
ASSERT_GT(remained_spatial_layers, 0);
for (int i = 0; i < num_super_frames; ++i) {
uint32_t frame_sizes[8] = { 0 };
int frame_count = 0;
int frames_found = 0;
int frame;
ASSERT_TRUE(inputs[i].buf != NULL);
ASSERT_GT(inputs[i].sz, 0U);
vpx_codec_err_t res = vp9_parse_superframe_index(
static_cast<const uint8_t *>(inputs[i].buf), inputs[i].sz,
frame_sizes, &frame_count, NULL, NULL);
ASSERT_EQ(VPX_CODEC_OK, res);
if (frame_count == 0) {
// There's no super frame but only a single frame.
ASSERT_EQ(1, remained_spatial_layers);
} else {
// Found a super frame.
uint8_t *frame_data = static_cast<uint8_t *>(inputs[i].buf);
uint8_t *frame_start = frame_data;
for (frame = 0; frame < frame_count; ++frame) {
// Looking for a visible frame.
if (frame_data[0] & 0x02) {
++frames_found;
if (frames_found == remained_spatial_layers) break;
}
frame_data += frame_sizes[frame];
}
ASSERT_LT(frame, frame_count)
<< "Couldn't find a visible frame. "
<< "remained_spatial_layers: " << remained_spatial_layers
<< " super_frame: " << i;
if (frame == frame_count - 1) continue;
frame_data += frame_sizes[frame];
// We need to add one more frame for multiple frame contexts.
uint8_t marker =
static_cast<const uint8_t *>(inputs[i].buf)[inputs[i].sz - 1];
const uint32_t mag = ((marker >> 3) & 0x3) + 1;
const size_t index_sz = 2 + mag * frame_count;
const size_t new_index_sz = 2 + mag * (frame + 1);
marker &= 0x0f8;
marker |= frame;
// Copy existing frame sizes.
memmove(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
new_index_sz - 2);
// New marker.
frame_data[0] = marker;
frame_data += (mag * (frame + 1) + 1);
*frame_data++ = marker;
inputs[i].sz = frame_data - frame_start;
}
}
}
void FreeBitstreamBuffers(struct vpx_fixed_buf *const inputs, const int n) {
ASSERT_TRUE(inputs != NULL);
ASSERT_GT(n, 0);
for (int i = 0; i < n; ++i) {
free(inputs[i].buf);
inputs[i].buf = NULL;
inputs[i].sz = 0;
}
}
SvcContext svc_;
vpx_codec_ctx_t codec_;
struct vpx_codec_enc_cfg codec_enc_;
vpx_codec_iface_t *codec_iface_;
std::string test_file_name_;
bool codec_initialized_;
Decoder *decoder_;
int tile_columns_;
int tile_rows_;
};
TEST_F(SvcTest, SvcInit) {
// test missing parameters
vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
svc_.spatial_layers = 6; // too many layers
res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
svc_.spatial_layers = 0; // use default layers
InitializeEncoder();
EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers);
}
TEST_F(SvcTest, InitTwoLayers) {
svc_.spatial_layers = 2;
InitializeEncoder();
}
TEST_F(SvcTest, InvalidOptions) {
vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "not-an-option=1");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
}
TEST_F(SvcTest, SetLayersOption) {
vpx_codec_err_t res = vpx_svc_set_options(&svc_, "spatial-layers=3");
EXPECT_EQ(VPX_CODEC_OK, res);
InitializeEncoder();
EXPECT_EQ(3, svc_.spatial_layers);
}
TEST_F(SvcTest, SetMultipleOptions) {
vpx_codec_err_t res =
vpx_svc_set_options(&svc_, "spatial-layers=2 scale-factors=1/3,2/3");
EXPECT_EQ(VPX_CODEC_OK, res);
InitializeEncoder();
EXPECT_EQ(2, svc_.spatial_layers);
}
TEST_F(SvcTest, SetScaleFactorsOption) {
svc_.spatial_layers = 2;
vpx_codec_err_t res =
vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "scale-factors=1/3, 3*3");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "scale-factors=1/3");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3");
EXPECT_EQ(VPX_CODEC_OK, res);
InitializeEncoder();
}
TEST_F(SvcTest, SetQuantizersOption) {
svc_.spatial_layers = 2;
vpx_codec_err_t res = vpx_svc_set_options(&svc_, "max-quantizers=nothing");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "min-quantizers=nothing");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "max-quantizers=40");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "min-quantizers=40");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "max-quantizers=30,30 min-quantizers=40,40");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "max-quantizers=40,40 min-quantizers=30,30");
InitializeEncoder();
}
TEST_F(SvcTest, SetAutoAltRefOption) {
svc_.spatial_layers = 5;
vpx_codec_err_t res = vpx_svc_set_options(&svc_, "auto-alt-refs=none");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
res = vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1,1,0");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
InitializeEncoder();
}
// Test that decoder can handle an SVC frame as the first frame in a sequence.
TEST_F(SvcTest, OnePassEncodeOneFrame) {
codec_enc_.g_pass = VPX_RC_ONE_PASS;
vpx_fixed_buf output = vpx_fixed_buf();
Pass2EncodeNFrames(NULL, 1, 2, &output);
DecodeNFrames(&output, 1);
FreeBitstreamBuffers(&output, 1);
}
TEST_F(SvcTest, OnePassEncodeThreeFrames) {
codec_enc_.g_pass = VPX_RC_ONE_PASS;
codec_enc_.g_lag_in_frames = 0;
vpx_fixed_buf outputs[3];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
DecodeNFrames(&outputs[0], 3);
FreeBitstreamBuffers(&outputs[0], 3);
}
TEST_F(SvcTest, TwoPassEncode10Frames) {
// First pass encode
std::string stats_buf;
Pass1EncodeNFrames(10, 2, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode20FramesWithAltRef) {
// First pass encode
std::string stats_buf;
Pass1EncodeNFrames(20, 2, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
vpx_fixed_buf outputs[20];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
DecodeNFrames(&outputs[0], 20);
FreeBitstreamBuffers(&outputs[0], 20);
}
TEST_F(SvcTest, TwoPassEncode2SpatialLayersDecodeBaseLayerOnly) {
// First pass encode
std::string stats_buf;
Pass1EncodeNFrames(10, 2, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
DropEnhancementLayers(&outputs[0], 10, 1);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode5SpatialLayersDecode54321Layers) {
// First pass encode
std::string stats_buf;
Pass1EncodeNFrames(10, 5, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
DropEnhancementLayers(&outputs[0], 10, 4);
DecodeNFrames(&outputs[0], 10);
DropEnhancementLayers(&outputs[0], 10, 3);
DecodeNFrames(&outputs[0], 10);
DropEnhancementLayers(&outputs[0], 10, 2);
DecodeNFrames(&outputs[0], 10);
DropEnhancementLayers(&outputs[0], 10, 1);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode2SNRLayers) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
Pass1EncodeNFrames(20, 2, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 scale-factors=1/1,1/1");
vpx_fixed_buf outputs[20];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
DecodeNFrames(&outputs[0], 20);
FreeBitstreamBuffers(&outputs[0], 20);
}
TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
Pass1EncodeNFrames(20, 3, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1");
vpx_fixed_buf outputs[20];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
DecodeNFrames(&outputs[0], 20);
DropEnhancementLayers(&outputs[0], 20, 2);
DecodeNFrames(&outputs[0], 20);
DropEnhancementLayers(&outputs[0], 20, 1);
DecodeNFrames(&outputs[0], 20);
FreeBitstreamBuffers(&outputs[0], 20);
}
TEST_F(SvcTest, SetMultipleFrameContextsOption) {
svc_.spatial_layers = 5;
vpx_codec_err_t res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
EXPECT_EQ(VPX_CODEC_OK, res);
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
svc_.spatial_layers = 2;
res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
InitializeEncoder();
}
TEST_F(SvcTest, TwoPassEncode2SpatialLayersWithMultipleFrameContexts) {
// First pass encode
std::string stats_buf;
Pass1EncodeNFrames(10, 2, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
codec_enc_.g_error_resilient = 0;
vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest,
TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer) {
// First pass encode
std::string stats_buf;
Pass1EncodeNFrames(10, 2, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
codec_enc_.g_error_resilient = 0;
vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
DropEnhancementLayers(&outputs[0], 10, 1);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContexts) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
Pass1EncodeNFrames(10, 2, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
codec_enc_.g_error_resilient = 0;
vpx_svc_set_options(&svc_,
"auto-alt-refs=1,1 scale-factors=1/1,1/1 "
"multi-frame-contexts=1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest,
TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
Pass1EncodeNFrames(10, 3, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
codec_enc_.g_error_resilient = 0;
vpx_svc_set_options(&svc_,
"auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1 "
"multi-frame-contexts=1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 3, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
DropEnhancementLayers(&outputs[0], 10, 2);
DecodeNFrames(&outputs[0], 10);
DropEnhancementLayers(&outputs[0], 10, 1);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode2TemporalLayers) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1");
svc_.temporal_layers = 2;
Pass1EncodeNFrames(10, 1, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
svc_.temporal_layers = 2;
vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContexts) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1");
svc_.temporal_layers = 2;
Pass1EncodeNFrames(10, 1, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
svc_.temporal_layers = 2;
codec_enc_.g_error_resilient = 0;
vpx_svc_set_options(&svc_,
"auto-alt-refs=1 scale-factors=1/1 "
"multi-frame-contexts=1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode2TemporalLayersDecodeBaseLayer) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1");
svc_.temporal_layers = 2;
Pass1EncodeNFrames(10, 1, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
svc_.temporal_layers = 2;
vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
vpx_fixed_buf base_layer[5];
for (int i = 0; i < 5; ++i) base_layer[i] = outputs[i * 2];
DecodeNFrames(&base_layer[0], 5);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest,
TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1");
svc_.temporal_layers = 2;
Pass1EncodeNFrames(10, 1, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
svc_.temporal_layers = 2;
codec_enc_.g_error_resilient = 0;
vpx_svc_set_options(&svc_,
"auto-alt-refs=1 scale-factors=1/1 "
"multi-frame-contexts=1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
vpx_fixed_buf base_layer[5];
for (int i = 0; i < 5; ++i) base_layer[i] = outputs[i * 2];
DecodeNFrames(&base_layer[0], 5);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithTiles) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1");
svc_.temporal_layers = 2;
Pass1EncodeNFrames(10, 1, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
svc_.temporal_layers = 2;
vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
codec_enc_.g_w = 704;
codec_enc_.g_h = 144;
tile_columns_ = 1;
tile_rows_ = 1;
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContextsAndTiles) {
// First pass encode
std::string stats_buf;
vpx_svc_set_options(&svc_, "scale-factors=1/1");
svc_.temporal_layers = 2;
Pass1EncodeNFrames(10, 1, &stats_buf);
// Second pass encode
codec_enc_.g_pass = VPX_RC_LAST_PASS;
svc_.temporal_layers = 2;
codec_enc_.g_error_resilient = 0;
codec_enc_.g_w = 704;
codec_enc_.g_h = 144;
tile_columns_ = 1;
tile_rows_ = 1;
vpx_svc_set_options(&svc_,
"auto-alt-refs=1 scale-factors=1/1 "
"multi-frame-contexts=1");
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
} // namespace

View File

@ -734,8 +734,6 @@ endif # CONFIG_VP9_HIGHBITDEPTH
# Invalid files for testing libvpx error checking. # Invalid files for testing libvpx error checking.
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-1443.ivf LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-1443.ivf
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-1443.ivf.res LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-1443.ivf.res
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-token-partition.ivf
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-token-partition.ivf.res
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf.res LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf.res
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm

View File

@ -852,7 +852,5 @@ e402cbbf9e550ae017a1e9f1f73931c1d18474e8 *invalid-crbug-667044.webm
d3964f9dad9f60363c81b688324d95b4ec7c8038 *invalid-crbug-667044.webm.res d3964f9dad9f60363c81b688324d95b4ec7c8038 *invalid-crbug-667044.webm.res
fd9df7f3f6992af1d7a9dde975c9a0d6f28c053d *invalid-bug-1443.ivf fd9df7f3f6992af1d7a9dde975c9a0d6f28c053d *invalid-bug-1443.ivf
fd3020fa6e9ca5966206738654c97dec313b0a95 *invalid-bug-1443.ivf.res fd3020fa6e9ca5966206738654c97dec313b0a95 *invalid-bug-1443.ivf.res
1a0e405606939f2febab1a21b30c37cb8f2c8cb1 *invalid-token-partition.ivf
90a8a95e7024f015b87f5483a65036609b3d1b74 *invalid-token-partition.ivf.res
17696cd21e875f1d6e5d418cbf89feab02c8850a *vp90-2-22-svc_1280x720_1.webm 17696cd21e875f1d6e5d418cbf89feab02c8850a *vp90-2-22-svc_1280x720_1.webm
e2f9e1e47a791b4e939a9bdc50bf7a25b3761f77 *vp90-2-22-svc_1280x720_1.webm.md5 e2f9e1e47a791b4e939a9bdc50bf7a25b3761f77 *vp90-2-22-svc_1280x720_1.webm.md5

View File

@ -22,9 +22,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../y4minput.h ../y4minput.c
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += altref_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += altref_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += aq_segment_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += aq_segment_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += alt_ref_aq_segment_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += alt_ref_aq_segment_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += vp8_datarate_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += datarate_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += vp9_datarate_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += svc_datarate_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_api_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_api_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += error_resilience_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += error_resilience_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += i420_video_source.h LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += i420_video_source.h
@ -171,6 +169,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_quantize_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_subtract_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_subtract_test.cc
ifeq ($(CONFIG_VP9_ENCODER),yes) ifeq ($(CONFIG_VP9_ENCODER),yes)
LIBVPX_TEST_SRCS-$(CONFIG_SPATIAL_SVC) += svc_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += blockiness_test.cc LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += blockiness_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += consistency_test.cc LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += consistency_test.cc
endif endif

View File

@ -61,6 +61,7 @@ int main(int argc, char **argv) {
#if !CONFIG_SHARED #if !CONFIG_SHARED
// Shared library builds don't support whitebox tests // Shared library builds don't support whitebox tests
// that exercise internal symbols. // that exercise internal symbols.
#if CONFIG_VP8 #if CONFIG_VP8
vp8_rtcd(); vp8_rtcd();
#endif // CONFIG_VP8 #endif // CONFIG_VP8

View File

@ -31,7 +31,7 @@ namespace {
const int kThreads = 0; const int kThreads = 0;
const int kFileName = 1; const int kFileName = 1;
typedef ::testing::tuple<int, const char *> DecodeParam; typedef std::tr1::tuple<int, const char *> DecodeParam;
class TestVectorTest : public ::libvpx_test::DecoderTest, class TestVectorTest : public ::libvpx_test::DecoderTest,
public ::libvpx_test::CodecTestWithParam<DecodeParam> { public ::libvpx_test::CodecTestWithParam<DecodeParam> {
@ -88,12 +88,12 @@ class TestVectorTest : public ::libvpx_test::DecoderTest,
// the test failed. // the test failed.
TEST_P(TestVectorTest, MD5Match) { TEST_P(TestVectorTest, MD5Match) {
const DecodeParam input = GET_PARAM(1); const DecodeParam input = GET_PARAM(1);
const std::string filename = ::testing::get<kFileName>(input); const std::string filename = std::tr1::get<kFileName>(input);
vpx_codec_flags_t flags = 0; vpx_codec_flags_t flags = 0;
vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
char str[256]; char str[256];
cfg.threads = ::testing::get<kThreads>(input); cfg.threads = std::tr1::get<kThreads>(input);
snprintf(str, sizeof(str) / sizeof(str[0]) - 1, "file: %s threads: %d", snprintf(str, sizeof(str) / sizeof(str[0]) - 1, "file: %s threads: %d",
filename.c_str(), cfg.threads); filename.c_str(), cfg.threads);

View File

@ -27,8 +27,8 @@
namespace { namespace {
using libvpx_test::ACMRandom;
using std::string; using std::string;
using libvpx_test::ACMRandom;
#if CONFIG_WEBM_IO #if CONFIG_WEBM_IO

View File

@ -17,7 +17,7 @@
#include "vpx/vpx_image.h" #include "vpx/vpx_image.h"
// Macros // Macros
#define GET_PARAM(k) ::testing::get<k>(GetParam()) #define GET_PARAM(k) std::tr1::get<k>(GetParam())
inline double compute_psnr(const vpx_image_t *img1, const vpx_image_t *img2) { inline double compute_psnr(const vpx_image_t *img1, const vpx_image_t *img2) {
assert((img1->fmt == img2->fmt) && (img1->d_w == img2->d_w) && assert((img1->fmt == img2->fmt) && (img1->d_w == img2->d_w) &&

View File

@ -1,513 +0,0 @@
/*
* Copyright (c) 2012 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 "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "vpx/vpx_codec.h"
namespace {
class DatarateTestLarge
: public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
public:
DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
virtual ~DatarateTestLarge() {}
protected:
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
set_cpu_used_ = GET_PARAM(2);
ResetModel();
}
virtual void ResetModel() {
last_pts_ = 0;
bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
frame_number_ = 0;
first_drop_ = 0;
bits_total_ = 0;
duration_ = 0.0;
denoiser_offon_test_ = 0;
denoiser_offon_period_ = -1;
gf_boost_ = 0;
use_roi_ = false;
}
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) {
if (video->frame() == 0) {
encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
encoder->Control(VP8E_SET_GF_CBR_BOOST_PCT, gf_boost_);
}
if (use_roi_) {
encoder->Control(VP8E_SET_ROI_MAP, &roi_);
}
if (denoiser_offon_test_) {
ASSERT_GT(denoiser_offon_period_, 0)
<< "denoiser_offon_period_ is not positive.";
if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
// Flip denoiser_on_ periodically
denoiser_on_ ^= 1;
}
encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
}
const vpx_rational_t tb = video->timebase();
timebase_ = static_cast<double>(tb.num) / tb.den;
duration_ = 0;
}
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
// Time since last timestamp = duration.
vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
// TODO(jimbankoski): Remove these lines when the issue:
// http://code.google.com/p/webm/issues/detail?id=496 is fixed.
// For now the codec assumes buffer starts at starting buffer rate
// plus one frame's time.
if (last_pts_ == 0) duration = 1;
// Add to the buffer the bits we'd expect from a constant bitrate server.
bits_in_buffer_model_ += static_cast<int64_t>(
duration * timebase_ * cfg_.rc_target_bitrate * 1000);
/* Test the buffer model here before subtracting the frame. Do so because
* the way the leaky bucket model works in libvpx is to allow the buffer to
* empty - and then stop showing frames until we've got enough bits to
* show one. As noted in comment below (issue 495), this does not currently
* apply to key frames. For now exclude key frames in condition below. */
const bool key_frame =
(pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
if (!key_frame) {
ASSERT_GE(bits_in_buffer_model_, 0)
<< "Buffer Underrun at frame " << pkt->data.frame.pts;
}
const int64_t frame_size_in_bits = pkt->data.frame.sz * 8;
// Subtract from the buffer the bits associated with a played back frame.
bits_in_buffer_model_ -= frame_size_in_bits;
// Update the running total of bits for end of test datarate checks.
bits_total_ += frame_size_in_bits;
// If first drop not set and we have a drop set it to this time.
if (!first_drop_ && duration > 1) first_drop_ = last_pts_ + 1;
// Update the most recent pts.
last_pts_ = pkt->data.frame.pts;
// We update this so that we can calculate the datarate minus the last
// frame encoded in the file.
bits_in_last_frame_ = frame_size_in_bits;
++frame_number_;
}
virtual void EndPassHook(void) {
if (bits_total_) {
const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit
duration_ = (last_pts_ + 1) * timebase_;
// Effective file datarate includes the time spent prebuffering.
effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0 /
(cfg_.rc_buf_initial_sz / 1000.0 + duration_);
file_datarate_ = file_size_in_kb / duration_;
}
}
vpx_codec_pts_t last_pts_;
int64_t bits_in_buffer_model_;
double timebase_;
int frame_number_;
vpx_codec_pts_t first_drop_;
int64_t bits_total_;
double duration_;
double file_datarate_;
double effective_datarate_;
int64_t bits_in_last_frame_;
int denoiser_on_;
int denoiser_offon_test_;
int denoiser_offon_period_;
int set_cpu_used_;
int gf_boost_;
bool use_roi_;
vpx_roi_map_t roi_;
};
#if CONFIG_TEMPORAL_DENOISING
// Check basic datarate targeting, for a single bitrate, but loop over the
// various denoiser settings.
TEST_P(DatarateTestLarge, DenoiserLevels) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
for (int j = 1; j < 5; ++j) {
// Run over the denoiser levels.
// For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
// refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
// denoiserOnAggressive, and denoiserOnAdaptive.
denoiser_on_ = j;
cfg_.rc_target_bitrate = 300;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
}
// Check basic datarate targeting, for a single bitrate, when denoiser is off
// and on.
TEST_P(DatarateTestLarge, DenoiserOffOn) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 299);
cfg_.rc_target_bitrate = 300;
ResetModel();
// The denoiser is off by default.
denoiser_on_ = 0;
// Set the offon test flag.
denoiser_offon_test_ = 1;
denoiser_offon_period_ = 100;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
#endif // CONFIG_TEMPORAL_DENOISING
TEST_P(DatarateTestLarge, BasicBufferModel) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
// 2 pass cbr datarate control has a bug hidden by the small # of
// frames selected in this encode. The problem is that even if the buffer is
// negative we produce a keyframe on a cutscene. Ignoring datarate
// constraints
// TODO(jimbankoski): ( Fix when issue
// http://code.google.com/p/webm/issues/detail?id=495 is addressed. )
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
// There is an issue for low bitrates in real-time mode, where the
// effective_datarate slightly overshoots the target bitrate.
// This is same the issue as noted about (#495).
// TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
// when the issue is resolved.
for (int i = 100; i < 800; i += 200) {
cfg_.rc_target_bitrate = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
}
TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_max_quantizer = 36;
cfg_.rc_end_usage = VPX_CBR;
cfg_.rc_target_bitrate = 200;
cfg_.kf_mode = VPX_KF_DISABLED;
const int frame_count = 40;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, frame_count);
// Here we check that the first dropped frame gets earlier and earlier
// as the drop frame threshold is increased.
const int kDropFrameThreshTestStep = 30;
vpx_codec_pts_t last_drop = frame_count;
for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
cfg_.rc_dropframe_thresh = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_LE(first_drop_, last_drop)
<< " The first dropped frame for drop_thresh " << i
<< " > first dropped frame for drop_thresh "
<< i - kDropFrameThreshTestStep;
last_drop = first_drop_;
}
}
TEST_P(DatarateTestLarge, DropFramesMultiThreads) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 30;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_threads = 2;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
cfg_.rc_target_bitrate = 200;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
class DatarateTestRealTime : public DatarateTestLarge {
public:
virtual ~DatarateTestRealTime() {}
};
#if CONFIG_TEMPORAL_DENOISING
// Check basic datarate targeting, for a single bitrate, but loop over the
// various denoiser settings.
TEST_P(DatarateTestRealTime, DenoiserLevels) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
for (int j = 1; j < 5; ++j) {
// Run over the denoiser levels.
// For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
// refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
// denoiserOnAggressive, and denoiserOnAdaptive.
denoiser_on_ = j;
cfg_.rc_target_bitrate = 300;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
}
// Check basic datarate targeting, for a single bitrate, when denoiser is off
// and on.
TEST_P(DatarateTestRealTime, DenoiserOffOn) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 299);
cfg_.rc_target_bitrate = 300;
ResetModel();
// The denoiser is off by default.
denoiser_on_ = 0;
// Set the offon test flag.
denoiser_offon_test_ = 1;
denoiser_offon_period_ = 100;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
#endif // CONFIG_TEMPORAL_DENOISING
TEST_P(DatarateTestRealTime, BasicBufferModel) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
// 2 pass cbr datarate control has a bug hidden by the small # of
// frames selected in this encode. The problem is that even if the buffer is
// negative we produce a keyframe on a cutscene, ignoring datarate
// constraints
// TODO(jimbankoski): Fix when issue
// http://bugs.chromium.org/p/webm/issues/detail?id=495 is addressed.
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
// There is an issue for low bitrates in real-time mode, where the
// effective_datarate slightly overshoots the target bitrate.
// This is same the issue as noted above (#495).
// TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
// when the issue is resolved.
for (int i = 100; i <= 700; i += 200) {
cfg_.rc_target_bitrate = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
}
TEST_P(DatarateTestRealTime, ChangingDropFrameThresh) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_max_quantizer = 36;
cfg_.rc_end_usage = VPX_CBR;
cfg_.rc_target_bitrate = 200;
cfg_.kf_mode = VPX_KF_DISABLED;
const int frame_count = 40;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, frame_count);
// Check that the first dropped frame gets earlier and earlier
// as the drop frame threshold is increased.
const int kDropFrameThreshTestStep = 30;
vpx_codec_pts_t last_drop = frame_count;
for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
cfg_.rc_dropframe_thresh = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_LE(first_drop_, last_drop)
<< " The first dropped frame for drop_thresh " << i
<< " > first dropped frame for drop_thresh "
<< i - kDropFrameThreshTestStep;
last_drop = first_drop_;
}
}
TEST_P(DatarateTestRealTime, DropFramesMultiThreads) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 30;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
// Encode using multiple threads.
cfg_.g_threads = 2;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
cfg_.rc_target_bitrate = 200;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
TEST_P(DatarateTestRealTime, RegionOfInterest) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 0;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
// Encode using multiple threads.
cfg_.g_threads = 2;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
cfg_.rc_target_bitrate = 450;
cfg_.g_w = 352;
cfg_.g_h = 288;
ResetModel();
// Set ROI parameters
use_roi_ = true;
memset(&roi_, 0, sizeof(roi_));
roi_.rows = (cfg_.g_h + 15) / 16;
roi_.cols = (cfg_.g_w + 15) / 16;
roi_.delta_q[0] = 0;
roi_.delta_q[1] = -20;
roi_.delta_q[2] = 0;
roi_.delta_q[3] = 0;
roi_.delta_lf[0] = 0;
roi_.delta_lf[1] = -20;
roi_.delta_lf[2] = 0;
roi_.delta_lf[3] = 0;
roi_.static_threshold[0] = 0;
roi_.static_threshold[1] = 1000;
roi_.static_threshold[2] = 0;
roi_.static_threshold[3] = 0;
// Use 2 states: 1 is center square, 0 is the rest.
roi_.roi_map =
(uint8_t *)calloc(roi_.rows * roi_.cols, sizeof(*roi_.roi_map));
for (unsigned int i = 0; i < roi_.rows; ++i) {
for (unsigned int j = 0; j < roi_.cols; ++j) {
if (i > (roi_.rows >> 2) && i < ((roi_.rows * 3) >> 2) &&
j > (roi_.cols >> 2) && j < ((roi_.cols * 3) >> 2)) {
roi_.roi_map[i * roi_.cols + j] = 1;
}
}
}
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
free(roi_.roi_map);
}
TEST_P(DatarateTestRealTime, GFBoost) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 0;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_error_resilient = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
cfg_.rc_target_bitrate = 300;
ResetModel();
// Apply a gf boost.
gf_boost_ = 50;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
<< " The datarate for the file missed the target!";
}
VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES,
::testing::Values(0));
VP8_INSTANTIATE_TEST_CASE(DatarateTestRealTime,
::testing::Values(::libvpx_test::kRealTime),
::testing::Values(-6, -12));
} // namespace

View File

@ -35,7 +35,7 @@ typedef int64_t (*HBDBlockErrorFunc)(const tran_low_t *coeff,
intptr_t block_size, int64_t *ssz, intptr_t block_size, int64_t *ssz,
int bps); int bps);
typedef ::testing::tuple<HBDBlockErrorFunc, HBDBlockErrorFunc, vpx_bit_depth_t> typedef std::tr1::tuple<HBDBlockErrorFunc, HBDBlockErrorFunc, vpx_bit_depth_t>
BlockErrorParam; BlockErrorParam;
typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff, typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff,
@ -168,7 +168,7 @@ TEST_P(BlockErrorTest, ExtremeValues) {
<< "First failed at test case " << first_failure; << "First failed at test case " << first_failure;
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
#if HAVE_SSE2 #if HAVE_SSE2
const BlockErrorParam sse2_block_error_tests[] = { const BlockErrorParam sse2_block_error_tests[] = {

View File

@ -1,839 +0,0 @@
/*
* Copyright (c) 2012 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 "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "vpx/vpx_codec.h"
#include "vpx_ports/bitops.h"
namespace {
class DatarateTestVP9 : public ::libvpx_test::EncoderTest {
public:
explicit DatarateTestVP9(const ::libvpx_test::CodecFactory *codec)
: EncoderTest(codec) {}
protected:
virtual ~DatarateTestVP9() {}
virtual void ResetModel() {
last_pts_ = 0;
bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
frame_number_ = 0;
tot_frame_number_ = 0;
first_drop_ = 0;
num_drops_ = 0;
// Denoiser is off by default.
denoiser_on_ = 0;
// For testing up to 3 layers.
for (int i = 0; i < 3; ++i) {
bits_total_[i] = 0;
}
denoiser_offon_test_ = 0;
denoiser_offon_period_ = -1;
frame_parallel_decoding_mode_ = 1;
use_roi_ = false;
}
//
// Frame flags and layer id for temporal layers.
//
// For two layers, test pattern is:
// 1 3
// 0 2 .....
// For three layers, test pattern is:
// 1 3 5 7
// 2 6
// 0 4 ....
// LAST is always update on base/layer 0, GOLDEN is updated on layer 1.
// For this 3 layer example, the 2nd enhancement layer (layer 2) updates
// the altref frame.
static int GetFrameFlags(int frame_num, int num_temp_layers) {
int frame_flags = 0;
if (num_temp_layers == 2) {
if (frame_num % 2 == 0) {
// Layer 0: predict from L and ARF, update L.
frame_flags =
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
} else {
// Layer 1: predict from L, G and ARF, and update G.
frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_ENTROPY;
}
} else if (num_temp_layers == 3) {
if (frame_num % 4 == 0) {
// Layer 0: predict from L and ARF; update L.
frame_flags =
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
} else if ((frame_num - 2) % 4 == 0) {
// Layer 1: predict from L, G, ARF; update G.
frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
} else if ((frame_num - 1) % 2 == 0) {
// Layer 2: predict from L, G, ARF; update ARF.
frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
}
}
return frame_flags;
}
static int SetLayerId(int frame_num, int num_temp_layers) {
int layer_id = 0;
if (num_temp_layers == 2) {
if (frame_num % 2 == 0) {
layer_id = 0;
} else {
layer_id = 1;
}
} else if (num_temp_layers == 3) {
if (frame_num % 4 == 0) {
layer_id = 0;
} else if ((frame_num - 2) % 4 == 0) {
layer_id = 1;
} else if ((frame_num - 1) % 2 == 0) {
layer_id = 2;
}
}
return layer_id;
}
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) {
if (video->frame() == 0) encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
if (denoiser_offon_test_) {
ASSERT_GT(denoiser_offon_period_, 0)
<< "denoiser_offon_period_ is not positive.";
if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
// Flip denoiser_on_ periodically
denoiser_on_ ^= 1;
}
}
encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
encoder->Control(VP9E_SET_TILE_COLUMNS, get_msb(cfg_.g_threads));
encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING,
frame_parallel_decoding_mode_);
if (use_roi_) {
encoder->Control(VP9E_SET_ROI_MAP, &roi_);
}
if (cfg_.ts_number_layers > 1) {
if (video->frame() == 0) {
encoder->Control(VP9E_SET_SVC, 1);
}
vpx_svc_layer_id_t layer_id;
layer_id.spatial_layer_id = 0;
frame_flags_ = GetFrameFlags(video->frame(), cfg_.ts_number_layers);
layer_id.temporal_layer_id =
SetLayerId(video->frame(), cfg_.ts_number_layers);
encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
}
const vpx_rational_t tb = video->timebase();
timebase_ = static_cast<double>(tb.num) / tb.den;
duration_ = 0;
}
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
// Time since last timestamp = duration.
vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
if (duration > 1) {
// If first drop not set and we have a drop set it to this time.
if (!first_drop_) first_drop_ = last_pts_ + 1;
// Update the number of frame drops.
num_drops_ += static_cast<int>(duration - 1);
// Update counter for total number of frames (#frames input to encoder).
// Needed for setting the proper layer_id below.
tot_frame_number_ += static_cast<int>(duration - 1);
}
int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
// Add to the buffer the bits we'd expect from a constant bitrate server.
bits_in_buffer_model_ += static_cast<int64_t>(
duration * timebase_ * cfg_.rc_target_bitrate * 1000);
// Buffer should not go negative.
ASSERT_GE(bits_in_buffer_model_, 0)
<< "Buffer Underrun at frame " << pkt->data.frame.pts;
const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
// Update the total encoded bits. For temporal layers, update the cumulative
// encoded bits per layer.
for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
bits_total_[i] += frame_size_in_bits;
}
// Update the most recent pts.
last_pts_ = pkt->data.frame.pts;
++frame_number_;
++tot_frame_number_;
}
virtual void EndPassHook(void) {
for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
++layer) {
duration_ = (last_pts_ + 1) * timebase_;
if (bits_total_[layer]) {
// Effective file datarate:
effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
}
}
}
vpx_codec_pts_t last_pts_;
double timebase_;
int frame_number_; // Counter for number of non-dropped/encoded frames.
int tot_frame_number_; // Counter for total number of input frames.
int64_t bits_total_[3];
double duration_;
double effective_datarate_[3];
int set_cpu_used_;
int64_t bits_in_buffer_model_;
vpx_codec_pts_t first_drop_;
int num_drops_;
int denoiser_on_;
int denoiser_offon_test_;
int denoiser_offon_period_;
int frame_parallel_decoding_mode_;
bool use_roi_;
vpx_roi_map_t roi_;
};
// Params: test mode, speed setting and index for bitrate array.
class DatarateTestVP9Large
: public DatarateTestVP9,
public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode, int,
int> {
public:
DatarateTestVP9Large() : DatarateTestVP9(GET_PARAM(0)) {}
protected:
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
set_cpu_used_ = GET_PARAM(2);
ResetModel();
}
};
// Params: test mode, speed setting.
class DatarateTestVP9LargeOneBR
: public DatarateTestVP9,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
public:
DatarateTestVP9LargeOneBR() : DatarateTestVP9(GET_PARAM(0)) {}
protected:
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
set_cpu_used_ = GET_PARAM(2);
ResetModel();
}
};
// Check basic rate targeting for VBR mode with 0 lag.
TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagZero) {
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.g_error_resilient = 0;
cfg_.rc_end_usage = VPX_VBR;
cfg_.g_lag_in_frames = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
const int bitrates[2] = { 400, 800 };
const int bitrate_index = GET_PARAM(3);
if (bitrate_index > 1) return;
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.35)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic rate targeting for VBR mode with non-zero lag.
TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagNonZero) {
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.g_error_resilient = 0;
cfg_.rc_end_usage = VPX_VBR;
// For non-zero lag, rate control will work (be within bounds) for
// real-time mode.
if (deadline_ == VPX_DL_REALTIME) {
cfg_.g_lag_in_frames = 15;
} else {
cfg_.g_lag_in_frames = 0;
}
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
const int bitrates[2] = { 400, 800 };
const int bitrate_index = GET_PARAM(3);
if (bitrate_index > 1) return;
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.30)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic rate targeting for VBR mode with non-zero lag, with
// frame_parallel_decoding_mode off. This enables the adapt_coeff/mode/mv probs
// since error_resilience is off.
TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagNonZeroFrameParDecOff) {
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.g_error_resilient = 0;
cfg_.rc_end_usage = VPX_VBR;
// For non-zero lag, rate control will work (be within bounds) for
// real-time mode.
if (deadline_ == VPX_DL_REALTIME) {
cfg_.g_lag_in_frames = 15;
} else {
cfg_.g_lag_in_frames = 0;
}
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
const int bitrates[2] = { 400, 800 };
const int bitrate_index = GET_PARAM(3);
if (bitrate_index > 1) return;
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
frame_parallel_decoding_mode_ = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.35)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic rate targeting for CBR mode.
TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
const int bitrates[4] = { 150, 350, 550, 750 };
const int bitrate_index = GET_PARAM(3);
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic rate targeting for CBR mode, with frame_parallel_decoding_mode
// off( and error_resilience off).
TEST_P(DatarateTestVP9Large, BasicRateTargetingFrameParDecOff) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
cfg_.g_error_resilient = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
const int bitrates[4] = { 150, 350, 550, 750 };
const int bitrate_index = GET_PARAM(3);
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
frame_parallel_decoding_mode_ = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic rate targeting for CBR mode, with 2 threads and dropped frames.
TEST_P(DatarateTestVP9LargeOneBR, BasicRateTargetingDropFramesMultiThreads) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 30;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
// Encode using multiple threads.
cfg_.g_threads = 2;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
cfg_.rc_target_bitrate = 200;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic rate targeting for CBR.
TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
cfg_.g_profile = 1;
cfg_.g_timebase = video.timebase();
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
const int bitrates[4] = { 250, 450, 650, 850 };
const int bitrate_index = GET_PARAM(3);
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
effective_datarate_[0] * 0.80)
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
effective_datarate_[0] * 1.15)
<< " The datarate for the file missed the target!"
<< cfg_.rc_target_bitrate << " " << effective_datarate_;
}
// Check that (1) the first dropped frame gets earlier and earlier
// as the drop frame threshold is increased, and (2) that the total number of
// frame drops does not decrease as we increase frame drop threshold.
// Use a lower qp-max to force some frame drops.
TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_undershoot_pct = 20;
cfg_.rc_undershoot_pct = 20;
cfg_.rc_dropframe_thresh = 10;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 50;
cfg_.rc_end_usage = VPX_CBR;
cfg_.rc_target_bitrate = 200;
cfg_.g_lag_in_frames = 0;
// TODO(marpan): Investigate datarate target failures with a smaller keyframe
// interval (128).
cfg_.kf_max_dist = 9999;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
const int kDropFrameThreshTestStep = 30;
const int bitrates[2] = { 50, 150 };
const int bitrate_index = GET_PARAM(3);
if (bitrate_index > 1) return;
cfg_.rc_target_bitrate = bitrates[bitrate_index];
vpx_codec_pts_t last_drop = 140;
int last_num_drops = 0;
for (int i = 10; i < 100; i += kDropFrameThreshTestStep) {
cfg_.rc_dropframe_thresh = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
<< " The datarate for the file is greater than target by too much!";
ASSERT_LE(first_drop_, last_drop)
<< " The first dropped frame for drop_thresh " << i
<< " > first dropped frame for drop_thresh "
<< i - kDropFrameThreshTestStep;
ASSERT_GE(num_drops_, last_num_drops * 0.85)
<< " The number of dropped frames for drop_thresh " << i
<< " < number of dropped frames for drop_thresh "
<< i - kDropFrameThreshTestStep;
last_drop = first_drop_;
last_num_drops = num_drops_;
}
} // namespace
// Check basic rate targeting for 2 temporal layers.
TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
// 2 Temporal layers, no spatial layers: Framerate decimation (2, 1).
cfg_.ss_number_layers = 1;
cfg_.ts_number_layers = 2;
cfg_.ts_rate_decimator[0] = 2;
cfg_.ts_rate_decimator[1] = 1;
cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
if (deadline_ == VPX_DL_REALTIME) cfg_.g_error_resilient = 1;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 200);
const int bitrates[4] = { 200, 400, 600, 800 };
const int bitrate_index = GET_PARAM(3);
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
// 60-40 bitrate allocation for 2 temporal layers.
cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
<< " The datarate for the file is lower than target by too much, "
"for layer: "
<< j;
ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
<< " The datarate for the file is greater than target by too much, "
"for layer: "
<< j;
}
}
// Check basic rate targeting for 3 temporal layers.
TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
// 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
cfg_.ss_number_layers = 1;
cfg_.ts_number_layers = 3;
cfg_.ts_rate_decimator[0] = 4;
cfg_.ts_rate_decimator[1] = 2;
cfg_.ts_rate_decimator[2] = 1;
cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 200);
const int bitrates[4] = { 200, 400, 600, 800 };
const int bitrate_index = GET_PARAM(3);
cfg_.rc_target_bitrate = bitrates[bitrate_index];
ResetModel();
// 40-20-40 bitrate allocation for 3 temporal layers.
cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
// TODO(yaowu): Work out more stable rc control strategy and
// Adjust the thresholds to be tighter than .75.
ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
<< " The datarate for the file is lower than target by too much, "
"for layer: "
<< j;
// TODO(yaowu): Work out more stable rc control strategy and
// Adjust the thresholds to be tighter than 1.25.
ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
<< " The datarate for the file is greater than target by too much, "
"for layer: "
<< j;
}
}
// Check basic rate targeting for 3 temporal layers, with frame dropping.
// Only for one (low) bitrate with lower max_quantizer, and somewhat higher
// frame drop threshold, to force frame dropping.
TEST_P(DatarateTestVP9LargeOneBR,
BasicRateTargeting3TemporalLayersFrameDropping) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
// Set frame drop threshold and rc_max_quantizer to force some frame drops.
cfg_.rc_dropframe_thresh = 20;
cfg_.rc_max_quantizer = 45;
cfg_.rc_min_quantizer = 0;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
// 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
cfg_.ss_number_layers = 1;
cfg_.ts_number_layers = 3;
cfg_.ts_rate_decimator[0] = 4;
cfg_.ts_rate_decimator[1] = 2;
cfg_.ts_rate_decimator[2] = 1;
cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 200);
cfg_.rc_target_bitrate = 200;
ResetModel();
// 40-20-40 bitrate allocation for 3 temporal layers.
cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
<< " The datarate for the file is lower than target by too much, "
"for layer: "
<< j;
ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
<< " The datarate for the file is greater than target by too much, "
"for layer: "
<< j;
// Expect some frame drops in this test: for this 200 frames test,
// expect at least 10% and not more than 60% drops.
ASSERT_GE(num_drops_, 20);
ASSERT_LE(num_drops_, 130);
}
}
// Params: speed setting.
class DatarateTestVP9RealTime : public DatarateTestVP9,
public ::libvpx_test::CodecTestWithParam<int> {
public:
DatarateTestVP9RealTime() : DatarateTestVP9(GET_PARAM(0)) {}
virtual ~DatarateTestVP9RealTime() {}
protected:
virtual void SetUp() {
InitializeConfig();
SetMode(::libvpx_test::kRealTime);
set_cpu_used_ = GET_PARAM(1);
ResetModel();
}
};
// Check VP9 region of interest feature.
TEST_P(DatarateTestVP9RealTime, RegionOfInterest) {
if (deadline_ != VPX_DL_REALTIME || set_cpu_used_ < 5) return;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 0;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
cfg_.rc_target_bitrate = 450;
cfg_.g_w = 352;
cfg_.g_h = 288;
ResetModel();
// Set ROI parameters
use_roi_ = true;
memset(&roi_, 0, sizeof(roi_));
roi_.rows = (cfg_.g_h + 7) / 8;
roi_.cols = (cfg_.g_w + 7) / 8;
roi_.delta_q[1] = -20;
roi_.delta_lf[1] = -20;
memset(roi_.ref_frame, -1, sizeof(roi_.ref_frame));
roi_.ref_frame[1] = 1;
// Use 2 states: 1 is center square, 0 is the rest.
roi_.roi_map = reinterpret_cast<uint8_t *>(
calloc(roi_.rows * roi_.cols, sizeof(*roi_.roi_map)));
ASSERT_TRUE(roi_.roi_map != NULL);
for (unsigned int i = 0; i < roi_.rows; ++i) {
for (unsigned int j = 0; j < roi_.cols; ++j) {
if (i > (roi_.rows >> 2) && i < ((roi_.rows * 3) >> 2) &&
j > (roi_.cols >> 2) && j < ((roi_.cols * 3) >> 2)) {
roi_.roi_map[i * roi_.cols + j] = 1;
}
}
}
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_[0] * 0.90)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, effective_datarate_[0] * 1.4)
<< " The datarate for the file missed the target!";
free(roi_.roi_map);
}
#if CONFIG_VP9_TEMPORAL_DENOISING
// Params: speed setting.
class DatarateTestVP9LargeDenoiser : public DatarateTestVP9RealTime {
public:
virtual ~DatarateTestVP9LargeDenoiser() {}
};
// Check basic datarate targeting, for a single bitrate, when denoiser is on.
TEST_P(DatarateTestVP9LargeDenoiser, LowNoise) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 2;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
// For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
// there is only one denoiser mode: denoiserYonly(which is 1),
// but may add more modes in the future.
cfg_.rc_target_bitrate = 300;
ResetModel();
// Turn on the denoiser.
denoiser_on_ = 1;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic datarate targeting, for a single bitrate, when denoiser is on,
// for clip with high noise level. Use 2 threads.
TEST_P(DatarateTestVP9LargeDenoiser, HighNoise) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 2;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
cfg_.g_threads = 2;
::libvpx_test::Y4mVideoSource video("noisy_clip_640_360.y4m", 0, 200);
// For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
// there is only one denoiser mode: kDenoiserOnYOnly(which is 1),
// but may add more modes in the future.
cfg_.rc_target_bitrate = 1000;
ResetModel();
// Turn on the denoiser.
denoiser_on_ = 1;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic datarate targeting, for a single bitrate, when denoiser is on,
// for 1280x720 clip with 4 threads.
TEST_P(DatarateTestVP9LargeDenoiser, 4threads) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 2;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
cfg_.g_threads = 4;
::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
// For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
// there is only one denoiser mode: denoiserYonly(which is 1),
// but may add more modes in the future.
cfg_.rc_target_bitrate = 1000;
ResetModel();
// Turn on the denoiser.
denoiser_on_ = 1;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.29)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic datarate targeting, for a single bitrate, when denoiser is off
// and on.
TEST_P(DatarateTestVP9LargeDenoiser, DenoiserOffOn) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 1;
cfg_.rc_min_quantizer = 2;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 299);
// For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
// there is only one denoiser mode: denoiserYonly(which is 1),
// but may add more modes in the future.
cfg_.rc_target_bitrate = 300;
ResetModel();
// The denoiser is off by default.
denoiser_on_ = 0;
// Set the offon test flag.
denoiser_offon_test_ = 1;
denoiser_offon_period_ = 100;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
#endif // CONFIG_VP9_TEMPORAL_DENOISING
VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
::testing::Values(::libvpx_test::kOnePassGood,
::libvpx_test::kRealTime),
::testing::Range(2, 9), ::testing::Range(0, 4));
VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9LargeOneBR,
::testing::Values(::libvpx_test::kOnePassGood,
::libvpx_test::kRealTime),
::testing::Range(2, 9));
VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9RealTime, ::testing::Range(5, 9));
#if CONFIG_VP9_TEMPORAL_DENOISING
VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9LargeDenoiser, ::testing::Range(5, 9));
#endif
} // namespace

View File

@ -35,8 +35,7 @@ typedef int (*Vp9DenoiserFilterFunc)(const uint8_t *sig, int sig_stride,
uint8_t *avg, int avg_stride, uint8_t *avg, int avg_stride,
int increase_denoising, BLOCK_SIZE bs, int increase_denoising, BLOCK_SIZE bs,
int motion_magnitude); int motion_magnitude);
typedef ::testing::tuple<Vp9DenoiserFilterFunc, BLOCK_SIZE> typedef std::tr1::tuple<Vp9DenoiserFilterFunc, BLOCK_SIZE> VP9DenoiserTestParam;
VP9DenoiserTestParam;
class VP9DenoiserTest class VP9DenoiserTest
: public ::testing::Test, : public ::testing::Test,
@ -100,7 +99,7 @@ TEST_P(VP9DenoiserTest, BitexactCheck) {
} }
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
// Test for all block size. // Test for all block size.
#if HAVE_SSE2 #if HAVE_SSE2

View File

@ -59,7 +59,7 @@ const TestVideoParam kTestVectors[] = {
// Encoding modes tested // Encoding modes tested
const libvpx_test::TestMode kEncodingModeVectors[] = { const libvpx_test::TestMode kEncodingModeVectors[] = {
::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood, ::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
::libvpx_test::kRealTime ::libvpx_test::kRealTime,
}; };
// Speed settings tested // Speed settings tested

View File

@ -22,7 +22,7 @@ namespace {
// Encoding modes // Encoding modes
const libvpx_test::TestMode kEncodingModeVectors[] = { const libvpx_test::TestMode kEncodingModeVectors[] = {
::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood, ::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
::libvpx_test::kRealTime ::libvpx_test::kRealTime,
}; };
// Encoding speeds // Encoding speeds

View File

@ -14,9 +14,9 @@
#include "third_party/googletest/src/include/gtest/gtest.h" #include "third_party/googletest/src/include/gtest/gtest.h"
#include "./vp9_rtcd.h"
#include "./vpx_config.h" #include "./vpx_config.h"
#include "./vpx_dsp_rtcd.h" #include "./vpx_dsp_rtcd.h"
#include "./vp9_rtcd.h"
#include "test/acm_random.h" #include "test/acm_random.h"
#include "test/buffer.h" #include "test/buffer.h"
#include "test/clear_system_state.h" #include "test/clear_system_state.h"
@ -41,8 +41,8 @@ typedef void (*QuantizeFunc)(const tran_low_t *coeff, intptr_t count,
tran_low_t *dqcoeff, const int16_t *dequant, tran_low_t *dqcoeff, const int16_t *dequant,
uint16_t *eob, const int16_t *scan, uint16_t *eob, const int16_t *scan,
const int16_t *iscan); const int16_t *iscan);
typedef ::testing::tuple<QuantizeFunc, QuantizeFunc, vpx_bit_depth_t, typedef std::tr1::tuple<QuantizeFunc, QuantizeFunc, vpx_bit_depth_t,
int /*max_size*/, bool /*is_fp*/> int /*max_size*/>
QuantizeParam; QuantizeParam;
// Wrapper for FP version which does not use zbin or quant_shift. // Wrapper for FP version which does not use zbin or quant_shift.
@ -69,15 +69,11 @@ void QuantFPWrapper(const tran_low_t *coeff, intptr_t count, int skip_block,
class VP9QuantizeBase { class VP9QuantizeBase {
public: public:
VP9QuantizeBase(vpx_bit_depth_t bit_depth, int max_size, bool is_fp) VP9QuantizeBase(vpx_bit_depth_t bit_depth, int max_size)
: bit_depth_(bit_depth), max_size_(max_size), is_fp_(is_fp) { : bit_depth_(bit_depth), max_size_(max_size) {
max_value_ = (1 << bit_depth_) - 1; max_value_ = (1 << bit_depth_) - 1;
zbin_ptr_ = zbin_ptr_ =
reinterpret_cast<int16_t *>(vpx_memalign(16, 8 * sizeof(*zbin_ptr_))); reinterpret_cast<int16_t *>(vpx_memalign(16, 8 * sizeof(*zbin_ptr_)));
round_fp_ptr_ = reinterpret_cast<int16_t *>(
vpx_memalign(16, 8 * sizeof(*round_fp_ptr_)));
quant_fp_ptr_ = reinterpret_cast<int16_t *>(
vpx_memalign(16, 8 * sizeof(*quant_fp_ptr_)));
round_ptr_ = round_ptr_ =
reinterpret_cast<int16_t *>(vpx_memalign(16, 8 * sizeof(*round_ptr_))); reinterpret_cast<int16_t *>(vpx_memalign(16, 8 * sizeof(*round_ptr_)));
quant_ptr_ = quant_ptr_ =
@ -90,15 +86,11 @@ class VP9QuantizeBase {
~VP9QuantizeBase() { ~VP9QuantizeBase() {
vpx_free(zbin_ptr_); vpx_free(zbin_ptr_);
vpx_free(round_fp_ptr_);
vpx_free(quant_fp_ptr_);
vpx_free(round_ptr_); vpx_free(round_ptr_);
vpx_free(quant_ptr_); vpx_free(quant_ptr_);
vpx_free(quant_shift_ptr_); vpx_free(quant_shift_ptr_);
vpx_free(dequant_ptr_); vpx_free(dequant_ptr_);
zbin_ptr_ = NULL; zbin_ptr_ = NULL;
round_fp_ptr_ = NULL;
quant_fp_ptr_ = NULL;
round_ptr_ = NULL; round_ptr_ = NULL;
quant_ptr_ = NULL; quant_ptr_ = NULL;
quant_shift_ptr_ = NULL; quant_shift_ptr_ = NULL;
@ -108,8 +100,6 @@ class VP9QuantizeBase {
protected: protected:
int16_t *zbin_ptr_; int16_t *zbin_ptr_;
int16_t *round_fp_ptr_;
int16_t *quant_fp_ptr_;
int16_t *round_ptr_; int16_t *round_ptr_;
int16_t *quant_ptr_; int16_t *quant_ptr_;
int16_t *quant_shift_ptr_; int16_t *quant_shift_ptr_;
@ -117,136 +107,29 @@ class VP9QuantizeBase {
const vpx_bit_depth_t bit_depth_; const vpx_bit_depth_t bit_depth_;
int max_value_; int max_value_;
const int max_size_; const int max_size_;
const bool is_fp_;
}; };
class VP9QuantizeTest : public VP9QuantizeBase, class VP9QuantizeTest : public VP9QuantizeBase,
public ::testing::TestWithParam<QuantizeParam> { public ::testing::TestWithParam<QuantizeParam> {
public: public:
VP9QuantizeTest() VP9QuantizeTest()
: VP9QuantizeBase(GET_PARAM(2), GET_PARAM(3), GET_PARAM(4)), : VP9QuantizeBase(GET_PARAM(2), GET_PARAM(3)), quantize_op_(GET_PARAM(0)),
quantize_op_(GET_PARAM(0)), ref_quantize_op_(GET_PARAM(1)) {} ref_quantize_op_(GET_PARAM(1)) {}
protected: protected:
const QuantizeFunc quantize_op_; const QuantizeFunc quantize_op_;
const QuantizeFunc ref_quantize_op_; const QuantizeFunc ref_quantize_op_;
}; };
// This quantizer compares the AC coefficients to the quantization step size to
// determine if further multiplication operations are needed.
// Based on vp9_quantize_fp_sse2().
inline void quant_fp_nz(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan, int is_32x32) {
int i, eob = -1;
const int thr = dequant_ptr[1] >> (1 + is_32x32);
(void)iscan;
(void)skip_block;
assert(!skip_block);
// Quantization pass: All coefficients with index >= zero_flag are
// skippable. Note: zero_flag can be zero.
for (i = 0; i < n_coeffs; i += 16) {
int y;
int nzflag_cnt = 0;
int abs_coeff[16];
int coeff_sign[16];
// count nzflag for each row (16 tran_low_t)
for (y = 0; y < 16; ++y) {
const int rc = i + y;
const int coeff = coeff_ptr[rc];
coeff_sign[y] = (coeff >> 31);
abs_coeff[y] = (coeff ^ coeff_sign[y]) - coeff_sign[y];
// The first 16 are skipped in the sse2 code. Do the same here to match.
if (i >= 16 && (abs_coeff[y] <= thr)) {
nzflag_cnt++;
}
}
for (y = 0; y < 16; ++y) {
const int rc = i + y;
// If all of the AC coeffs in a row has magnitude less than the
// quantization step_size/2, quantize to zero.
if (nzflag_cnt < 16) {
int tmp;
int _round;
if (is_32x32) {
_round = ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
} else {
_round = round_ptr[rc != 0];
}
tmp = clamp(abs_coeff[y] + _round, INT16_MIN, INT16_MAX);
tmp = (tmp * quant_ptr[rc != 0]) >> (16 - is_32x32);
qcoeff_ptr[rc] = (tmp ^ coeff_sign[y]) - coeff_sign[y];
dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
if (is_32x32) {
dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
} else {
dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
}
} else {
qcoeff_ptr[rc] = 0;
dqcoeff_ptr[rc] = 0;
}
}
}
// Scan for eob.
for (i = 0; i < n_coeffs; i++) {
// Use the scan order to find the correct eob.
const int rc = scan[i];
if (qcoeff_ptr[rc]) {
eob = i;
}
}
*eob_ptr = eob + 1;
}
void quantize_fp_nz_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
quant_fp_nz(coeff_ptr, n_coeffs, skip_block, round_ptr, quant_ptr, qcoeff_ptr,
dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, 0);
}
void quantize_fp_32x32_nz_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
quant_fp_nz(coeff_ptr, n_coeffs, skip_block, round_ptr, quant_ptr, qcoeff_ptr,
dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, 1);
}
void GenerateHelperArrays(ACMRandom *rnd, int16_t *zbin, int16_t *round, void GenerateHelperArrays(ACMRandom *rnd, int16_t *zbin, int16_t *round,
int16_t *quant, int16_t *quant_shift, int16_t *quant, int16_t *quant_shift,
int16_t *dequant, int16_t *round_fp, int16_t *dequant) {
int16_t *quant_fp) {
// Max when q == 0. Otherwise, it is 48 for Y and 42 for U/V.
const int max_qrounding_factor_fp = 64;
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
// The range is 4 to 1828 in the VP9 tables.
const int qlookup = rnd->RandRange(1825) + 4;
round_fp[j] = (max_qrounding_factor_fp * qlookup) >> 7;
quant_fp[j] = (1 << 16) / qlookup;
// Values determined by deconstructing vp9_init_quantizer(). // Values determined by deconstructing vp9_init_quantizer().
// zbin may be up to 1143 for 8 and 10 bit Y values, or 1200 for 12 bit Y // zbin may be up to 1143 for 8 and 10 bit Y values, or 1200 for 12 bit Y
// values or U/V values of any bit depth. This is because y_delta is not // values or U/V values of any bit depth. This is because y_delta is not
// factored into the vp9_ac_quant() call. // factored into the vp9_ac_quant() call.
zbin[j] = rnd->RandRange(1200); zbin[j] = rnd->RandRange(1200);
// round may be up to 685 for Y values or 914 for U/V. // round may be up to 685 for Y values or 914 for U/V.
round[j] = rnd->RandRange(914); round[j] = rnd->RandRange(914);
// quant ranges from 1 to -32703 // quant ranges from 1 to -32703
@ -258,8 +141,6 @@ void GenerateHelperArrays(ACMRandom *rnd, int16_t *zbin, int16_t *round,
} }
for (int j = 2; j < 8; j++) { for (int j = 2; j < 8; j++) {
zbin[j] = zbin[1]; zbin[j] = zbin[1];
round_fp[j] = round_fp[1];
quant_fp[j] = quant_fp[1];
round[j] = round[1]; round[j] = round[1];
quant[j] = quant[1]; quant[j] = quant[1];
quant_shift[j] = quant_shift[1]; quant_shift[j] = quant_shift[1];
@ -298,19 +179,19 @@ TEST_P(VP9QuantizeTest, OperationCheck) {
const int count = (4 << sz) * (4 << sz); const int count = (4 << sz) * (4 << sz);
coeff.Set(&rnd, -max_value_, max_value_); coeff.Set(&rnd, -max_value_, max_value_);
GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_, GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_,
quant_shift_ptr_, dequant_ptr_, round_fp_ptr_, quant_shift_ptr_, dequant_ptr_);
quant_fp_ptr_);
int16_t *r_ptr = (is_fp_) ? round_fp_ptr_ : round_ptr_;
int16_t *q_ptr = (is_fp_) ? quant_fp_ptr_ : quant_ptr_;
ref_quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_, r_ptr,
q_ptr, quant_shift_ptr_, ref_qcoeff.TopLeftPixel(),
ref_dqcoeff.TopLeftPixel(), dequant_ptr_, &ref_eob,
scan_order->scan, scan_order->iscan);
ASM_REGISTER_STATE_CHECK(quantize_op_( ref_quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_,
coeff.TopLeftPixel(), count, skip_block, zbin_ptr_, r_ptr, q_ptr, round_ptr_, quant_ptr_, quant_shift_ptr_,
quant_shift_ptr_, qcoeff.TopLeftPixel(), dqcoeff.TopLeftPixel(), ref_qcoeff.TopLeftPixel(), ref_dqcoeff.TopLeftPixel(),
dequant_ptr_, &eob, scan_order->scan, scan_order->iscan)); dequant_ptr_, &ref_eob, scan_order->scan,
scan_order->iscan);
ASM_REGISTER_STATE_CHECK(
quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_,
round_ptr_, quant_ptr_, quant_shift_ptr_,
qcoeff.TopLeftPixel(), dqcoeff.TopLeftPixel(),
dequant_ptr_, &eob, scan_order->scan, scan_order->iscan));
EXPECT_TRUE(qcoeff.CheckValues(ref_qcoeff)); EXPECT_TRUE(qcoeff.CheckValues(ref_qcoeff));
EXPECT_TRUE(dqcoeff.CheckValues(ref_dqcoeff)); EXPECT_TRUE(dqcoeff.CheckValues(ref_dqcoeff));
@ -360,19 +241,19 @@ TEST_P(VP9QuantizeTest, EOBCheck) {
coeff.TopLeftPixel()[rnd(count)] = coeff.TopLeftPixel()[rnd(count)] =
static_cast<int>(rnd.RandRange(max_value_ * 2)) - max_value_; static_cast<int>(rnd.RandRange(max_value_ * 2)) - max_value_;
GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_, GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_,
quant_shift_ptr_, dequant_ptr_, round_fp_ptr_, quant_shift_ptr_, dequant_ptr_);
quant_fp_ptr_);
int16_t *r_ptr = (is_fp_) ? round_fp_ptr_ : round_ptr_;
int16_t *q_ptr = (is_fp_) ? quant_fp_ptr_ : quant_ptr_;
ref_quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_, r_ptr,
q_ptr, quant_shift_ptr_, ref_qcoeff.TopLeftPixel(),
ref_dqcoeff.TopLeftPixel(), dequant_ptr_, &ref_eob,
scan_order->scan, scan_order->iscan);
ASM_REGISTER_STATE_CHECK(quantize_op_( ref_quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_,
coeff.TopLeftPixel(), count, skip_block, zbin_ptr_, r_ptr, q_ptr, round_ptr_, quant_ptr_, quant_shift_ptr_,
quant_shift_ptr_, qcoeff.TopLeftPixel(), dqcoeff.TopLeftPixel(), ref_qcoeff.TopLeftPixel(), ref_dqcoeff.TopLeftPixel(),
dequant_ptr_, &eob, scan_order->scan, scan_order->iscan)); dequant_ptr_, &ref_eob, scan_order->scan,
scan_order->iscan);
ASM_REGISTER_STATE_CHECK(
quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_,
round_ptr_, quant_ptr_, quant_shift_ptr_,
qcoeff.TopLeftPixel(), dqcoeff.TopLeftPixel(),
dequant_ptr_, &eob, scan_order->scan, scan_order->iscan));
EXPECT_TRUE(qcoeff.CheckValues(ref_qcoeff)); EXPECT_TRUE(qcoeff.CheckValues(ref_qcoeff));
EXPECT_TRUE(dqcoeff.CheckValues(ref_dqcoeff)); EXPECT_TRUE(dqcoeff.CheckValues(ref_dqcoeff));
@ -418,10 +299,7 @@ TEST_P(VP9QuantizeTest, DISABLED_Speed) {
const int count = (4 << sz) * (4 << sz); const int count = (4 << sz) * (4 << sz);
GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_, GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_,
quant_shift_ptr_, dequant_ptr_, round_fp_ptr_, quant_shift_ptr_, dequant_ptr_);
quant_fp_ptr_);
int16_t *r_ptr = (is_fp_) ? round_fp_ptr_ : round_ptr_;
int16_t *q_ptr = (is_fp_) ? quant_fp_ptr_ : quant_ptr_;
if (i == 0) { if (i == 0) {
// When |coeff values| are less than zbin the results are 0. // When |coeff values| are less than zbin the results are 0.
@ -441,10 +319,10 @@ TEST_P(VP9QuantizeTest, DISABLED_Speed) {
vpx_usec_timer timer; vpx_usec_timer timer;
vpx_usec_timer_start(&timer); vpx_usec_timer_start(&timer);
for (int j = 0; j < 100000000 / count; ++j) { for (int j = 0; j < 100000000 / count; ++j) {
quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_, r_ptr, quantize_op_(coeff.TopLeftPixel(), count, skip_block, zbin_ptr_,
q_ptr, quant_shift_ptr_, qcoeff.TopLeftPixel(), round_ptr_, quant_ptr_, quant_shift_ptr_,
dqcoeff.TopLeftPixel(), dequant_ptr_, &eob, qcoeff.TopLeftPixel(), dqcoeff.TopLeftPixel(),
scan_order->scan, scan_order->iscan); dequant_ptr_, &eob, scan_order->scan, scan_order->iscan);
} }
vpx_usec_timer_mark(&timer); vpx_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer)); const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
@ -457,7 +335,7 @@ TEST_P(VP9QuantizeTest, DISABLED_Speed) {
} }
} }
using ::testing::make_tuple; using std::tr1::make_tuple;
#if HAVE_SSE2 #if HAVE_SSE2
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
@ -467,54 +345,50 @@ INSTANTIATE_TEST_CASE_P(
SSE2, VP9QuantizeTest, SSE2, VP9QuantizeTest,
::testing::Values( ::testing::Values(
make_tuple(&vpx_highbd_quantize_b_sse2, &vpx_highbd_quantize_b_c, make_tuple(&vpx_highbd_quantize_b_sse2, &vpx_highbd_quantize_b_c,
VPX_BITS_8, 16, false), VPX_BITS_8, 16),
make_tuple(&vpx_highbd_quantize_b_sse2, &vpx_highbd_quantize_b_c, make_tuple(&vpx_highbd_quantize_b_sse2, &vpx_highbd_quantize_b_c,
VPX_BITS_10, 16, false), VPX_BITS_10, 16),
make_tuple(&vpx_highbd_quantize_b_sse2, &vpx_highbd_quantize_b_c, make_tuple(&vpx_highbd_quantize_b_sse2, &vpx_highbd_quantize_b_c,
VPX_BITS_12, 16, false), VPX_BITS_12, 16),
make_tuple(&vpx_highbd_quantize_b_32x32_sse2, make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
&vpx_highbd_quantize_b_32x32_c, VPX_BITS_8, 32, false), &vpx_highbd_quantize_b_32x32_c, VPX_BITS_8, 32),
make_tuple(&vpx_highbd_quantize_b_32x32_sse2, make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
&vpx_highbd_quantize_b_32x32_c, VPX_BITS_10, 32, false), &vpx_highbd_quantize_b_32x32_c, VPX_BITS_10, 32),
make_tuple(&vpx_highbd_quantize_b_32x32_sse2, make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
&vpx_highbd_quantize_b_32x32_c, VPX_BITS_12, 32, false))); &vpx_highbd_quantize_b_32x32_c, VPX_BITS_12, 32)));
#else #else
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(SSE2, VP9QuantizeTest,
SSE2, VP9QuantizeTest, ::testing::Values(make_tuple(&vpx_quantize_b_sse2,
::testing::Values(make_tuple(&vpx_quantize_b_sse2, &vpx_quantize_b_c, &vpx_quantize_b_c,
VPX_BITS_8, 16, false), VPX_BITS_8, 16)));
make_tuple(&QuantFPWrapper<vp9_quantize_fp_sse2>,
&QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8,
16, true)));
#endif // CONFIG_VP9_HIGHBITDEPTH #endif // CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
DISABLED_SSE2, VP9QuantizeTest,
::testing::Values(make_tuple(&QuantFPWrapper<vp9_quantize_fp_sse2>,
&QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8,
16)));
#endif // HAVE_SSE2 #endif // HAVE_SSE2
#if HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH #if HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH
#if ARCH_X86_64
INSTANTIATE_TEST_CASE_P(
SSSE3, VP9QuantizeTest,
::testing::Values(make_tuple(&vpx_quantize_b_ssse3, &vpx_quantize_b_c,
VPX_BITS_8, 16, false),
make_tuple(&QuantFPWrapper<vp9_quantize_fp_ssse3>,
&QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8,
16, true),
make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_ssse3>,
&QuantFPWrapper<quantize_fp_32x32_nz_c>,
VPX_BITS_8, 32, true)));
#else
INSTANTIATE_TEST_CASE_P(SSSE3, VP9QuantizeTest, INSTANTIATE_TEST_CASE_P(SSSE3, VP9QuantizeTest,
::testing::Values(make_tuple(&vpx_quantize_b_ssse3, ::testing::Values(make_tuple(&vpx_quantize_b_ssse3,
&vpx_quantize_b_c, &vpx_quantize_b_c,
VPX_BITS_8, 16, false))); VPX_BITS_8, 16)));
#endif
#if ARCH_X86_64 #if ARCH_X86_64
// TODO(johannkoenig): SSSE3 optimizations do not yet pass this test. // TODO(johannkoenig): SSSE3 optimizations do not yet pass this test.
INSTANTIATE_TEST_CASE_P(DISABLED_SSSE3, VP9QuantizeTest, INSTANTIATE_TEST_CASE_P(
::testing::Values(make_tuple( DISABLED_SSSE3, VP9QuantizeTest,
&vpx_quantize_b_32x32_ssse3, ::testing::Values(make_tuple(&vpx_quantize_b_32x32_ssse3,
&vpx_quantize_b_32x32_c, VPX_BITS_8, 32, false))); &vpx_quantize_b_32x32_c, VPX_BITS_8, 32),
make_tuple(&QuantFPWrapper<vp9_quantize_fp_ssse3>,
&QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8,
16),
make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_ssse3>,
&QuantFPWrapper<vp9_quantize_fp_32x32_c>,
VPX_BITS_8, 32)));
#endif // ARCH_X86_64 #endif // ARCH_X86_64
#endif // HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH #endif // HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH
@ -524,54 +398,36 @@ INSTANTIATE_TEST_CASE_P(DISABLED_SSSE3, VP9QuantizeTest,
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
AVX, VP9QuantizeTest, AVX, VP9QuantizeTest,
::testing::Values(make_tuple(&vpx_quantize_b_avx, &vpx_quantize_b_c, ::testing::Values(make_tuple(&vpx_quantize_b_avx, &vpx_quantize_b_c,
VPX_BITS_8, 16, false), VPX_BITS_8, 16),
// Even though SSSE3 and AVX do not match the reference // Even though SSSE3 and AVX do not match the reference
// code, we can keep them in sync with each other. // code, we can keep them in sync with each other.
make_tuple(&vpx_quantize_b_32x32_avx, make_tuple(&vpx_quantize_b_32x32_avx,
&vpx_quantize_b_32x32_ssse3, VPX_BITS_8, 32, &vpx_quantize_b_32x32_ssse3, VPX_BITS_8, 32)));
false)));
#endif // HAVE_AVX && !CONFIG_VP9_HIGHBITDEPTH #endif // HAVE_AVX && !CONFIG_VP9_HIGHBITDEPTH
#if ARCH_X86_64 && HAVE_AVX2
INSTANTIATE_TEST_CASE_P(
AVX2, VP9QuantizeTest,
::testing::Values(make_tuple(&QuantFPWrapper<vp9_quantize_fp_avx2>,
&QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8,
16, true)));
#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH
// TODO(webm:1448): dqcoeff is not handled correctly in HBD builds. // TODO(webm:1448): dqcoeff is not handled correctly in HBD builds.
#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH #if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
NEON, VP9QuantizeTest, NEON, VP9QuantizeTest,
::testing::Values(make_tuple(&vpx_quantize_b_neon, &vpx_quantize_b_c, ::testing::Values(
VPX_BITS_8, 16, false), make_tuple(&vpx_quantize_b_neon, &vpx_quantize_b_c, VPX_BITS_8, 16),
make_tuple(&vpx_quantize_b_32x32_neon, make_tuple(&vpx_quantize_b_32x32_neon, &vpx_quantize_b_32x32_c,
&vpx_quantize_b_32x32_c, VPX_BITS_8, 32, VPX_BITS_8, 32),
false), make_tuple(&QuantFPWrapper<vp9_quantize_fp_neon>,
make_tuple(&QuantFPWrapper<vp9_quantize_fp_neon>, &QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8, 16),
&QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8, make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_neon>,
16, true), &QuantFPWrapper<vp9_quantize_fp_32x32_c>, VPX_BITS_8, 32)));
make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_neon>,
&QuantFPWrapper<vp9_quantize_fp_32x32_c>,
VPX_BITS_8, 32, true)));
#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH #endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH
// Only useful to compare "Speed" test results. // Only useful to compare "Speed" test results.
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
DISABLED_C, VP9QuantizeTest, DISABLED_C, VP9QuantizeTest,
::testing::Values( ::testing::Values(
make_tuple(&vpx_quantize_b_c, &vpx_quantize_b_c, VPX_BITS_8, 16, false), make_tuple(&vpx_quantize_b_c, &vpx_quantize_b_c, VPX_BITS_8, 16),
make_tuple(&vpx_quantize_b_32x32_c, &vpx_quantize_b_32x32_c, VPX_BITS_8, make_tuple(&vpx_quantize_b_32x32_c, &vpx_quantize_b_32x32_c, VPX_BITS_8,
32, false), 32),
make_tuple(&QuantFPWrapper<vp9_quantize_fp_c>, make_tuple(&QuantFPWrapper<vp9_quantize_fp_c>,
&QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8, 16, true), &QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8, 16),
make_tuple(&QuantFPWrapper<quantize_fp_nz_c>,
&QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8, 16, true),
make_tuple(&QuantFPWrapper<quantize_fp_32x32_nz_c>,
&QuantFPWrapper<quantize_fp_32x32_nz_c>, VPX_BITS_8, 32,
true),
make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_c>, make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_c>,
&QuantFPWrapper<vp9_quantize_fp_32x32_c>, VPX_BITS_8, 32, &QuantFPWrapper<vp9_quantize_fp_32x32_c>, VPX_BITS_8, 32)));
true)));
} // namespace } // namespace

View File

@ -47,7 +47,7 @@ class ScaleTest : public VpxScaleBase,
scale_fn_(&img_, &dst_img_, filter_type, phase_scaler)); scale_fn_(&img_, &dst_img_, filter_type, phase_scaler));
} }
void RunTest(INTERP_FILTER filter_type) { void RunTest() {
static const int kNumSizesToTest = 20; static const int kNumSizesToTest = 20;
static const int kNumScaleFactorsToTest = 4; static const int kNumScaleFactorsToTest = 4;
static const int kSizesToTest[] = { static const int kSizesToTest[] = {
@ -55,48 +55,50 @@ class ScaleTest : public VpxScaleBase,
22, 24, 26, 28, 30, 32, 34, 68, 128, 134 22, 24, 26, 28, 30, 32, 34, 68, 128, 134
}; };
static const int kScaleFactors[] = { 1, 2, 3, 4 }; static const int kScaleFactors[] = { 1, 2, 3, 4 };
for (int phase_scaler = 0; phase_scaler < 16; ++phase_scaler) { for (INTERP_FILTER filter_type = 0; filter_type < 4; ++filter_type) {
for (int h = 0; h < kNumSizesToTest; ++h) { for (int phase_scaler = 0; phase_scaler < 16; ++phase_scaler) {
const int src_height = kSizesToTest[h]; for (int h = 0; h < kNumSizesToTest; ++h) {
for (int w = 0; w < kNumSizesToTest; ++w) { const int src_height = kSizesToTest[h];
const int src_width = kSizesToTest[w]; for (int w = 0; w < kNumSizesToTest; ++w) {
for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest; const int src_width = kSizesToTest[w];
++sf_up_idx) { for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest;
const int sf_up = kScaleFactors[sf_up_idx]; ++sf_up_idx) {
for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest; const int sf_up = kScaleFactors[sf_up_idx];
++sf_down_idx) { for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest;
const int sf_down = kScaleFactors[sf_down_idx]; ++sf_down_idx) {
const int dst_width = src_width * sf_up / sf_down; const int sf_down = kScaleFactors[sf_down_idx];
const int dst_height = src_height * sf_up / sf_down; const int dst_width = src_width * sf_up / sf_down;
if (sf_up == sf_down && sf_up != 1) { const int dst_height = src_height * sf_up / sf_down;
continue; if (sf_up == sf_down && sf_up != 1) {
continue;
}
// I420 frame width and height must be even.
if (!dst_width || !dst_height || dst_width & 1 ||
dst_height & 1) {
continue;
}
// vpx_convolve8_c() has restriction on the step which cannot
// exceed 64 (ratio 1 to 4).
if (src_width > 4 * dst_width || src_height > 4 * dst_height) {
continue;
}
ASSERT_NO_FATAL_FAILURE(ResetScaleImages(
src_width, src_height, dst_width, dst_height));
ReferenceScaleFrame(filter_type, phase_scaler);
ScaleFrame(filter_type, phase_scaler);
if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc,
ref_img_.frame_size)) {
printf(
"filter_type = %d, phase_scaler = %d, src_width = %4d, "
"src_height = %4d, dst_width = %4d, dst_height = %4d, "
"scale factor = %d:%d\n",
filter_type, phase_scaler, src_width, src_height,
dst_width, dst_height, sf_down, sf_up);
PrintDiff();
}
CompareImages(dst_img_);
DeallocScaleImages();
} }
// I420 frame width and height must be even.
if (!dst_width || !dst_height || dst_width & 1 ||
dst_height & 1) {
continue;
}
// vpx_convolve8_c() has restriction on the step which cannot
// exceed 64 (ratio 1 to 4).
if (src_width > 4 * dst_width || src_height > 4 * dst_height) {
continue;
}
ASSERT_NO_FATAL_FAILURE(ResetScaleImages(src_width, src_height,
dst_width, dst_height));
ReferenceScaleFrame(filter_type, phase_scaler);
ScaleFrame(filter_type, phase_scaler);
if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc,
ref_img_.frame_size)) {
printf(
"filter_type = %d, phase_scaler = %d, src_width = %4d, "
"src_height = %4d, dst_width = %4d, dst_height = %4d, "
"scale factor = %d:%d\n",
filter_type, phase_scaler, src_width, src_height, dst_width,
dst_height, sf_down, sf_up);
PrintDiff();
}
CompareImages(dst_img_);
DeallocScaleImages();
} }
} }
} }
@ -143,10 +145,7 @@ class ScaleTest : public VpxScaleBase,
ScaleFrameFunc scale_fn_; ScaleFrameFunc scale_fn_;
}; };
TEST_P(ScaleTest, ScaleFrame_EightTap) { RunTest(EIGHTTAP); } TEST_P(ScaleTest, ScaleFrame) { ASSERT_NO_FATAL_FAILURE(RunTest()); }
TEST_P(ScaleTest, ScaleFrame_EightTapSmooth) { RunTest(EIGHTTAP_SMOOTH); }
TEST_P(ScaleTest, ScaleFrame_EightTapSharp) { RunTest(EIGHTTAP_SHARP); }
TEST_P(ScaleTest, ScaleFrame_Bilinear) { RunTest(BILINEAR); }
TEST_P(ScaleTest, DISABLED_Speed) { TEST_P(ScaleTest, DISABLED_Speed) {
static const int kCountSpeedTestBlock = 100; static const int kCountSpeedTestBlock = 100;

72
test/vp9_spatial_svc_encoder.sh Executable file
View File

@ -0,0 +1,72 @@
#!/bin/sh
##
## 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.
##
## This file tests the libvpx vp9_spatial_svc_encoder example. To add new
## tests to to this file, do the following:
## 1. Write a shell function (this is your test).
## 2. Add the function to vp9_spatial_svc_tests (on a new line).
##
. $(dirname $0)/tools_common.sh
# Environment check: $YUV_RAW_INPUT is required.
vp9_spatial_svc_encoder_verify_environment() {
if [ ! -e "${YUV_RAW_INPUT}" ]; then
echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
return 1
fi
}
# Runs vp9_spatial_svc_encoder. $1 is the test name.
vp9_spatial_svc_encoder() {
local readonly \
encoder="${LIBVPX_BIN_PATH}/vp9_spatial_svc_encoder${VPX_TEST_EXE_SUFFIX}"
local readonly test_name="$1"
local readonly \
output_file="${VPX_TEST_OUTPUT_DIR}/vp9_ssvc_encoder${test_name}.ivf"
local readonly frames_to_encode=10
local readonly max_kf=9999
shift
if [ ! -x "${encoder}" ]; then
elog "${encoder} does not exist or is not executable."
return 1
fi
eval "${VPX_TEST_PREFIX}" "${encoder}" -w "${YUV_RAW_INPUT_WIDTH}" \
-h "${YUV_RAW_INPUT_HEIGHT}" -k "${max_kf}" -f "${frames_to_encode}" \
"$@" "${YUV_RAW_INPUT}" "${output_file}" ${devnull}
[ -e "${output_file}" ] || return 1
}
# Each test is run with layer count 1-$vp9_ssvc_test_layers.
vp9_ssvc_test_layers=5
vp9_spatial_svc() {
if [ "$(vp9_encode_available)" = "yes" ]; then
local readonly test_name="vp9_spatial_svc"
for layers in $(seq 1 ${vp9_ssvc_test_layers}); do
vp9_spatial_svc_encoder "${test_name}" -sl ${layers}
done
fi
}
readonly vp9_spatial_svc_tests="DISABLED_vp9_spatial_svc_mode_i
DISABLED_vp9_spatial_svc_mode_altip
DISABLED_vp9_spatial_svc_mode_ip
DISABLED_vp9_spatial_svc_mode_gf
vp9_spatial_svc"
if [ "$(vpx_config_option_enabled CONFIG_SPATIAL_SVC)" = "yes" ]; then
run_tests \
vp9_spatial_svc_encoder_verify_environment \
"${vp9_spatial_svc_tests}"
fi

View File

@ -147,6 +147,7 @@ TEST(VPxWorkerThreadTest, TestInterfaceAPI) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Multi-threaded decode tests // Multi-threaded decode tests
#if CONFIG_WEBM_IO #if CONFIG_WEBM_IO
struct FileList { struct FileList {
const char *name; const char *name;

View File

@ -20,15 +20,6 @@
#include "vpx_scale/yv12config.h" #include "vpx_scale/yv12config.h"
namespace libvpx_test { namespace libvpx_test {
namespace {
#if ARCH_ARM || (ARCH_MIPS && !HAVE_MIPS64) || ARCH_X86
// Avoid OOM failures on 32-bit platforms.
const int kNumSizesToTest = 7;
#else
const int kNumSizesToTest = 8;
#endif
const int kSizesToTest[] = { 1, 15, 33, 145, 512, 1025, 3840, 16383 };
typedef void (*ExtendFrameBorderFunc)(YV12_BUFFER_CONFIG *ybf); typedef void (*ExtendFrameBorderFunc)(YV12_BUFFER_CONFIG *ybf);
typedef void (*CopyFrameFunc)(const YV12_BUFFER_CONFIG *src_ybf, typedef void (*CopyFrameFunc)(const YV12_BUFFER_CONFIG *src_ybf,
@ -46,6 +37,13 @@ class ExtendBorderTest
void ExtendBorder() { ASM_REGISTER_STATE_CHECK(extend_fn_(&img_)); } void ExtendBorder() { ASM_REGISTER_STATE_CHECK(extend_fn_(&img_)); }
void RunTest() { void RunTest() {
#if ARCH_ARM
// Some arm devices OOM when trying to allocate the largest buffers.
static const int kNumSizesToTest = 6;
#else
static const int kNumSizesToTest = 7;
#endif
static const int kSizesToTest[] = { 1, 15, 33, 145, 512, 1025, 16383 };
for (int h = 0; h < kNumSizesToTest; ++h) { for (int h = 0; h < kNumSizesToTest; ++h) {
for (int w = 0; w < kNumSizesToTest; ++w) { for (int w = 0; w < kNumSizesToTest; ++w) {
ASSERT_NO_FATAL_FAILURE(ResetImages(kSizesToTest[w], kSizesToTest[h])); ASSERT_NO_FATAL_FAILURE(ResetImages(kSizesToTest[w], kSizesToTest[h]));
@ -78,6 +76,13 @@ class CopyFrameTest : public VpxScaleBase,
} }
void RunTest() { void RunTest() {
#if ARCH_ARM
// Some arm devices OOM when trying to allocate the largest buffers.
static const int kNumSizesToTest = 6;
#else
static const int kNumSizesToTest = 7;
#endif
static const int kSizesToTest[] = { 1, 15, 33, 145, 512, 1025, 16383 };
for (int h = 0; h < kNumSizesToTest; ++h) { for (int h = 0; h < kNumSizesToTest; ++h) {
for (int w = 0; w < kNumSizesToTest; ++w) { for (int w = 0; w < kNumSizesToTest; ++w) {
ASSERT_NO_FATAL_FAILURE(ResetImages(kSizesToTest[w], kSizesToTest[h])); ASSERT_NO_FATAL_FAILURE(ResetImages(kSizesToTest[w], kSizesToTest[h]));
@ -97,5 +102,4 @@ TEST_P(CopyFrameTest, CopyFrame) { ASSERT_NO_FATAL_FAILURE(RunTest()); }
INSTANTIATE_TEST_CASE_P(C, CopyFrameTest, INSTANTIATE_TEST_CASE_P(C, CopyFrameTest,
::testing::Values(vp8_yv12_copy_frame_c)); ::testing::Values(vp8_yv12_copy_frame_c));
} // namespace
} // namespace libvpx_test } // namespace libvpx_test

View File

@ -33,8 +33,7 @@ class VpxScaleBase {
const int height) { const int height) {
memset(img, 0, sizeof(*img)); memset(img, 0, sizeof(*img));
ASSERT_EQ( ASSERT_EQ(
0, vp8_yv12_alloc_frame_buffer(img, width, height, VP8BORDERINPIXELS)) 0, vp8_yv12_alloc_frame_buffer(img, width, height, VP8BORDERINPIXELS));
<< "for width: " << width << " height: " << height;
memset(img->buffer_alloc, kBufFiller, img->frame_size); memset(img->buffer_alloc, kBufFiller, img->frame_size);
} }

View File

@ -1,5 +1,5 @@
URL: https://github.com/google/googletest.git URL: https://github.com/google/googletest
Version: release-1.8.0-742-g7857975 Version: 1.8.0
License: BSD License: BSD
License File: LICENSE License File: LICENSE
@ -20,3 +20,5 @@ Local Modifications:
LICENSE LICENSE
README.md README.md
src src
- Suppress unsigned overflow instrumentation in the LCG
https://github.com/google/googletest/pull/1066

View File

@ -59,13 +59,7 @@ cross-platform.). If you don't have CMake installed already, you can
download it for free from <http://www.cmake.org/>. download it for free from <http://www.cmake.org/>.
CMake works by generating native makefiles or build projects that can CMake works by generating native makefiles or build projects that can
be used in the compiler environment of your choice. You can either be used in the compiler environment of your choice. The typical
build Google Test as a standalone project or it can be incorporated
into an existing CMake build for another project.
#### Standalone CMake Project ####
When building Google Test as a standalone project, the typical
workflow starts with: workflow starts with:
mkdir mybuild # Create a directory to hold the build output. mkdir mybuild # Create a directory to hold the build output.
@ -86,122 +80,13 @@ using Visual Studio.
On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated. On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
#### Incorporating Into An Existing CMake Project ####
If you want to use gtest in a project which already uses CMake, then a
more robust and flexible approach is to build gtest as part of that
project directly. This is done by making the GoogleTest source code
available to the main build and adding it using CMake's
`add_subdirectory()` command. This has the significant advantage that
the same compiler and linker settings are used between gtest and the
rest of your project, so issues associated with using incompatible
libraries (eg debug/release), etc. are avoided. This is particularly
useful on Windows. Making GoogleTest's source code available to the
main build can be done a few different ways:
* Download the GoogleTest source code manually and place it at a
known location. This is the least flexible approach and can make
it more difficult to use with continuous integration systems, etc.
* Embed the GoogleTest source code as a direct copy in the main
project's source tree. This is often the simplest approach, but is
also the hardest to keep up to date. Some organizations may not
permit this method.
* Add GoogleTest as a git submodule or equivalent. This may not
always be possible or appropriate. Git submodules, for example,
have their own set of advantages and drawbacks.
* Use CMake to download GoogleTest as part of the build's configure
step. This is just a little more complex, but doesn't have the
limitations of the other methods.
The last of the above methods is implemented with a small piece
of CMake code in a separate file (e.g. `CMakeLists.txt.in`) which
is copied to the build area and then invoked as a sub-build
_during the CMake stage_. That directory is then pulled into the
main build with `add_subdirectory()`. For example:
New file `CMakeLists.txt.in`:
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
Existing build's `CMakeLists.txt`:
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include")
endif()
# Now simply link against gtest or gtest_main as needed. Eg
add_executable(example example.cpp)
target_link_libraries(example gtest_main)
add_test(NAME example_test COMMAND example)
Note that this approach requires CMake 2.8.2 or later due to
its use of the `ExternalProject_Add()` command. The above
technique is discussed in more detail in
[this separate article](http://crascit.com/2015/07/25/cmake-gtest/)
which also contains a link to a fully generalized implementation
of the technique.
##### Visual Studio Dynamic vs Static Runtimes #####
By default, new Visual Studio projects link the C runtimes dynamically
but Google Test links them statically.
This will generate an error that looks something like the following:
gtest.lib(gtest-all.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in main.obj
Google Test already has a CMake option for this: `gtest_force_shared_crt`
Enabling this option will make gtest link the runtimes dynamically too,
and match the project in which it is included.
### Legacy Build Scripts ### ### Legacy Build Scripts ###
Before settling on CMake, we have been providing hand-maintained build Before settling on CMake, we have been providing hand-maintained build
projects/scripts for Visual Studio, Xcode, and Autotools. While we projects/scripts for Visual Studio, Xcode, and Autotools. While we
continue to provide them for convenience, they are not actively continue to provide them for convenience, they are not actively
maintained any more. We highly recommend that you follow the maintained any more. We highly recommend that you follow the
instructions in the above sections to integrate Google Test instructions in the previous two sections to integrate Google Test
with your existing build system. with your existing build system.
If you still need to use the legacy build scripts, here's how: If you still need to use the legacy build scripts, here's how:
@ -358,3 +243,38 @@ instead of
TEST(SomeTest, DoesThis) { ... } TEST(SomeTest, DoesThis) { ... }
in order to define a test. in order to define a test.
## Developing Google Test ##
This section discusses how to make your own changes to Google Test.
### Testing Google Test Itself ###
To make sure your changes work as intended and don't break existing
functionality, you'll want to compile and run Google Test's own tests.
For that you can use CMake:
mkdir mybuild
cd mybuild
cmake -Dgtest_build_tests=ON ${GTEST_DIR}
Make sure you have Python installed, as some of Google Test's tests
are written in Python. If the cmake command complains about not being
able to find Python (`Could NOT find PythonInterp (missing:
PYTHON_EXECUTABLE)`), try telling it explicitly where your Python
executable can be found:
cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
Next, you can build Google Test and all of its own tests. On \*nix,
this is usually done by 'make'. To run the tests, do
make test
All tests should pass.
Normally you don't need to worry about regenerating the source files,
unless you need to modify them. In that case, you should modify the
corresponding .pump files instead and run the pump.py Python script to
regenerate them. You can find pump.py in the [scripts/](scripts/) directory.
Read the [Pump manual](docs/PumpManual.md) for how to use it.

View File

@ -102,7 +102,7 @@ GTEST_API_ bool InDeathTestChild();
// On POSIX-compliant systems (*nix), we use the <regex.h> library, // On POSIX-compliant systems (*nix), we use the <regex.h> library,
// which uses the POSIX extended regex syntax. // which uses the POSIX extended regex syntax.
// //
// On other platforms (e.g. Windows or Mac), we only support a simple regex // On other platforms (e.g. Windows), we only support a simple regex
// syntax implemented as part of Google Test. This limited // syntax implemented as part of Google Test. This limited
// implementation should be enough most of the time when writing // implementation should be enough most of the time when writing
// death tests; though it lacks many features you can find in PCRE // death tests; though it lacks many features you can find in PCRE
@ -272,54 +272,6 @@ class GTEST_API_ KilledBySignal {
# endif // NDEBUG for EXPECT_DEBUG_DEATH # endif // NDEBUG for EXPECT_DEBUG_DEATH
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
// This macro is used for implementing macros such as
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
// death tests are not supported. Those macros must compile on such systems
// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
// systems that support death tests. This allows one to write such a macro
// on a system that does not support death tests and be sure that it will
// compile on a death-test supporting system. It is exposed publicly so that
// systems that have death-tests with stricter requirements than
// GTEST_HAS_DEATH_TEST can write their own equivalent of
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED.
//
// Parameters:
// statement - A statement that a macro such as EXPECT_DEATH would test
// for program termination. This macro has to make sure this
// statement is compiled but not executed, to ensure that
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
// parameter iff EXPECT_DEATH compiles with it.
// regex - A regex that a macro such as EXPECT_DEATH would use to test
// the output of statement. This parameter has to be
// compiled but not evaluated by this macro, to ensure that
// this macro only accepts expressions that a macro such as
// EXPECT_DEATH would accept.
// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
// compile inside functions where ASSERT_DEATH doesn't
// compile.
//
// The branch that has an always false condition is used to ensure that
// statement and regex are compiled (and thus syntactically correct) but
// never executed. The unreachable code macro protects the terminator
// statement from generating an 'unreachable code' warning in case
// statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) \
<< "Death tests are not supported on this platform.\n" \
<< "Statement '" #statement "' cannot be verified."; \
} else if (::testing::internal::AlwaysFalse()) { \
::testing::internal::RE::PartialMatch(".*", (regex)); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
terminator; \
} else \
::testing::Message()
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and // EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if // ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
// death tests are supported; otherwise they just issue a warning. This is // death tests are supported; otherwise they just issue a warning. This is
@ -332,9 +284,9 @@ class GTEST_API_ KilledBySignal {
ASSERT_DEATH(statement, regex) ASSERT_DEATH(statement, regex)
#else #else
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ # define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, ) GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ # define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return) GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
#endif #endif
} // namespace testing } // namespace testing

View File

@ -196,6 +196,7 @@ class GTEST_API_ Message {
std::string GetString() const; std::string GetString() const;
private: private:
#if GTEST_OS_SYMBIAN #if GTEST_OS_SYMBIAN
// These are needed as the Nokia Symbian Compiler cannot decide between // These are needed as the Nokia Symbian Compiler cannot decide between
// const T& and const T* in a function template. The Nokia compiler _can_ // const T& and const T* in a function template. The Nokia compiler _can_

View File

@ -38,7 +38,6 @@
// //
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! // This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
// //
#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ #ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
@ -80,7 +79,7 @@ TEST_P(FooTest, HasBlahBlah) {
// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test // Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
// case with any set of parameters you want. Google Test defines a number // case with any set of parameters you want. Google Test defines a number
// of functions for generating test parameters. They return what we call // of functions for generating test parameters. They return what we call
// (surprise!) parameter generators. Here is a summary of them, which // (surprise!) parameter generators. Here is a summary of them, which
// are all in the testing namespace: // are all in the testing namespace:
// //
// //
@ -186,10 +185,15 @@ TEST_P(DerivedTest, DoesBlah) {
# include <utility> # include <utility>
#endif #endif
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-param-util.h" #include "gtest/internal/gtest-param-util.h"
#include "gtest/internal/gtest-param-util-generated.h" #include "gtest/internal/gtest-param-util-generated.h"
#if GTEST_HAS_PARAM_TEST
namespace testing { namespace testing {
// Functions producing parameter generators. // Functions producing parameter generators.
@ -269,7 +273,7 @@ internal::ParamGenerator<T> Range(T start, T end) {
// each with C-string values of "foo", "bar", and "baz": // each with C-string values of "foo", "bar", and "baz":
// //
// const char* strings[] = {"foo", "bar", "baz"}; // const char* strings[] = {"foo", "bar", "baz"};
// INSTANTIATE_TEST_CASE_P(StringSequence, StringTest, ValuesIn(strings)); // INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
// //
// This instantiates tests from test case StlStringTest // This instantiates tests from test case StlStringTest
// each with STL strings with values "a" and "b": // each with STL strings with values "a" and "b":
@ -1371,6 +1375,8 @@ internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
} }
# endif // GTEST_HAS_COMBINE # endif // GTEST_HAS_COMBINE
# define TEST_P(test_case_name, test_name) \ # define TEST_P(test_case_name, test_name) \
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
: public test_case_name { \ : public test_case_name { \
@ -1384,8 +1390,8 @@ internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
#test_case_name, \ #test_case_name, \
::testing::internal::CodeLocation(\ ::testing::internal::CodeLocation(\
__FILE__, __LINE__))->AddTestPattern(\ __FILE__, __LINE__))->AddTestPattern(\
GTEST_STRINGIFY_(test_case_name), \ #test_case_name, \
GTEST_STRINGIFY_(test_name), \ #test_name, \
new ::testing::internal::TestMetaFactory< \ new ::testing::internal::TestMetaFactory< \
GTEST_TEST_CLASS_NAME_(\ GTEST_TEST_CLASS_NAME_(\
test_case_name, test_name)>()); \ test_case_name, test_name)>()); \
@ -1406,33 +1412,33 @@ internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
// type testing::TestParamInfo<class ParamType>, and return std::string. // type testing::TestParamInfo<class ParamType>, and return std::string.
// //
// testing::PrintToStringParamName is a builtin test suffix generator that // testing::PrintToStringParamName is a builtin test suffix generator that
// returns the value of testing::PrintToString(GetParam()). // returns the value of testing::PrintToString(GetParam()). It does not work
// for std::string or C strings.
// //
// Note: test names must be non-empty, unique, and may only contain ASCII // Note: test names must be non-empty, unique, and may only contain ASCII
// alphanumeric characters or underscore. Because PrintToString adds quotes // alphanumeric characters or underscore.
// to std::string and C strings, it won't work for these types.
#define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \ # define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \
static ::testing::internal::ParamGenerator<test_case_name::ParamType> \ ::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { \ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
return generator; \ ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \
} \ const ::testing::TestParamInfo<test_case_name::ParamType>& info) { \
static ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \ return ::testing::internal::GetParamNameGen<test_case_name::ParamType> \
const ::testing::TestParamInfo<test_case_name::ParamType>& info) { \ (__VA_ARGS__)(info); \
return ::testing::internal::GetParamNameGen<test_case_name::ParamType>( \ } \
__VA_ARGS__)(info); \ int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \
} \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
static int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \ GetTestCasePatternHolder<test_case_name>(\
::testing::UnitTest::GetInstance() \ #test_case_name, \
->parameterized_test_registry() \ ::testing::internal::CodeLocation(\
.GetTestCasePatternHolder<test_case_name>( \ __FILE__, __LINE__))->AddTestCaseInstantiation(\
#test_case_name, \ #prefix, \
::testing::internal::CodeLocation(__FILE__, __LINE__)) \ &gtest_##prefix##test_case_name##_EvalGenerator_, \
->AddTestCaseInstantiation( \ &gtest_##prefix##test_case_name##_EvalGenerateName_, \
#prefix, &gtest_##prefix##test_case_name##_EvalGenerator_, \ __FILE__, __LINE__)
&gtest_##prefix##test_case_name##_EvalGenerateName_, __FILE__, \
__LINE__)
} // namespace testing } // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ #endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_

View File

@ -78,7 +78,7 @@ TEST_P(FooTest, HasBlahBlah) {
// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test // Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
// case with any set of parameters you want. Google Test defines a number // case with any set of parameters you want. Google Test defines a number
// of functions for generating test parameters. They return what we call // of functions for generating test parameters. They return what we call
// (surprise!) parameter generators. Here is a summary of them, which // (surprise!) parameter generators. Here is a summary of them, which
// are all in the testing namespace: // are all in the testing namespace:
// //
// //
@ -184,10 +184,15 @@ TEST_P(DerivedTest, DoesBlah) {
# include <utility> # include <utility>
#endif #endif
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-param-util.h" #include "gtest/internal/gtest-param-util.h"
#include "gtest/internal/gtest-param-util-generated.h" #include "gtest/internal/gtest-param-util-generated.h"
#if GTEST_HAS_PARAM_TEST
namespace testing { namespace testing {
// Functions producing parameter generators. // Functions producing parameter generators.
@ -267,7 +272,7 @@ internal::ParamGenerator<T> Range(T start, T end) {
// each with C-string values of "foo", "bar", and "baz": // each with C-string values of "foo", "bar", and "baz":
// //
// const char* strings[] = {"foo", "bar", "baz"}; // const char* strings[] = {"foo", "bar", "baz"};
// INSTANTIATE_TEST_CASE_P(StringSequence, StringTest, ValuesIn(strings)); // INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
// //
// This instantiates tests from test case StlStringTest // This instantiates tests from test case StlStringTest
// each with STL strings with values "a" and "b": // each with STL strings with values "a" and "b":
@ -436,6 +441,8 @@ internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
]] ]]
# endif // GTEST_HAS_COMBINE # endif // GTEST_HAS_COMBINE
# define TEST_P(test_case_name, test_name) \ # define TEST_P(test_case_name, test_name) \
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
: public test_case_name { \ : public test_case_name { \
@ -449,8 +456,8 @@ internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
#test_case_name, \ #test_case_name, \
::testing::internal::CodeLocation(\ ::testing::internal::CodeLocation(\
__FILE__, __LINE__))->AddTestPattern(\ __FILE__, __LINE__))->AddTestPattern(\
GTEST_STRINGIFY_(test_case_name), \ #test_case_name, \
GTEST_STRINGIFY_(test_name), \ #test_name, \
new ::testing::internal::TestMetaFactory< \ new ::testing::internal::TestMetaFactory< \
GTEST_TEST_CLASS_NAME_(\ GTEST_TEST_CLASS_NAME_(\
test_case_name, test_name)>()); \ test_case_name, test_name)>()); \
@ -478,14 +485,14 @@ internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
// to std::string and C strings, it won't work for these types. // to std::string and C strings, it won't work for these types.
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \ # define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \
static ::testing::internal::ParamGenerator<test_case_name::ParamType> \ ::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
static ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \ ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \
const ::testing::TestParamInfo<test_case_name::ParamType>& info) { \ const ::testing::TestParamInfo<test_case_name::ParamType>& info) { \
return ::testing::internal::GetParamNameGen<test_case_name::ParamType> \ return ::testing::internal::GetParamNameGen<test_case_name::ParamType> \
(__VA_ARGS__)(info); \ (__VA_ARGS__)(info); \
} \ } \
static int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \ int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\ GetTestCasePatternHolder<test_case_name>(\
#test_case_name, \ #test_case_name, \
@ -498,4 +505,6 @@ internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
} // namespace testing } // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ #endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_

View File

@ -46,10 +46,6 @@
// 2. operator<<(ostream&, const T&) defined in either foo or the // 2. operator<<(ostream&, const T&) defined in either foo or the
// global namespace. // global namespace.
// //
// However if T is an STL-style container then it is printed element-wise
// unless foo::PrintTo(const T&, ostream*) is defined. Note that
// operator<<() is ignored for container types.
//
// If none of the above is defined, it will print the debug string of // If none of the above is defined, it will print the debug string of
// the value if it is a protocol buffer, or print the raw bytes in the // the value if it is a protocol buffer, or print the raw bytes in the
// value otherwise. // value otherwise.
@ -111,11 +107,6 @@
# include <tuple> # include <tuple>
#endif #endif
#if GTEST_HAS_ABSL
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#endif // GTEST_HAS_ABSL
namespace testing { namespace testing {
// Definitions in the 'internal' and 'internal2' name spaces are // Definitions in the 'internal' and 'internal2' name spaces are
@ -134,11 +125,7 @@ enum TypeKind {
kProtobuf, // a protobuf type kProtobuf, // a protobuf type
kConvertibleToInteger, // a type implicitly convertible to BiggestInt kConvertibleToInteger, // a type implicitly convertible to BiggestInt
// (e.g. a named or unnamed enum type) // (e.g. a named or unnamed enum type)
#if GTEST_HAS_ABSL kOtherType // anything else
kConvertibleToStringView, // a type implicitly convertible to
// absl::string_view
#endif
kOtherType // anything else
}; };
// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called // TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
@ -150,8 +137,7 @@ class TypeWithoutFormatter {
public: public:
// This default version is called when kTypeKind is kOtherType. // This default version is called when kTypeKind is kOtherType.
static void PrintValue(const T& value, ::std::ostream* os) { static void PrintValue(const T& value, ::std::ostream* os) {
PrintBytesInObjectTo(static_cast<const unsigned char*>( PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
reinterpret_cast<const void*>(&value)),
sizeof(value), os); sizeof(value), os);
} }
}; };
@ -165,10 +151,10 @@ template <typename T>
class TypeWithoutFormatter<T, kProtobuf> { class TypeWithoutFormatter<T, kProtobuf> {
public: public:
static void PrintValue(const T& value, ::std::ostream* os) { static void PrintValue(const T& value, ::std::ostream* os) {
std::string pretty_str = value.ShortDebugString(); const ::testing::internal::string short_str = value.ShortDebugString();
if (pretty_str.length() > kProtobufOneLinerMaxLength) { const ::testing::internal::string pretty_str =
pretty_str = "\n" + value.DebugString(); short_str.length() <= kProtobufOneLinerMaxLength ?
} short_str : ("\n" + value.DebugString());
*os << ("<" + pretty_str + ">"); *os << ("<" + pretty_str + ">");
} }
}; };
@ -189,19 +175,6 @@ class TypeWithoutFormatter<T, kConvertibleToInteger> {
} }
}; };
#if GTEST_HAS_ABSL
template <typename T>
class TypeWithoutFormatter<T, kConvertibleToStringView> {
public:
// Since T has neither operator<< nor PrintTo() but can be implicitly
// converted to absl::string_view, we print it as a absl::string_view.
//
// Note: the implementation is further below, as it depends on
// internal::PrintTo symbol which is defined later in the file.
static void PrintValue(const T& value, ::std::ostream* os);
};
#endif
// Prints the given value to the given ostream. If the value is a // Prints the given value to the given ostream. If the value is a
// protocol message, its debug string is printed; if it's an enum or // protocol message, its debug string is printed; if it's an enum or
// of a type implicitly convertible to BiggestInt, it's printed as an // of a type implicitly convertible to BiggestInt, it's printed as an
@ -229,19 +202,10 @@ class TypeWithoutFormatter<T, kConvertibleToStringView> {
template <typename Char, typename CharTraits, typename T> template <typename Char, typename CharTraits, typename T>
::std::basic_ostream<Char, CharTraits>& operator<<( ::std::basic_ostream<Char, CharTraits>& operator<<(
::std::basic_ostream<Char, CharTraits>& os, const T& x) { ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value TypeWithoutFormatter<T,
? kProtobuf (internal::IsAProtocolMessage<T>::value ? kProtobuf :
: internal::ImplicitlyConvertible< internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
const T&, internal::BiggestInt>::value kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
? kConvertibleToInteger
:
#if GTEST_HAS_ABSL
internal::ImplicitlyConvertible<
const T&, absl::string_view>::value
? kConvertibleToStringView
:
#endif
kOtherType)>::PrintValue(x, &os);
return os; return os;
} }
@ -400,18 +364,11 @@ class UniversalPrinter;
template <typename T> template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os); void UniversalPrint(const T& value, ::std::ostream* os);
enum DefaultPrinterType {
kPrintContainer,
kPrintPointer,
kPrintFunctionPointer,
kPrintOther,
};
template <DefaultPrinterType type> struct WrapPrinterType {};
// Used to print an STL-style container when the user doesn't define // Used to print an STL-style container when the user doesn't define
// a PrintTo() for it. // a PrintTo() for it.
template <typename C> template <typename C>
void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */, void DefaultPrintTo(IsContainer /* dummy */,
false_type /* is not a pointer */,
const C& container, ::std::ostream* os) { const C& container, ::std::ostream* os) {
const size_t kMaxCount = 32; // The maximum number of elements to print. const size_t kMaxCount = 32; // The maximum number of elements to print.
*os << '{'; *os << '{';
@ -444,34 +401,40 @@ void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
// implementation-defined. Therefore they will be printed as raw // implementation-defined. Therefore they will be printed as raw
// bytes.) // bytes.)
template <typename T> template <typename T>
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */, void DefaultPrintTo(IsNotContainer /* dummy */,
true_type /* is a pointer */,
T* p, ::std::ostream* os) { T* p, ::std::ostream* os) {
if (p == NULL) { if (p == NULL) {
*os << "NULL"; *os << "NULL";
} else { } else {
// T is not a function type. We just call << to print p, // C++ doesn't allow casting from a function pointer to any object
// relying on ADL to pick up user-defined << for their pointer // pointer.
// types, if any. //
*os << p; // IsTrue() silences warnings: "Condition is always true",
} // "unreachable code".
} if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
template <typename T> // T is not a function type. We just call << to print p,
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */, // relying on ADL to pick up user-defined << for their pointer
T* p, ::std::ostream* os) { // types, if any.
if (p == NULL) { *os << p;
*os << "NULL"; } else {
} else { // T is a function type, so '*os << p' doesn't do what we want
// T is a function type, so '*os << p' doesn't do what we want // (it just prints p as bool). We want to print p as a const
// (it just prints p as bool). We want to print p as a const // void*. However, we cannot cast it to const void* directly,
// void*. // even using reinterpret_cast, as earlier versions of gcc
*os << reinterpret_cast<const void*>(p); // (e.g. 3.4.5) cannot compile the cast when p is a function
// pointer. Casting to UInt64 first solves the problem.
*os << reinterpret_cast<const void*>(
reinterpret_cast<internal::UInt64>(p));
}
} }
} }
// Used to print a non-container, non-pointer value when the user // Used to print a non-container, non-pointer value when the user
// doesn't define PrintTo() for it. // doesn't define PrintTo() for it.
template <typename T> template <typename T>
void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */, void DefaultPrintTo(IsNotContainer /* dummy */,
false_type /* is not a pointer */,
const T& value, ::std::ostream* os) { const T& value, ::std::ostream* os) {
::testing_internal::DefaultPrintNonContainerTo(value, os); ::testing_internal::DefaultPrintNonContainerTo(value, os);
} }
@ -489,8 +452,11 @@ void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */,
// wants). // wants).
template <typename T> template <typename T>
void PrintTo(const T& value, ::std::ostream* os) { void PrintTo(const T& value, ::std::ostream* os) {
// DefaultPrintTo() is overloaded. The type of its first argument // DefaultPrintTo() is overloaded. The type of its first two
// determines which version will be picked. // arguments determine which version will be picked. If T is an
// STL-style container, the version for container will be called; if
// T is a pointer, the pointer version will be called; otherwise the
// generic version will be called.
// //
// Note that we check for container types here, prior to we check // Note that we check for container types here, prior to we check
// for protocol message types in our operator<<. The rationale is: // for protocol message types in our operator<<. The rationale is:
@ -502,27 +468,13 @@ void PrintTo(const T& value, ::std::ostream* os) {
// elements; therefore we check for container types here to ensure // elements; therefore we check for container types here to ensure
// that our format is used. // that our format is used.
// //
// Note that MSVC and clang-cl do allow an implicit conversion from // The second argument of DefaultPrintTo() is needed to bypass a bug
// pointer-to-function to pointer-to-object, but clang-cl warns on it. // in Symbian's C++ compiler that prevents it from picking the right
// So don't use ImplicitlyConvertible if it can be helped since it will // overload between:
// cause this warning, and use a separate overload of DefaultPrintTo for //
// function pointers so that the `*os << p` in the object pointer overload // PrintTo(const T& x, ...);
// doesn't cause that warning either. // PrintTo(T* x, ...);
DefaultPrintTo( DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
WrapPrinterType <
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
!IsRecursiveContainer<T>::value
? kPrintContainer
: !is_pointer<T>::value
? kPrintOther
#if GTEST_LANG_CXX11
: std::is_function<typename std::remove_pointer<T>::type>::value
#else
: !internal::ImplicitlyConvertible<T, const void*>::value
#endif
? kPrintFunctionPointer
: kPrintPointer > (),
value, os);
} }
// The following list of PrintTo() overloads tells // The following list of PrintTo() overloads tells
@ -629,13 +581,6 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
} }
#endif // GTEST_HAS_STD_WSTRING #endif // GTEST_HAS_STD_WSTRING
#if GTEST_HAS_ABSL
// Overload for absl::string_view.
inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
PrintTo(::std::string(sp), os);
}
#endif // GTEST_HAS_ABSL
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_ #if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
// Helper function for printing a tuple. T must be instantiated with // Helper function for printing a tuple. T must be instantiated with
// a tuple type. // a tuple type.
@ -765,26 +710,6 @@ class UniversalPrinter {
GTEST_DISABLE_MSC_WARNINGS_POP_() GTEST_DISABLE_MSC_WARNINGS_POP_()
}; };
#if GTEST_HAS_ABSL
// Printer for absl::optional
template <typename T>
class UniversalPrinter<::absl::optional<T>> {
public:
static void Print(const ::absl::optional<T>& value, ::std::ostream* os) {
*os << '(';
if (!value) {
*os << "nullopt";
} else {
UniversalPrint(*value, os);
}
*os << ')';
}
};
#endif // GTEST_HAS_ABSL
// UniversalPrintArray(begin, len, os) prints an array of 'len' // UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'. // elements, starting at address 'begin'.
template <typename T> template <typename T>
@ -880,7 +805,7 @@ class UniversalTersePrinter<const char*> {
if (str == NULL) { if (str == NULL) {
*os << "NULL"; *os << "NULL";
} else { } else {
UniversalPrint(std::string(str), os); UniversalPrint(string(str), os);
} }
} }
}; };
@ -931,7 +856,7 @@ void UniversalPrint(const T& value, ::std::ostream* os) {
UniversalPrinter<T1>::Print(value, os); UniversalPrinter<T1>::Print(value, os);
} }
typedef ::std::vector< ::std::string> Strings; typedef ::std::vector<string> Strings;
// TuplePolicy<TupleT> must provide: // TuplePolicy<TupleT> must provide:
// - tuple_size // - tuple_size
@ -1051,16 +976,6 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
} // namespace internal } // namespace internal
#if GTEST_HAS_ABSL
namespace internal2 {
template <typename T>
void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
const T& value, ::std::ostream* os) {
internal::PrintTo(absl::string_view(value), os);
}
} // namespace internal2
#endif
template <typename T> template <typename T>
::std::string PrintToString(const T& value) { ::std::string PrintToString(const T& value) {
::std::stringstream ss; ::std::stringstream ss;

View File

@ -97,12 +97,13 @@ class GTEST_API_ SingleFailureChecker {
public: public:
// The constructor remembers the arguments. // The constructor remembers the arguments.
SingleFailureChecker(const TestPartResultArray* results, SingleFailureChecker(const TestPartResultArray* results,
TestPartResult::Type type, const std::string& substr); TestPartResult::Type type,
const string& substr);
~SingleFailureChecker(); ~SingleFailureChecker();
private: private:
const TestPartResultArray* const results_; const TestPartResultArray* const results_;
const TestPartResult::Type type_; const TestPartResult::Type type_;
const std::string substr_; const string substr_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
}; };

View File

@ -241,10 +241,9 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
namespace GTEST_CASE_NAMESPACE_(CaseName) { \ namespace GTEST_CASE_NAMESPACE_(CaseName) { \
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
} \ } \
static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) \ static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames( \ __FILE__, __LINE__, #__VA_ARGS__)
__FILE__, __LINE__, #__VA_ARGS__)
// The 'Types' template argument below must have spaces around it // The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template // since some compilers may choke on '>>' when passing a template

View File

@ -115,9 +115,6 @@ GTEST_DECLARE_string_(output);
// test. // test.
GTEST_DECLARE_bool_(print_time); GTEST_DECLARE_bool_(print_time);
// This flags control whether Google Test prints UTF8 characters as text.
GTEST_DECLARE_bool_(print_utf8);
// This flag specifies the random number seed. // This flag specifies the random number seed.
GTEST_DECLARE_int32_(random_seed); GTEST_DECLARE_int32_(random_seed);
@ -138,7 +135,7 @@ GTEST_DECLARE_int32_(stack_trace_depth);
// When this flag is specified, a failed assertion will throw an // When this flag is specified, a failed assertion will throw an
// exception if exceptions are enabled, or exit the program with a // exception if exceptions are enabled, or exit the program with a
// non-zero code otherwise. For use with an external test framework. // non-zero code otherwise.
GTEST_DECLARE_bool_(throw_on_failure); GTEST_DECLARE_bool_(throw_on_failure);
// When this flag is set with a "host:port" string, on supported // When this flag is set with a "host:port" string, on supported
@ -262,9 +259,7 @@ class GTEST_API_ AssertionResult {
// Used in EXPECT_TRUE/FALSE(assertion_result). // Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult(const AssertionResult& other); AssertionResult(const AssertionResult& other);
#if defined(_MSC_VER) && _MSC_VER < 1910
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
#endif
// Used in the EXPECT_TRUE/FALSE(bool_expression). // Used in the EXPECT_TRUE/FALSE(bool_expression).
// //
@ -281,9 +276,7 @@ class GTEST_API_ AssertionResult {
/*enabler*/ = NULL) /*enabler*/ = NULL)
: success_(success) {} : success_(success) {}
#if defined(_MSC_VER) && _MSC_VER < 1910
GTEST_DISABLE_MSC_WARNINGS_POP_() GTEST_DISABLE_MSC_WARNINGS_POP_()
#endif
// Assignment operator. // Assignment operator.
AssertionResult& operator=(AssertionResult other) { AssertionResult& operator=(AssertionResult other) {
@ -352,15 +345,6 @@ GTEST_API_ AssertionResult AssertionFailure();
// Deprecated; use AssertionFailure() << msg. // Deprecated; use AssertionFailure() << msg.
GTEST_API_ AssertionResult AssertionFailure(const Message& msg); GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
} // namespace testing
// Includes the auto-generated header that implements a family of generic
// predicate assertion macros. This include comes late because it relies on
// APIs declared above.
#include "gtest/gtest_pred_impl.h"
namespace testing {
// The abstract class that all tests inherit from. // The abstract class that all tests inherit from.
// //
// In Google Test, a unit test program contains one or many TestCases, and // In Google Test, a unit test program contains one or many TestCases, and
@ -371,7 +355,7 @@ namespace testing {
// this for you. // this for you.
// //
// The only time you derive from Test is when defining a test fixture // The only time you derive from Test is when defining a test fixture
// to be used in a TEST_F. For example: // to be used a TEST_F. For example:
// //
// class FooTest : public testing::Test { // class FooTest : public testing::Test {
// protected: // protected:
@ -566,8 +550,9 @@ class GTEST_API_ TestResult {
// Returns the elapsed time, in milliseconds. // Returns the elapsed time, in milliseconds.
TimeInMillis elapsed_time() const { return elapsed_time_; } TimeInMillis elapsed_time() const { return elapsed_time_; }
// Returns the i-th test part result among all the results. i can range from 0 // Returns the i-th test part result among all the results. i can range
// to total_part_count() - 1. If i is not in that range, aborts the program. // from 0 to test_property_count() - 1. If i is not in that range, aborts
// the program.
const TestPartResult& GetTestPartResult(int i) const; const TestPartResult& GetTestPartResult(int i) const;
// Returns the i-th test property. i can range from 0 to // Returns the i-th test property. i can range from 0 to
@ -690,9 +675,6 @@ class GTEST_API_ TestInfo {
// Returns the line where this test is defined. // Returns the line where this test is defined.
int line() const { return location_.line; } int line() const { return location_.line; }
// Return true if this test should not be run because it's in another shard.
bool is_in_another_shard() const { return is_in_another_shard_; }
// Returns true if this test should run, that is if the test is not // Returns true if this test should run, that is if the test is not
// disabled (or it is disabled but the also_run_disabled_tests flag has // disabled (or it is disabled but the also_run_disabled_tests flag has
// been specified) and its full name matches the user-specified filter. // been specified) and its full name matches the user-specified filter.
@ -713,9 +695,10 @@ class GTEST_API_ TestInfo {
// Returns true iff this test will appear in the XML report. // Returns true iff this test will appear in the XML report.
bool is_reportable() const { bool is_reportable() const {
// The XML report includes tests matching the filter, excluding those // For now, the XML report includes all tests matching the filter.
// run in other shards. // In the future, we may trim tests that are excluded because of
return matches_filter_ && !is_in_another_shard_; // sharding.
return matches_filter_;
} }
// Returns the result of the test. // Returns the result of the test.
@ -779,7 +762,6 @@ class GTEST_API_ TestInfo {
bool is_disabled_; // True iff this test is disabled bool is_disabled_; // True iff this test is disabled
bool matches_filter_; // True if this test matches the bool matches_filter_; // True if this test matches the
// user-specified filter. // user-specified filter.
bool is_in_another_shard_; // Will be run in another shard.
internal::TestFactoryBase* const factory_; // The factory that creates internal::TestFactoryBase* const factory_; // The factory that creates
// the test object // the test object
@ -1004,18 +986,6 @@ class Environment {
virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
}; };
#if GTEST_HAS_EXCEPTIONS
// Exception which can be thrown from TestEventListener::OnTestPartResult.
class GTEST_API_ AssertionException
: public internal::GoogleTestFailureException {
public:
explicit AssertionException(const TestPartResult& result)
: GoogleTestFailureException(result) {}
};
#endif // GTEST_HAS_EXCEPTIONS
// The interface for tracing execution of tests. The methods are organized in // The interface for tracing execution of tests. The methods are organized in
// the order the corresponding events are fired. // the order the corresponding events are fired.
class TestEventListener { class TestEventListener {
@ -1044,8 +1014,6 @@ class TestEventListener {
virtual void OnTestStart(const TestInfo& test_info) = 0; virtual void OnTestStart(const TestInfo& test_info) = 0;
// Fired after a failed assertion or a SUCCEED() invocation. // Fired after a failed assertion or a SUCCEED() invocation.
// If you want to throw an exception from this function to skip to the next
// TEST, it must be AssertionException defined above, or inherited from it.
virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
// Fired after the test ends. // Fired after the test ends.
@ -1212,12 +1180,14 @@ class GTEST_API_ UnitTest {
// Returns the random seed used at the start of the current test run. // Returns the random seed used at the start of the current test run.
int random_seed() const; int random_seed() const;
#if GTEST_HAS_PARAM_TEST
// Returns the ParameterizedTestCaseRegistry object used to keep track of // Returns the ParameterizedTestCaseRegistry object used to keep track of
// value-parameterized tests and instantiate and register them. // value-parameterized tests and instantiate and register them.
// //
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
internal::ParameterizedTestCaseRegistry& parameterized_test_registry() internal::ParameterizedTestCaseRegistry& parameterized_test_registry()
GTEST_LOCK_EXCLUDED_(mutex_); GTEST_LOCK_EXCLUDED_(mutex_);
#endif // GTEST_HAS_PARAM_TEST
// Gets the number of successful test cases. // Gets the number of successful test cases.
int successful_test_case_count() const; int successful_test_case_count() const;
@ -1317,11 +1287,11 @@ class GTEST_API_ UnitTest {
internal::UnitTestImpl* impl() { return impl_; } internal::UnitTestImpl* impl() { return impl_; }
const internal::UnitTestImpl* impl() const { return impl_; } const internal::UnitTestImpl* impl() const { return impl_; }
// These classes and functions are friends as they need to access private // These classes and funcions are friends as they need to access private
// members of UnitTest. // members of UnitTest.
friend class ScopedTrace;
friend class Test; friend class Test;
friend class internal::AssertHelper; friend class internal::AssertHelper;
friend class internal::ScopedTrace;
friend class internal::StreamingListenerTest; friend class internal::StreamingListenerTest;
friend class internal::UnitTestRecordPropertyTestHelper; friend class internal::UnitTestRecordPropertyTestHelper;
friend Environment* AddGlobalTestEnvironment(Environment* env); friend Environment* AddGlobalTestEnvironment(Environment* env);
@ -1418,9 +1388,11 @@ AssertionResult CmpHelperEQ(const char* lhs_expression,
const char* rhs_expression, const char* rhs_expression,
const T1& lhs, const T1& lhs,
const T2& rhs) { const T2& rhs) {
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4389 /* signed/unsigned mismatch */)
if (lhs == rhs) { if (lhs == rhs) {
return AssertionSuccess(); return AssertionSuccess();
} }
GTEST_DISABLE_MSC_WARNINGS_POP_()
return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs); return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs);
} }
@ -1734,6 +1706,7 @@ class GTEST_API_ AssertHelper {
} // namespace internal } // namespace internal
#if GTEST_HAS_PARAM_TEST
// The pure interface class that all value-parameterized tests inherit from. // The pure interface class that all value-parameterized tests inherit from.
// A value-parameterized class must inherit from both ::testing::Test and // A value-parameterized class must inherit from both ::testing::Test and
// ::testing::WithParamInterface. In most cases that just means inheriting // ::testing::WithParamInterface. In most cases that just means inheriting
@ -1810,6 +1783,8 @@ template <typename T>
class TestWithParam : public Test, public WithParamInterface<T> { class TestWithParam : public Test, public WithParamInterface<T> {
}; };
#endif // GTEST_HAS_PARAM_TEST
// Macros for indicating success/failure in test code. // Macros for indicating success/failure in test code.
// ADD_FAILURE unconditionally adds a failure to the current test. // ADD_FAILURE unconditionally adds a failure to the current test.
@ -1882,18 +1857,22 @@ class TestWithParam : public Test, public WithParamInterface<T> {
// AssertionResult. For more information on how to use AssertionResult with // AssertionResult. For more information on how to use AssertionResult with
// these macros see comments on that class. // these macros see comments on that class.
#define EXPECT_TRUE(condition) \ #define EXPECT_TRUE(condition) \
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \
GTEST_NONFATAL_FAILURE_) GTEST_NONFATAL_FAILURE_)
#define EXPECT_FALSE(condition) \ #define EXPECT_FALSE(condition) \
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
GTEST_NONFATAL_FAILURE_) GTEST_NONFATAL_FAILURE_)
#define ASSERT_TRUE(condition) \ #define ASSERT_TRUE(condition) \
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \
GTEST_FATAL_FAILURE_) GTEST_FATAL_FAILURE_)
#define ASSERT_FALSE(condition) \ #define ASSERT_FALSE(condition) \
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
GTEST_FATAL_FAILURE_) GTEST_FATAL_FAILURE_)
// Includes the auto-generated header that implements a family of
// generic predicate assertion macros.
#include "gtest/gtest_pred_impl.h"
// Macros for testing equalities and inequalities. // Macros for testing equalities and inequalities.
// //
// * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2 // * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2
@ -1935,8 +1914,8 @@ class TestWithParam : public Test, public WithParamInterface<T> {
// //
// Examples: // Examples:
// //
// EXPECT_NE(Foo(), 5); // EXPECT_NE(5, Foo());
// EXPECT_EQ(a_pointer, NULL); // EXPECT_EQ(NULL, a_pointer);
// ASSERT_LT(i, array_size); // ASSERT_LT(i, array_size);
// ASSERT_GT(records.size(), 0) << "There is no record left."; // ASSERT_GT(records.size(), 0) << "There is no record left.";
@ -2122,57 +2101,6 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
#define EXPECT_NO_FATAL_FAILURE(statement) \ #define EXPECT_NO_FATAL_FAILURE(statement) \
GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
// Causes a trace (including the given source file path and line number,
// and the given message) to be included in every test failure message generated
// by code in the scope of the lifetime of an instance of this class. The effect
// is undone with the destruction of the instance.
//
// The message argument can be anything streamable to std::ostream.
//
// Example:
// testing::ScopedTrace trace("file.cc", 123, "message");
//
class GTEST_API_ ScopedTrace {
public:
// The c'tor pushes the given source file location and message onto
// a trace stack maintained by Google Test.
// Template version. Uses Message() to convert the values into strings.
// Slow, but flexible.
template <typename T>
ScopedTrace(const char* file, int line, const T& message) {
PushTrace(file, line, (Message() << message).GetString());
}
// Optimize for some known types.
ScopedTrace(const char* file, int line, const char* message) {
PushTrace(file, line, message ? message : "(null)");
}
#if GTEST_HAS_GLOBAL_STRING
ScopedTrace(const char* file, int line, const ::string& message) {
PushTrace(file, line, message);
}
#endif
ScopedTrace(const char* file, int line, const std::string& message) {
PushTrace(file, line, message);
}
// The d'tor pops the info pushed by the c'tor.
//
// Note that the d'tor is not virtual in order to be efficient.
// Don't inherit from ScopedTrace!
~ScopedTrace();
private:
void PushTrace(const char* file, int line, std::string message);
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
// c'tor and d'tor. Therefore it doesn't
// need to be used otherwise.
// Causes a trace (including the source file path, the current line // Causes a trace (including the source file path, the current line
// number, and the given message) to be included in every test failure // number, and the given message) to be included in every test failure
// message generated by code in the current scope. The effect is // message generated by code in the current scope. The effect is
@ -2184,14 +2112,9 @@ class GTEST_API_ ScopedTrace {
// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s // of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
// to appear in the same block - as long as they are on different // to appear in the same block - as long as they are on different
// lines. // lines.
//
// Assuming that each thread maintains its own stack of traces.
// Therefore, a SCOPED_TRACE() would (correctly) only affect the
// assertions in its own thread.
#define SCOPED_TRACE(message) \ #define SCOPED_TRACE(message) \
::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
__FILE__, __LINE__, (message)) __FILE__, __LINE__, ::testing::Message() << (message))
// Compile-time assertion for type equality. // Compile-time assertion for type equality.
// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are // StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
@ -2271,7 +2194,7 @@ bool StaticAssertTypeEq() {
// name of the test within the test case. // name of the test within the test case.
// //
// A test fixture class must be declared earlier. The user should put // A test fixture class must be declared earlier. The user should put
// the test code between braces after using this macro. Example: // his test code between braces after using this macro. Example:
// //
// class FooTest : public testing::Test { // class FooTest : public testing::Test {
// protected: // protected:
@ -2286,18 +2209,14 @@ bool StaticAssertTypeEq() {
// } // }
// //
// TEST_F(FooTest, ReturnsElementCountCorrectly) { // TEST_F(FooTest, ReturnsElementCountCorrectly) {
// EXPECT_EQ(a_.size(), 0); // EXPECT_EQ(0, a_.size());
// EXPECT_EQ(b_.size(), 1); // EXPECT_EQ(1, b_.size());
// } // }
#define TEST_F(test_fixture, test_name)\ #define TEST_F(test_fixture, test_name)\
GTEST_TEST_(test_fixture, test_name, test_fixture, \ GTEST_TEST_(test_fixture, test_name, test_fixture, \
::testing::internal::GetTypeId<test_fixture>()) ::testing::internal::GetTypeId<test_fixture>())
// Returns a path to temporary directory.
// Tries to determine an appropriate directory for the platform.
GTEST_API_ std::string TempDir();
} // namespace testing } // namespace testing
// Use this function in main() to run all tests. It returns 0 if all // Use this function in main() to run all tests. It returns 0 if all

View File

@ -27,7 +27,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file is AUTOMATICALLY GENERATED on 01/02/2018 by command // This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! // 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
// //
// Implements a family of generic predicate assertion macros. // Implements a family of generic predicate assertion macros.
@ -35,9 +35,10 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
#include "gtest/gtest.h" // Makes sure this header is not included before gtest.h.
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
namespace testing { # error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
// This header implements a family of generic predicate assertion // This header implements a family of generic predicate assertion
// macros: // macros:
@ -65,6 +66,8 @@ namespace testing {
// We also define the EXPECT_* variations. // We also define the EXPECT_* variations.
// //
// For now we only support predicates whose arity is at most 5. // For now we only support predicates whose arity is at most 5.
// Please email googletestframework@googlegroups.com if you need
// support for higher arities.
// GTEST_ASSERT_ is the basic statement to which all of the assertions // GTEST_ASSERT_ is the basic statement to which all of the assertions
// in this file reduce. Don't use this in your code. // in this file reduce. Don't use this in your code.
@ -352,6 +355,4 @@ AssertionResult AssertPred5Helper(const char* pred_text,
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_

View File

@ -40,20 +40,17 @@
// //
// class MyClass { // class MyClass {
// private: // private:
// void PrivateMethod(); // void MyMethod();
// FRIEND_TEST(MyClassTest, PrivateMethodWorks); // FRIEND_TEST(MyClassTest, MyMethod);
// }; // };
// //
// class MyClassTest : public testing::Test { // class MyClassTest : public testing::Test {
// // ... // // ...
// }; // };
// //
// TEST_F(MyClassTest, PrivateMethodWorks) { // TEST_F(MyClassTest, MyMethod) {
// // Can call MyClass::PrivateMethod() here. // // Can call MyClass::MyMethod() here.
// } // }
//
// Note: The test class must be in the same namespace as the class being tested.
// For example, putting MyClassTest in an anonymous namespace will not work.
#define FRIEND_TEST(test_case_name, test_name)\ #define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test friend class test_case_name##_##test_name##_Test

View File

@ -61,12 +61,6 @@
// GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) // GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
// GTEST_LOCK_EXCLUDED_(locks) // GTEST_LOCK_EXCLUDED_(locks)
// //
// Underlying library support features:
// GTEST_HAS_CXXABI_H_
//
// Exporting API symbols:
// GTEST_API_ - Specifier for exported symbols.
//
// ** Custom implementation starts here ** // ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_

View File

@ -33,10 +33,6 @@
// GTEST_OS_STACK_TRACE_GETTER_ - The name of an implementation of // GTEST_OS_STACK_TRACE_GETTER_ - The name of an implementation of
// OsStackTraceGetterInterface. // OsStackTraceGetterInterface.
// //
// GTEST_CUSTOM_TEMPDIR_FUNCTION_ - An override for testing::TempDir().
// See testing::TempDir for semantics and
// signature.
//
// ** Custom implementation starts here ** // ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_

View File

@ -27,6 +27,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
// //
// The Google C++ Testing Framework (Google Test) // The Google C++ Testing Framework (Google Test)
// //
@ -217,18 +218,14 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// can be streamed. // can be streamed.
// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in // This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
// NDEBUG mode. In this case we need the statements to be executed and the macro // NDEBUG mode. In this case we need the statements to be executed, the regex is
// must accept a streamed message even though the message is never printed. // ignored, and the macro must accept a streamed message even though the message
// The regex object is not evaluated, but it is used to prevent "unused" // is never printed.
// warnings and to avoid an expression that doesn't compile in debug mode. # define GTEST_EXECUTE_STATEMENT_(statement, regex) \
#define GTEST_EXECUTE_STATEMENT_(statement, regex) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::AlwaysTrue()) { \
if (::testing::internal::AlwaysTrue()) { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } else \
} else if (!::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
static_cast<void>(gtest_regex); \
} else \
::testing::Message() ::testing::Message()
// A class representing the parsed contents of the // A class representing the parsed contents of the
@ -267,6 +264,53 @@ class InternalRunDeathTestFlag {
// the flag is specified; otherwise returns NULL. // the flag is specified; otherwise returns NULL.
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
#else // GTEST_HAS_DEATH_TEST
// This macro is used for implementing macros such as
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
// death tests are not supported. Those macros must compile on such systems
// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
// systems that support death tests. This allows one to write such a macro
// on a system that does not support death tests and be sure that it will
// compile on a death-test supporting system.
//
// Parameters:
// statement - A statement that a macro such as EXPECT_DEATH would test
// for program termination. This macro has to make sure this
// statement is compiled but not executed, to ensure that
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
// parameter iff EXPECT_DEATH compiles with it.
// regex - A regex that a macro such as EXPECT_DEATH would use to test
// the output of statement. This parameter has to be
// compiled but not evaluated by this macro, to ensure that
// this macro only accepts expressions that a macro such as
// EXPECT_DEATH would accept.
// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
// compile inside functions where ASSERT_DEATH doesn't
// compile.
//
// The branch that has an always false condition is used to ensure that
// statement and regex are compiled (and thus syntactically correct) but
// never executed. The unreachable code macro protects the terminator
// statement from generating an 'unreachable code' warning in case
// statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) \
<< "Death tests are not supported on this platform.\n" \
<< "Statement '" #statement "' cannot be verified."; \
} else if (::testing::internal::AlwaysFalse()) { \
::testing::internal::RE::PartialMatch(".*", (regex)); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
terminator; \
} else \
::testing::Message()
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
} // namespace internal } // namespace internal

View File

@ -27,13 +27,14 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Author: keith.ray@gmail.com (Keith Ray)
// //
// Google Test filepath utilities // Google Test filepath utilities
// //
// This header file declares classes and functions used internally by // This header file declares classes and functions used internally by
// Google Test. They are subject to change without notice. // Google Test. They are subject to change without notice.
// //
// This file is #included in gtest/internal/gtest-internal.h. // This file is #included in <gtest/internal/gtest-internal.h>.
// Do not include this header file separately! // Do not include this header file separately!
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_

View File

@ -27,6 +27,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
// //
// The Google C++ Testing Framework (Google Test) // The Google C++ Testing Framework (Google Test)
// //
@ -60,8 +61,8 @@
#include <vector> #include <vector>
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h"
#include "gtest/internal/gtest-filepath.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
#include "gtest/internal/gtest-filepath.h"
#include "gtest/internal/gtest-type-util.h" #include "gtest/internal/gtest-type-util.h"
// Due to C++ preprocessor weirdness, we need double indirection to // Due to C++ preprocessor weirdness, we need double indirection to
@ -75,9 +76,6 @@
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) #define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
// Stringifies its argument.
#define GTEST_STRINGIFY_(name) #name
class ProtocolMessage; class ProtocolMessage;
namespace proto2 { class Message; } namespace proto2 { class Message; }
@ -98,6 +96,7 @@ template <typename T>
namespace internal { namespace internal {
struct TraceInfo; // Information about a trace point. struct TraceInfo; // Information about a trace point.
class ScopedTrace; // Implements scoped trace.
class TestInfoImpl; // Opaque implementation of TestInfo class TestInfoImpl; // Opaque implementation of TestInfo
class UnitTestImpl; // Opaque implementation of UnitTest class UnitTestImpl; // Opaque implementation of UnitTest
@ -153,6 +152,25 @@ class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
#endif // GTEST_HAS_EXCEPTIONS #endif // GTEST_HAS_EXCEPTIONS
// A helper class for creating scoped traces in user programs.
class GTEST_API_ ScopedTrace {
public:
// The c'tor pushes the given source file location and message onto
// a trace stack maintained by Google Test.
ScopedTrace(const char* file, int line, const Message& message);
// The d'tor pops the info pushed by the c'tor.
//
// Note that the d'tor is not virtual in order to be efficient.
// Don't inherit from ScopedTrace!
~ScopedTrace();
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
// c'tor and d'tor. Therefore it doesn't
// need to be used otherwise.
namespace edit_distance { namespace edit_distance {
// Returns the optimal edits to go from 'left' to 'right'. // Returns the optimal edits to go from 'left' to 'right'.
// All edits cost the same, with replace having lower priority than // All edits cost the same, with replace having lower priority than
@ -484,10 +502,9 @@ typedef void (*SetUpTestCaseFunc)();
typedef void (*TearDownTestCaseFunc)(); typedef void (*TearDownTestCaseFunc)();
struct CodeLocation { struct CodeLocation {
CodeLocation(const std::string& a_file, int a_line) CodeLocation(const string& a_file, int a_line) : file(a_file), line(a_line) {}
: file(a_file), line(a_line) {}
std::string file; string file;
int line; int line;
}; };
@ -610,7 +627,7 @@ class TypeParameterizedTest {
// Types). Valid values for 'index' are [0, N - 1] where N is the // Types). Valid values for 'index' are [0, N - 1] where N is the
// length of Types. // length of Types.
static bool Register(const char* prefix, static bool Register(const char* prefix,
const CodeLocation& code_location, CodeLocation code_location,
const char* case_name, const char* test_names, const char* case_name, const char* test_names,
int index) { int index) {
typedef typename Types::Head Type; typedef typename Types::Head Type;
@ -641,7 +658,7 @@ class TypeParameterizedTest {
template <GTEST_TEMPLATE_ Fixture, class TestSel> template <GTEST_TEMPLATE_ Fixture, class TestSel>
class TypeParameterizedTest<Fixture, TestSel, Types0> { class TypeParameterizedTest<Fixture, TestSel, Types0> {
public: public:
static bool Register(const char* /*prefix*/, const CodeLocation&, static bool Register(const char* /*prefix*/, CodeLocation,
const char* /*case_name*/, const char* /*test_names*/, const char* /*case_name*/, const char* /*test_names*/,
int /*index*/) { int /*index*/) {
return true; return true;
@ -687,7 +704,7 @@ class TypeParameterizedTestCase {
template <GTEST_TEMPLATE_ Fixture, typename Types> template <GTEST_TEMPLATE_ Fixture, typename Types>
class TypeParameterizedTestCase<Fixture, Templates0, Types> { class TypeParameterizedTestCase<Fixture, Templates0, Types> {
public: public:
static bool Register(const char* /*prefix*/, const CodeLocation&, static bool Register(const char* /*prefix*/, CodeLocation,
const TypedTestCasePState* /*state*/, const TypedTestCasePState* /*state*/,
const char* /*case_name*/, const char* /*test_names*/) { const char* /*case_name*/, const char* /*test_names*/) {
return true; return true;
@ -806,6 +823,31 @@ struct RemoveConst<T[N]> {
#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
// Adds reference to a type if it is not a reference type,
// otherwise leaves it unchanged. This is the same as
// tr1::add_reference, which is not widely available yet.
template <typename T>
struct AddReference { typedef T& type; }; // NOLINT
template <typename T>
struct AddReference<T&> { typedef T& type; }; // NOLINT
// A handy wrapper around AddReference that works when the argument T
// depends on template parameters.
#define GTEST_ADD_REFERENCE_(T) \
typename ::testing::internal::AddReference<T>::type
// Adds a reference to const on top of T as necessary. For example,
// it transforms
//
// char ==> const char&
// const char ==> const char&
// char& ==> const char&
// const char& ==> const char&
//
// The argument T must depend on some template parameters.
#define GTEST_REFERENCE_TO_CONST_(T) \
GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
// ImplicitlyConvertible<From, To>::value is a compile-time bool // ImplicitlyConvertible<From, To>::value is a compile-time bool
// constant that's true iff type From can be implicitly converted to // constant that's true iff type From can be implicitly converted to
// type To. // type To.
@ -875,11 +917,8 @@ struct IsAProtocolMessage
// a container class by checking the type of IsContainerTest<C>(0). // a container class by checking the type of IsContainerTest<C>(0).
// The value of the expression is insignificant. // The value of the expression is insignificant.
// //
// In C++11 mode we check the existence of a const_iterator and that an // Note that we look for both C::iterator and C::const_iterator. The
// iterator is properly implemented for the container. // reason is that C++ injects the name of a class as a member of the
//
// For pre-C++11 that we look for both C::iterator and C::const_iterator.
// The reason is that C++ injects the name of a class as a member of the
// class itself (e.g. you can refer to class iterator as either // class itself (e.g. you can refer to class iterator as either
// 'iterator' or 'iterator::iterator'). If we look for C::iterator // 'iterator' or 'iterator::iterator'). If we look for C::iterator
// only, for example, we would mistakenly think that a class named // only, for example, we would mistakenly think that a class named
@ -889,96 +928,17 @@ struct IsAProtocolMessage
// IsContainerTest(typename C::const_iterator*) and // IsContainerTest(typename C::const_iterator*) and
// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. // IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
typedef int IsContainer; typedef int IsContainer;
#if GTEST_LANG_CXX11
template <class C,
class Iterator = decltype(::std::declval<const C&>().begin()),
class = decltype(::std::declval<const C&>().end()),
class = decltype(++::std::declval<Iterator&>()),
class = decltype(*::std::declval<Iterator>()),
class = typename C::const_iterator>
IsContainer IsContainerTest(int /* dummy */) {
return 0;
}
#else
template <class C> template <class C>
IsContainer IsContainerTest(int /* dummy */, IsContainer IsContainerTest(int /* dummy */,
typename C::iterator* /* it */ = NULL, typename C::iterator* /* it */ = NULL,
typename C::const_iterator* /* const_it */ = NULL) { typename C::const_iterator* /* const_it */ = NULL) {
return 0; return 0;
} }
#endif // GTEST_LANG_CXX11
typedef char IsNotContainer; typedef char IsNotContainer;
template <class C> template <class C>
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
// Trait to detect whether a type T is a hash table.
// The heuristic used is that the type contains an inner type `hasher` and does
// not contain an inner type `reverse_iterator`.
// If the container is iterable in reverse, then order might actually matter.
template <typename T>
struct IsHashTable {
private:
template <typename U>
static char test(typename U::hasher*, typename U::reverse_iterator*);
template <typename U>
static int test(typename U::hasher*, ...);
template <typename U>
static char test(...);
public:
static const bool value = sizeof(test<T>(0, 0)) == sizeof(int);
};
template <typename T>
const bool IsHashTable<T>::value;
template<typename T>
struct VoidT {
typedef void value_type;
};
template <typename T, typename = void>
struct HasValueType : false_type {};
template <typename T>
struct HasValueType<T, VoidT<typename T::value_type> > : true_type {
};
template <typename C,
bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer),
bool = HasValueType<C>::value>
struct IsRecursiveContainerImpl;
template <typename C, bool HV>
struct IsRecursiveContainerImpl<C, false, HV> : public false_type {};
// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
// obey the same inconsistencies as the IsContainerTest, namely check if
// something is a container is relying on only const_iterator in C++11 and
// is relying on both const_iterator and iterator otherwise
template <typename C>
struct IsRecursiveContainerImpl<C, true, false> : public false_type {};
template <typename C>
struct IsRecursiveContainerImpl<C, true, true> {
#if GTEST_LANG_CXX11
typedef typename IteratorTraits<typename C::const_iterator>::value_type
value_type;
#else
typedef typename IteratorTraits<typename C::iterator>::value_type value_type;
#endif
typedef is_same<value_type, C> type;
};
// IsRecursiveContainer<Type> is a unary compile-time predicate that
// evaluates whether C is a recursive container type. A recursive container
// type is a container type whose value_type is equal to the container type
// itself. An example for a recursive container type is
// boost::filesystem::path, whose iterator has a value_type that is equal to
// boost::filesystem::path.
template <typename C>
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
// EnableIf<condition>::type is void when 'Cond' is true, and // EnableIf<condition>::type is void when 'Cond' is true, and
// undefined when 'Cond' is false. To use SFINAE to make a function // undefined when 'Cond' is false. To use SFINAE to make a function
// overload only apply when a particular expression is true, add // overload only apply when a particular expression is true, add
@ -1110,7 +1070,7 @@ class NativeArray {
private: private:
enum { enum {
kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper< kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper<
Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value,
}; };
// Initializes this object with a copy of the input. // Initializes this object with a copy of the input.
@ -1275,3 +1235,4 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_

View File

@ -46,9 +46,14 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-param-util.h" #include "gtest/internal/gtest-param-util.h"
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#if GTEST_HAS_PARAM_TEST
namespace testing { namespace testing {
// Forward declarations of ValuesIn(), which is implemented in // Forward declarations of ValuesIn(), which is implemented in
@ -3203,7 +3208,7 @@ class CartesianProductGenerator2
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -3235,7 +3240,7 @@ class CartesianProductGenerator2
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_)); current_value_ = ParamType(*current1_, *current2_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -3257,7 +3262,7 @@ class CartesianProductGenerator2
const typename ParamGenerator<T2>::iterator begin2_; const typename ParamGenerator<T2>::iterator begin2_;
const typename ParamGenerator<T2>::iterator end2_; const typename ParamGenerator<T2>::iterator end2_;
typename ParamGenerator<T2>::iterator current2_; typename ParamGenerator<T2>::iterator current2_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator2::Iterator }; // class CartesianProductGenerator2::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -3326,7 +3331,7 @@ class CartesianProductGenerator3
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -3362,7 +3367,7 @@ class CartesianProductGenerator3
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_)); current_value_ = ParamType(*current1_, *current2_, *current3_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -3388,7 +3393,7 @@ class CartesianProductGenerator3
const typename ParamGenerator<T3>::iterator begin3_; const typename ParamGenerator<T3>::iterator begin3_;
const typename ParamGenerator<T3>::iterator end3_; const typename ParamGenerator<T3>::iterator end3_;
typename ParamGenerator<T3>::iterator current3_; typename ParamGenerator<T3>::iterator current3_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator3::Iterator }; // class CartesianProductGenerator3::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -3467,7 +3472,7 @@ class CartesianProductGenerator4
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -3507,8 +3512,8 @@ class CartesianProductGenerator4
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_, current_value_ = ParamType(*current1_, *current2_, *current3_,
*current4_)); *current4_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -3538,7 +3543,7 @@ class CartesianProductGenerator4
const typename ParamGenerator<T4>::iterator begin4_; const typename ParamGenerator<T4>::iterator begin4_;
const typename ParamGenerator<T4>::iterator end4_; const typename ParamGenerator<T4>::iterator end4_;
typename ParamGenerator<T4>::iterator current4_; typename ParamGenerator<T4>::iterator current4_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator4::Iterator }; // class CartesianProductGenerator4::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -3625,7 +3630,7 @@ class CartesianProductGenerator5
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -3669,8 +3674,8 @@ class CartesianProductGenerator5
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_, current_value_ = ParamType(*current1_, *current2_, *current3_,
*current4_, *current5_)); *current4_, *current5_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -3704,7 +3709,7 @@ class CartesianProductGenerator5
const typename ParamGenerator<T5>::iterator begin5_; const typename ParamGenerator<T5>::iterator begin5_;
const typename ParamGenerator<T5>::iterator end5_; const typename ParamGenerator<T5>::iterator end5_;
typename ParamGenerator<T5>::iterator current5_; typename ParamGenerator<T5>::iterator current5_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator5::Iterator }; // class CartesianProductGenerator5::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -3802,7 +3807,7 @@ class CartesianProductGenerator6
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -3850,8 +3855,8 @@ class CartesianProductGenerator6
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_, current_value_ = ParamType(*current1_, *current2_, *current3_,
*current4_, *current5_, *current6_)); *current4_, *current5_, *current6_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -3889,7 +3894,7 @@ class CartesianProductGenerator6
const typename ParamGenerator<T6>::iterator begin6_; const typename ParamGenerator<T6>::iterator begin6_;
const typename ParamGenerator<T6>::iterator end6_; const typename ParamGenerator<T6>::iterator end6_;
typename ParamGenerator<T6>::iterator current6_; typename ParamGenerator<T6>::iterator current6_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator6::Iterator }; // class CartesianProductGenerator6::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -3996,7 +4001,7 @@ class CartesianProductGenerator7
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -4048,8 +4053,8 @@ class CartesianProductGenerator7
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_, current_value_ = ParamType(*current1_, *current2_, *current3_,
*current4_, *current5_, *current6_, *current7_)); *current4_, *current5_, *current6_, *current7_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -4091,7 +4096,7 @@ class CartesianProductGenerator7
const typename ParamGenerator<T7>::iterator begin7_; const typename ParamGenerator<T7>::iterator begin7_;
const typename ParamGenerator<T7>::iterator end7_; const typename ParamGenerator<T7>::iterator end7_;
typename ParamGenerator<T7>::iterator current7_; typename ParamGenerator<T7>::iterator current7_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator7::Iterator }; // class CartesianProductGenerator7::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -4209,7 +4214,7 @@ class CartesianProductGenerator8
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -4265,8 +4270,8 @@ class CartesianProductGenerator8
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_, current_value_ = ParamType(*current1_, *current2_, *current3_,
*current4_, *current5_, *current6_, *current7_, *current8_)); *current4_, *current5_, *current6_, *current7_, *current8_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -4312,7 +4317,7 @@ class CartesianProductGenerator8
const typename ParamGenerator<T8>::iterator begin8_; const typename ParamGenerator<T8>::iterator begin8_;
const typename ParamGenerator<T8>::iterator end8_; const typename ParamGenerator<T8>::iterator end8_;
typename ParamGenerator<T8>::iterator current8_; typename ParamGenerator<T8>::iterator current8_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator8::Iterator }; // class CartesianProductGenerator8::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -4438,7 +4443,7 @@ class CartesianProductGenerator9
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -4498,9 +4503,9 @@ class CartesianProductGenerator9
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_, current_value_ = ParamType(*current1_, *current2_, *current3_,
*current4_, *current5_, *current6_, *current7_, *current8_, *current4_, *current5_, *current6_, *current7_, *current8_,
*current9_)); *current9_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -4550,7 +4555,7 @@ class CartesianProductGenerator9
const typename ParamGenerator<T9>::iterator begin9_; const typename ParamGenerator<T9>::iterator begin9_;
const typename ParamGenerator<T9>::iterator end9_; const typename ParamGenerator<T9>::iterator end9_;
typename ParamGenerator<T9>::iterator current9_; typename ParamGenerator<T9>::iterator current9_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator9::Iterator }; // class CartesianProductGenerator9::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -4685,7 +4690,7 @@ class CartesianProductGenerator10
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -4749,9 +4754,9 @@ class CartesianProductGenerator10
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType(*current1_, *current2_, *current3_, current_value_ = ParamType(*current1_, *current2_, *current3_,
*current4_, *current5_, *current6_, *current7_, *current8_, *current4_, *current5_, *current6_, *current7_, *current8_,
*current9_, *current10_)); *current9_, *current10_);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -4805,7 +4810,7 @@ class CartesianProductGenerator10
const typename ParamGenerator<T10>::iterator begin10_; const typename ParamGenerator<T10>::iterator begin10_;
const typename ParamGenerator<T10>::iterator end10_; const typename ParamGenerator<T10>::iterator end10_;
typename ParamGenerator<T10>::iterator current10_; typename ParamGenerator<T10>::iterator current10_;
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator10::Iterator }; // class CartesianProductGenerator10::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -5136,4 +5141,6 @@ CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_

View File

@ -45,9 +45,14 @@ $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-param-util.h" #include "gtest/internal/gtest-param-util.h"
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#if GTEST_HAS_PARAM_TEST
namespace testing { namespace testing {
// Forward declarations of ValuesIn(), which is implemented in // Forward declarations of ValuesIn(), which is implemented in
@ -160,7 +165,7 @@ $for k [[
virtual ParamIteratorInterface<ParamType>* Clone() const { virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this); return new Iterator(*this);
} }
virtual const ParamType* Current() const { return current_value_.get(); } virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const { virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other // Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast. // iterator is of the same type and we can downcast.
@ -192,7 +197,7 @@ $for k [[
void ComputeCurrentValue() { void ComputeCurrentValue() {
if (!AtEnd()) if (!AtEnd())
current_value_.reset(new ParamType($for j, [[*current$(j)_]])); current_value_ = ParamType($for j, [[*current$(j)_]]);
} }
bool AtEnd() const { bool AtEnd() const {
// We must report iterator past the end of the range when either of the // We must report iterator past the end of the range when either of the
@ -217,7 +222,7 @@ $for j [[
typename ParamGenerator<T$j>::iterator current$(j)_; typename ParamGenerator<T$j>::iterator current$(j)_;
]] ]]
linked_ptr<ParamType> current_value_; ParamType current_value_;
}; // class CartesianProductGenerator$i::Iterator }; // class CartesianProductGenerator$i::Iterator
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -276,4 +281,6 @@ $for j [[
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_

View File

@ -41,11 +41,16 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-linked_ptr.h" #include "gtest/internal/gtest-linked_ptr.h"
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "gtest/gtest-printers.h" #include "gtest/gtest-printers.h"
#if GTEST_HAS_PARAM_TEST
namespace testing { namespace testing {
// Input to a parameterized test name generator, describing a test parameter. // Input to a parameterized test name generator, describing a test parameter.
@ -467,7 +472,7 @@ class ParameterizedTestCaseInfoBase {
virtual ~ParameterizedTestCaseInfoBase() {} virtual ~ParameterizedTestCaseInfoBase() {}
// Base part of test case name for display purposes. // Base part of test case name for display purposes.
virtual const std::string& GetTestCaseName() const = 0; virtual const string& GetTestCaseName() const = 0;
// Test case id to verify identity. // Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const = 0; virtual TypeId GetTestCaseTypeId() const = 0;
// UnitTest class invokes this method to register tests in this // UnitTest class invokes this method to register tests in this
@ -506,7 +511,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
: test_case_name_(name), code_location_(code_location) {} : test_case_name_(name), code_location_(code_location) {}
// Test case base name for display purposes. // Test case base name for display purposes.
virtual const std::string& GetTestCaseName() const { return test_case_name_; } virtual const string& GetTestCaseName() const { return test_case_name_; }
// Test case id to verify identity. // Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); } virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
// TEST_P macro uses AddTestPattern() to record information // TEST_P macro uses AddTestPattern() to record information
@ -524,10 +529,11 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
} }
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
// about a generator. // about a generator.
int AddTestCaseInstantiation(const std::string& instantiation_name, int AddTestCaseInstantiation(const string& instantiation_name,
GeneratorCreationFunc* func, GeneratorCreationFunc* func,
ParamNameGeneratorFunc* name_func, ParamNameGeneratorFunc* name_func,
const char* file, int line) { const char* file,
int line) {
instantiations_.push_back( instantiations_.push_back(
InstantiationInfo(instantiation_name, func, name_func, file, line)); InstantiationInfo(instantiation_name, func, name_func, file, line));
return 0; // Return value used only to run this method in namespace scope. return 0; // Return value used only to run this method in namespace scope.
@ -544,13 +550,13 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
for (typename InstantiationContainer::iterator gen_it = for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it != instantiations_.end(); instantiations_.begin(); gen_it != instantiations_.end();
++gen_it) { ++gen_it) {
const std::string& instantiation_name = gen_it->name; const string& instantiation_name = gen_it->name;
ParamGenerator<ParamType> generator((*gen_it->generator)()); ParamGenerator<ParamType> generator((*gen_it->generator)());
ParamNameGeneratorFunc* name_func = gen_it->name_func; ParamNameGeneratorFunc* name_func = gen_it->name_func;
const char* file = gen_it->file; const char* file = gen_it->file;
int line = gen_it->line; int line = gen_it->line;
std::string test_case_name; string test_case_name;
if ( !instantiation_name.empty() ) if ( !instantiation_name.empty() )
test_case_name = instantiation_name + "/"; test_case_name = instantiation_name + "/";
test_case_name += test_info->test_case_base_name; test_case_name += test_info->test_case_base_name;
@ -603,8 +609,8 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
test_base_name(a_test_base_name), test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {} test_meta_factory(a_test_meta_factory) {}
const std::string test_case_base_name; const string test_case_base_name;
const std::string test_base_name; const string test_base_name;
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory; const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
}; };
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer; typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
@ -645,7 +651,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
return true; return true;
} }
const std::string test_case_name_; const string test_case_name_;
CodeLocation code_location_; CodeLocation code_location_;
TestInfoContainer tests_; TestInfoContainer tests_;
InstantiationContainer instantiations_; InstantiationContainer instantiations_;
@ -720,4 +726,6 @@ class ParameterizedTestCaseRegistry {
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_

View File

@ -54,9 +54,6 @@
# define GTEST_OS_WINDOWS_PHONE 1 # define GTEST_OS_WINDOWS_PHONE 1
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
# define GTEST_OS_WINDOWS_RT 1 # define GTEST_OS_WINDOWS_RT 1
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
# define GTEST_OS_WINDOWS_PHONE 1
# define GTEST_OS_WINDOWS_TV_TITLE 1
# else # else
// WINAPI_FAMILY defined but no known partition matched. // WINAPI_FAMILY defined but no known partition matched.
// Default to desktop. // Default to desktop.
@ -72,8 +69,6 @@
# endif # endif
#elif defined __FreeBSD__ #elif defined __FreeBSD__
# define GTEST_OS_FREEBSD 1 # define GTEST_OS_FREEBSD 1
#elif defined __Fuchsia__
# define GTEST_OS_FUCHSIA 1
#elif defined __linux__ #elif defined __linux__
# define GTEST_OS_LINUX 1 # define GTEST_OS_LINUX 1
# if defined __ANDROID__ # if defined __ANDROID__
@ -89,8 +84,6 @@
# define GTEST_OS_HPUX 1 # define GTEST_OS_HPUX 1
#elif defined __native_client__ #elif defined __native_client__
# define GTEST_OS_NACL 1 # define GTEST_OS_NACL 1
#elif defined __NetBSD__
# define GTEST_OS_NETBSD 1
#elif defined __OpenBSD__ #elif defined __OpenBSD__
# define GTEST_OS_OPENBSD 1 # define GTEST_OS_OPENBSD 1
#elif defined __QNX__ #elif defined __QNX__

View File

@ -73,9 +73,11 @@
// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions // GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions
// are enabled. // are enabled.
// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string // GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string
// is/isn't available // is/isn't available (some systems define
// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::wstring // ::string, which is different to std::string).
// is/isn't available // GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
// is/isn't available (some systems define
// ::wstring, which is different to std::wstring).
// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular // GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular
// expressions are/aren't available. // expressions are/aren't available.
// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h> // GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h>
@ -107,12 +109,6 @@
// GTEST_CREATE_SHARED_LIBRARY // GTEST_CREATE_SHARED_LIBRARY
// - Define to 1 when compiling Google Test itself // - Define to 1 when compiling Google Test itself
// as a shared library. // as a shared library.
// GTEST_DEFAULT_DEATH_TEST_STYLE
// - The default value of --gtest_death_test_style.
// The legacy default has been "fast" in the open
// source version since 2008. The recommended value
// is "threadsafe", and can be set in
// custom/gtest-port.h.
// Platform-indicating macros // Platform-indicating macros
// -------------------------- // --------------------------
@ -126,14 +122,12 @@
// GTEST_OS_AIX - IBM AIX // GTEST_OS_AIX - IBM AIX
// GTEST_OS_CYGWIN - Cygwin // GTEST_OS_CYGWIN - Cygwin
// GTEST_OS_FREEBSD - FreeBSD // GTEST_OS_FREEBSD - FreeBSD
// GTEST_OS_FUCHSIA - Fuchsia
// GTEST_OS_HPUX - HP-UX // GTEST_OS_HPUX - HP-UX
// GTEST_OS_LINUX - Linux // GTEST_OS_LINUX - Linux
// GTEST_OS_LINUX_ANDROID - Google Android // GTEST_OS_LINUX_ANDROID - Google Android
// GTEST_OS_MAC - Mac OS X // GTEST_OS_MAC - Mac OS X
// GTEST_OS_IOS - iOS // GTEST_OS_IOS - iOS
// GTEST_OS_NACL - Google Native Client (NaCl) // GTEST_OS_NACL - Google Native Client (NaCl)
// GTEST_OS_NETBSD - NetBSD
// GTEST_OS_OPENBSD - OpenBSD // GTEST_OS_OPENBSD - OpenBSD
// GTEST_OS_QNX - QNX // GTEST_OS_QNX - QNX
// GTEST_OS_SOLARIS - Sun Solaris // GTEST_OS_SOLARIS - Sun Solaris
@ -175,6 +169,7 @@
// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized // GTEST_HAS_COMBINE - the Combine() function (for value-parameterized
// tests) // tests)
// GTEST_HAS_DEATH_TEST - death tests // GTEST_HAS_DEATH_TEST - death tests
// GTEST_HAS_PARAM_TEST - value-parameterized tests
// GTEST_HAS_TYPED_TEST - typed tests // GTEST_HAS_TYPED_TEST - typed tests
// GTEST_HAS_TYPED_TEST_P - type-parameterized tests // GTEST_HAS_TYPED_TEST_P - type-parameterized tests
// GTEST_IS_THREADSAFE - Google Test is thread-safe. // GTEST_IS_THREADSAFE - Google Test is thread-safe.
@ -182,7 +177,7 @@
// GTEST_HAS_POSIX_RE (see above) which users can // GTEST_HAS_POSIX_RE (see above) which users can
// define themselves. // define themselves.
// GTEST_USES_SIMPLE_RE - our own simple regex is used; // GTEST_USES_SIMPLE_RE - our own simple regex is used;
// the above RE\b(s) are mutually exclusive. // the above two are mutually exclusive.
// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). // GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
// Misc public macros // Misc public macros
@ -211,7 +206,6 @@
// //
// C++11 feature wrappers: // C++11 feature wrappers:
// //
// testing::internal::forward - portability wrapper for std::forward.
// testing::internal::move - portability wrapper for std::move. // testing::internal::move - portability wrapper for std::move.
// //
// Synchronization: // Synchronization:
@ -277,12 +271,10 @@
# include <TargetConditionals.h> # include <TargetConditionals.h>
#endif #endif
// Brings in the definition of HAS_GLOBAL_STRING. This must be done
// BEFORE we test HAS_GLOBAL_STRING.
#include <string> // NOLINT
#include <algorithm> // NOLINT #include <algorithm> // NOLINT
#include <iostream> // NOLINT #include <iostream> // NOLINT
#include <sstream> // NOLINT #include <sstream> // NOLINT
#include <string> // NOLINT
#include <utility> #include <utility>
#include <vector> // NOLINT #include <vector> // NOLINT
@ -331,7 +323,7 @@
// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a // -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a
// value for __cplusplus, and recent versions of clang, gcc, and // value for __cplusplus, and recent versions of clang, gcc, and
// probably other compilers set that too in C++11 mode. // probably other compilers set that too in C++11 mode.
# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L || _MSC_VER >= 1900 # if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L
// Compiling in at least C++11 mode. // Compiling in at least C++11 mode.
# define GTEST_LANG_CXX11 1 # define GTEST_LANG_CXX11 1
# else # else
@ -363,16 +355,12 @@
#if GTEST_STDLIB_CXX11 #if GTEST_STDLIB_CXX11
# define GTEST_HAS_STD_BEGIN_AND_END_ 1 # define GTEST_HAS_STD_BEGIN_AND_END_ 1
# define GTEST_HAS_STD_FORWARD_LIST_ 1 # define GTEST_HAS_STD_FORWARD_LIST_ 1
# if !defined(_MSC_VER) || (_MSC_FULL_VER >= 190023824) # define GTEST_HAS_STD_FUNCTION_ 1
// works only with VS2015U2 and better
# define GTEST_HAS_STD_FUNCTION_ 1
# endif
# define GTEST_HAS_STD_INITIALIZER_LIST_ 1 # define GTEST_HAS_STD_INITIALIZER_LIST_ 1
# define GTEST_HAS_STD_MOVE_ 1 # define GTEST_HAS_STD_MOVE_ 1
# define GTEST_HAS_STD_UNIQUE_PTR_ 1
# define GTEST_HAS_STD_SHARED_PTR_ 1 # define GTEST_HAS_STD_SHARED_PTR_ 1
# define GTEST_HAS_UNORDERED_MAP_ 1 # define GTEST_HAS_STD_TYPE_TRAITS_ 1
# define GTEST_HAS_UNORDERED_SET_ 1 # define GTEST_HAS_STD_UNIQUE_PTR_ 1
#endif #endif
// C++11 specifies that <tuple> provides std::tuple. // C++11 specifies that <tuple> provides std::tuple.
@ -408,16 +396,10 @@
# include <io.h> # include <io.h>
# endif # endif
// In order to avoid having to include <windows.h>, use forward declaration // In order to avoid having to include <windows.h>, use forward declaration
#if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR) // assuming CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION.
// MinGW defined _CRITICAL_SECTION and _RTL_CRITICAL_SECTION as two
// separate (equivalent) structs, instead of using typedef
typedef struct _CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#else
// Assume CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION.
// This assumption is verified by // This assumption is verified by
// WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION. // WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION.
typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; struct _RTL_CRITICAL_SECTION;
#endif
#else #else
// This assumes that non-Windows OSes provide unistd.h. For OSes where this // This assumes that non-Windows OSes provide unistd.h. For OSes where this
// is not the case, we need to include headers that provide the functions // is not the case, we need to include headers that provide the functions
@ -471,11 +453,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#ifndef GTEST_HAS_EXCEPTIONS #ifndef GTEST_HAS_EXCEPTIONS
// The user didn't tell us whether exceptions are enabled, so we need // The user didn't tell us whether exceptions are enabled, so we need
// to figure it out. // to figure it out.
# if defined(_MSC_VER) && defined(_CPPUNWIND) # if defined(_MSC_VER) || defined(__BORLANDC__)
// MSVC defines _CPPUNWIND to 1 iff exceptions are enabled. // MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
# define GTEST_HAS_EXCEPTIONS 1
# elif defined(__BORLANDC__)
// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS
// macro to enable exceptions, so we'll do the same. // macro to enable exceptions, so we'll do the same.
// Assumes that exceptions are enabled by default. // Assumes that exceptions are enabled by default.
# ifndef _HAS_EXCEPTIONS # ifndef _HAS_EXCEPTIONS
@ -519,7 +498,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
# define GTEST_HAS_STD_STRING 1 # define GTEST_HAS_STD_STRING 1
#elif !GTEST_HAS_STD_STRING #elif !GTEST_HAS_STD_STRING
// The user told us that ::std::string isn't available. // The user told us that ::std::string isn't available.
# error "::std::string isn't available." # error "Google Test cannot be used where ::std::string isn't available."
#endif // !defined(GTEST_HAS_STD_STRING) #endif // !defined(GTEST_HAS_STD_STRING)
#ifndef GTEST_HAS_GLOBAL_STRING #ifndef GTEST_HAS_GLOBAL_STRING
@ -621,9 +600,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
// //
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 // To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
// to your compiler flags. // to your compiler flags.
#define GTEST_HAS_PTHREAD \ # define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \
(GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX || GTEST_OS_QNX || \ || GTEST_OS_QNX || GTEST_OS_FREEBSD || GTEST_OS_NACL)
GTEST_OS_FREEBSD || GTEST_OS_NACL || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA)
#endif // GTEST_HAS_PTHREAD #endif // GTEST_HAS_PTHREAD
#if GTEST_HAS_PTHREAD #if GTEST_HAS_PTHREAD
@ -638,7 +616,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
// Determines if hash_map/hash_set are available. // Determines if hash_map/hash_set are available.
// Only used for testing against those containers. // Only used for testing against those containers.
#if !defined(GTEST_HAS_HASH_MAP_) #if !defined(GTEST_HAS_HASH_MAP_)
# if defined(_MSC_VER) && (_MSC_VER < 1900) # if _MSC_VER
# define GTEST_HAS_HASH_MAP_ 1 // Indicates that hash_map is available. # define GTEST_HAS_HASH_MAP_ 1 // Indicates that hash_map is available.
# define GTEST_HAS_HASH_SET_ 1 // Indicates that hash_set is available. # define GTEST_HAS_HASH_SET_ 1 // Indicates that hash_set is available.
# endif // _MSC_VER # endif // _MSC_VER
@ -651,9 +629,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) # if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR)
// STLport, provided with the Android NDK, has neither <tr1/tuple> or <tuple>. // STLport, provided with the Android NDK, has neither <tr1/tuple> or <tuple>.
# define GTEST_HAS_TR1_TUPLE 0 # define GTEST_HAS_TR1_TUPLE 0
# elif defined(_MSC_VER) && (_MSC_VER >= 1910)
// Prevent `warning C4996: 'std::tr1': warning STL4002: The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED.`
# define GTEST_HAS_TR1_TUPLE 0
# else # else
// The user didn't tell us not to do it, so we assume it's OK. // The user didn't tell us not to do it, so we assume it's OK.
# define GTEST_HAS_TR1_TUPLE 1 # define GTEST_HAS_TR1_TUPLE 1
@ -676,8 +651,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, // support TR1 tuple. libc++ only provides std::tuple, in C++11 mode,
// and it can be used with some compilers that define __GNUC__. // and it can be used with some compilers that define __GNUC__.
# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ # if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \
&& !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) \ && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600
|| (_MSC_VER >= 1600 && _MSC_VER < 1900)
# define GTEST_ENV_HAS_TR1_TUPLE_ 1 # define GTEST_ENV_HAS_TR1_TUPLE_ 1
# endif # endif
@ -758,7 +732,7 @@ using ::std::tuple_size;
# define _TR1_FUNCTIONAL 1 # define _TR1_FUNCTIONAL 1
# include <tr1/tuple> # include <tr1/tuple>
# undef _TR1_FUNCTIONAL // Allows the user to #include # undef _TR1_FUNCTIONAL // Allows the user to #include
// <tr1/functional> if they choose to. // <tr1/functional> if he chooses to.
# else # else
# include <tr1/tuple> // NOLINT # include <tr1/tuple> // NOLINT
# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 # endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
@ -780,12 +754,8 @@ using ::std::tuple_size;
# if GTEST_OS_LINUX && !defined(__ia64__) # if GTEST_OS_LINUX && !defined(__ia64__)
# if GTEST_OS_LINUX_ANDROID # if GTEST_OS_LINUX_ANDROID
// On Android, clone() became available at different API levels for each 32-bit // On Android, clone() is only available on ARM starting with Gingerbread.
// architecture. # if defined(__arm__) && __ANDROID_API__ >= 9
# if defined(__LP64__) || \
(defined(__arm__) && __ANDROID_API__ >= 9) || \
(defined(__mips__) && __ANDROID_API__ >= 12) || \
(defined(__i386__) && __ANDROID_API__ >= 17)
# define GTEST_HAS_CLONE 1 # define GTEST_HAS_CLONE 1
# else # else
# define GTEST_HAS_CLONE 0 # define GTEST_HAS_CLONE 0
@ -816,14 +786,19 @@ using ::std::tuple_size;
// Google Test does not support death tests for VC 7.1 and earlier as // Google Test does not support death tests for VC 7.1 and earlier as
// abort() in a VC 7.1 application compiled as GUI in debug config // abort() in a VC 7.1 application compiled as GUI in debug config
// pops up a dialog window that cannot be suppressed programmatically. // pops up a dialog window that cannot be suppressed programmatically.
#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ #if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
(GTEST_OS_MAC && !GTEST_OS_IOS) || \ (GTEST_OS_MAC && !GTEST_OS_IOS) || \
(GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
GTEST_OS_OPENBSD || GTEST_OS_QNX || GTEST_OS_FREEBSD || GTEST_OS_NETBSD) GTEST_OS_OPENBSD || GTEST_OS_QNX || GTEST_OS_FREEBSD)
# define GTEST_HAS_DEATH_TEST 1 # define GTEST_HAS_DEATH_TEST 1
#endif #endif
// We don't support MSVC 7.1 with exceptions disabled now. Therefore
// all the compilers we care about are adequate for supporting
// value-parameterized tests.
#define GTEST_HAS_PARAM_TEST 1
// Determines whether to support type-driven tests. // Determines whether to support type-driven tests.
// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0, // Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
@ -838,7 +813,7 @@ using ::std::tuple_size;
// value-parameterized tests are enabled. The implementation doesn't // value-parameterized tests are enabled. The implementation doesn't
// work on Sun Studio since it doesn't understand templated conversion // work on Sun Studio since it doesn't understand templated conversion
// operators. // operators.
#if (GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_) && !defined(__SUNPRO_CC) #if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
# define GTEST_HAS_COMBINE 1 # define GTEST_HAS_COMBINE 1
#endif #endif
@ -889,39 +864,15 @@ using ::std::tuple_size;
# define GTEST_ATTRIBUTE_UNUSED_ # define GTEST_ATTRIBUTE_UNUSED_
#endif #endif
#if GTEST_LANG_CXX11
# define GTEST_CXX11_EQUALS_DELETE_ = delete
#else // GTEST_LANG_CXX11
# define GTEST_CXX11_EQUALS_DELETE_
#endif // GTEST_LANG_CXX11
// Use this annotation before a function that takes a printf format string.
#if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC)
# if defined(__MINGW_PRINTF_FORMAT)
// MinGW has two different printf implementations. Ensure the format macro
// matches the selected implementation. See
// https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/.
# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
__attribute__((__format__(__MINGW_PRINTF_FORMAT, string_index, \
first_to_check)))
# else
# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
__attribute__((__format__(__printf__, string_index, first_to_check)))
# endif
#else
# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
#endif
// A macro to disallow operator= // A macro to disallow operator=
// This should be used in the private: declarations for a class. // This should be used in the private: declarations for a class.
#define GTEST_DISALLOW_ASSIGN_(type) \ #define GTEST_DISALLOW_ASSIGN_(type)\
void operator=(type const &) GTEST_CXX11_EQUALS_DELETE_ void operator=(type const &)
// A macro to disallow copy constructor and operator= // A macro to disallow copy constructor and operator=
// This should be used in the private: declarations for a class. // This should be used in the private: declarations for a class.
#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \ #define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
type(type const &) GTEST_CXX11_EQUALS_DELETE_; \ type(type const &);\
GTEST_DISALLOW_ASSIGN_(type) GTEST_DISALLOW_ASSIGN_(type)
// Tell the compiler to warn about unused return values for functions declared // Tell the compiler to warn about unused return values for functions declared
@ -969,11 +920,6 @@ using ::std::tuple_size;
#endif // GTEST_HAS_SEH #endif // GTEST_HAS_SEH
// GTEST_API_ qualifies all symbols that must be exported. The definitions below
// are guarded by #ifndef to give embedders a chance to define GTEST_API_ in
// gtest/internal/custom/gtest-port.h
#ifndef GTEST_API_
#ifdef _MSC_VER #ifdef _MSC_VER
# if GTEST_LINKED_AS_SHARED_LIBRARY # if GTEST_LINKED_AS_SHARED_LIBRARY
# define GTEST_API_ __declspec(dllimport) # define GTEST_API_ __declspec(dllimport)
@ -982,17 +928,11 @@ using ::std::tuple_size;
# endif # endif
#elif __GNUC__ >= 4 || defined(__clang__) #elif __GNUC__ >= 4 || defined(__clang__)
# define GTEST_API_ __attribute__((visibility ("default"))) # define GTEST_API_ __attribute__((visibility ("default")))
#endif // _MSC_VER #endif // _MSC_VER
#endif // GTEST_API_
#ifndef GTEST_API_ #ifndef GTEST_API_
# define GTEST_API_ # define GTEST_API_
#endif // GTEST_API_ #endif
#ifndef GTEST_DEFAULT_DEATH_TEST_STYLE
# define GTEST_DEFAULT_DEATH_TEST_STYLE "fast"
#endif // GTEST_DEFAULT_DEATH_TEST_STYLE
#ifdef __GNUC__ #ifdef __GNUC__
// Ask the compiler to never inline a given function. // Ask the compiler to never inline a given function.
@ -1002,12 +942,10 @@ using ::std::tuple_size;
#endif #endif
// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. // _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
#if !defined(GTEST_HAS_CXXABI_H_) #if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
# if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) # define GTEST_HAS_CXXABI_H_ 1
# define GTEST_HAS_CXXABI_H_ 1 #else
# else # define GTEST_HAS_CXXABI_H_ 0
# define GTEST_HAS_CXXABI_H_ 0
# endif
#endif #endif
// A function level attribute to disable checking for use of uninitialized // A function level attribute to disable checking for use of uninitialized
@ -1047,6 +985,19 @@ using ::std::tuple_size;
# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ # define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
#endif // __clang__ #endif // __clang__
// A function level attribute to disable UndefinedBehaviorSanitizer's (defined)
// unsigned integer overflow instrumentation.
#if defined(__clang__)
# if defined(__has_attribute) && __has_attribute(no_sanitize)
# define GTEST_ATTRIBUTE_NO_SANITIZE_UNSIGNED_OVERFLOW_ \
__attribute__((no_sanitize("unsigned-integer-overflow")))
# else
# define GTEST_ATTRIBUTE_NO_SANITIZE_UNSIGNED_OVERFLOW_
# endif // defined(__has_attribute) && __has_attribute(no_sanitize)
#else
# define GTEST_ATTRIBUTE_NO_SANITIZE_UNSIGNED_OVERFLOW_
#endif // __clang__
namespace testing { namespace testing {
class Message; class Message;
@ -1150,16 +1101,6 @@ struct StaticAssertTypeEqHelper<T, T> {
enum { value = true }; enum { value = true };
}; };
// Same as std::is_same<>.
template <typename T, typename U>
struct IsSame {
enum { value = false };
};
template <typename T>
struct IsSame<T, T> {
enum { value = true };
};
// Evaluates to the number of elements in 'array'. // Evaluates to the number of elements in 'array'.
#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0])) #define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0]))
@ -1223,10 +1164,6 @@ class scoped_ptr {
// Defines RE. // Defines RE.
#if GTEST_USES_PCRE
using ::RE;
#elif GTEST_USES_POSIX_RE || GTEST_USES_SIMPLE_RE
// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended // A simple C++ wrapper for <regex.h>. It uses the POSIX Extended
// Regular Expression syntax. // Regular Expression syntax.
class GTEST_API_ RE { class GTEST_API_ RE {
@ -1238,11 +1175,11 @@ class GTEST_API_ RE {
// Constructs an RE from a string. // Constructs an RE from a string.
RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT
# if GTEST_HAS_GLOBAL_STRING #if GTEST_HAS_GLOBAL_STRING
RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT
# endif // GTEST_HAS_GLOBAL_STRING #endif // GTEST_HAS_GLOBAL_STRING
RE(const char* regex) { Init(regex); } // NOLINT RE(const char* regex) { Init(regex); } // NOLINT
~RE(); ~RE();
@ -1264,7 +1201,7 @@ class GTEST_API_ RE {
return PartialMatch(str.c_str(), re); return PartialMatch(str.c_str(), re);
} }
# if GTEST_HAS_GLOBAL_STRING #if GTEST_HAS_GLOBAL_STRING
static bool FullMatch(const ::string& str, const RE& re) { static bool FullMatch(const ::string& str, const RE& re) {
return FullMatch(str.c_str(), re); return FullMatch(str.c_str(), re);
@ -1273,7 +1210,7 @@ class GTEST_API_ RE {
return PartialMatch(str.c_str(), re); return PartialMatch(str.c_str(), re);
} }
# endif // GTEST_HAS_GLOBAL_STRING #endif // GTEST_HAS_GLOBAL_STRING
static bool FullMatch(const char* str, const RE& re); static bool FullMatch(const char* str, const RE& re);
static bool PartialMatch(const char* str, const RE& re); static bool PartialMatch(const char* str, const RE& re);
@ -1287,22 +1224,20 @@ class GTEST_API_ RE {
const char* pattern_; const char* pattern_;
bool is_valid_; bool is_valid_;
# if GTEST_USES_POSIX_RE #if GTEST_USES_POSIX_RE
regex_t full_regex_; // For FullMatch(). regex_t full_regex_; // For FullMatch().
regex_t partial_regex_; // For PartialMatch(). regex_t partial_regex_; // For PartialMatch().
# else // GTEST_USES_SIMPLE_RE #else // GTEST_USES_SIMPLE_RE
const char* full_pattern_; // For FullMatch(); const char* full_pattern_; // For FullMatch();
# endif #endif
GTEST_DISALLOW_ASSIGN_(RE); GTEST_DISALLOW_ASSIGN_(RE);
}; };
#endif // GTEST_USES_PCRE
// Formats a source file path and a line number as they would appear // Formats a source file path and a line number as they would appear
// in an error message from the compiler used to compile this code. // in an error message from the compiler used to compile this code.
GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
@ -1388,59 +1323,13 @@ inline void FlushInfoLog() { fflush(NULL); }
GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
<< gtest_error << gtest_error
// Adds reference to a type if it is not a reference type,
// otherwise leaves it unchanged. This is the same as
// tr1::add_reference, which is not widely available yet.
template <typename T>
struct AddReference { typedef T& type; }; // NOLINT
template <typename T>
struct AddReference<T&> { typedef T& type; }; // NOLINT
// A handy wrapper around AddReference that works when the argument T
// depends on template parameters.
#define GTEST_ADD_REFERENCE_(T) \
typename ::testing::internal::AddReference<T>::type
// Transforms "T" into "const T&" according to standard reference collapsing
// rules (this is only needed as a backport for C++98 compilers that do not
// support reference collapsing). Specifically, it transforms:
//
// char ==> const char&
// const char ==> const char&
// char& ==> char&
// const char& ==> const char&
//
// Note that the non-const reference will not have "const" added. This is
// standard, and necessary so that "T" can always bind to "const T&".
template <typename T>
struct ConstRef { typedef const T& type; };
template <typename T>
struct ConstRef<T&> { typedef T& type; };
// The argument T must depend on some template parameters.
#define GTEST_REFERENCE_TO_CONST_(T) \
typename ::testing::internal::ConstRef<T>::type
#if GTEST_HAS_STD_MOVE_ #if GTEST_HAS_STD_MOVE_
using std::forward;
using std::move; using std::move;
template <typename T>
struct RvalueRef {
typedef T&& type;
};
#else // GTEST_HAS_STD_MOVE_ #else // GTEST_HAS_STD_MOVE_
template <typename T> template <typename T>
const T& move(const T& t) { const T& move(const T& t) {
return t; return t;
} }
template <typename T>
GTEST_ADD_REFERENCE_(T) forward(GTEST_ADD_REFERENCE_(T) t) { return t; }
template <typename T>
struct RvalueRef {
typedef const T& type;
};
#endif // GTEST_HAS_STD_MOVE_ #endif // GTEST_HAS_STD_MOVE_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
@ -1541,6 +1430,10 @@ GTEST_API_ void CaptureStderr();
GTEST_API_ std::string GetCapturedStderr(); GTEST_API_ std::string GetCapturedStderr();
#endif // GTEST_HAS_STREAM_REDIRECTION #endif // GTEST_HAS_STREAM_REDIRECTION
// Returns a path to temporary directory.
GTEST_API_ std::string TempDir();
// Returns the size (in bytes) of a file. // Returns the size (in bytes) of a file.
GTEST_API_ size_t GetFileSize(FILE* file); GTEST_API_ size_t GetFileSize(FILE* file);
@ -1548,18 +1441,14 @@ GTEST_API_ size_t GetFileSize(FILE* file);
GTEST_API_ std::string ReadEntireFile(FILE* file); GTEST_API_ std::string ReadEntireFile(FILE* file);
// All command line arguments. // All command line arguments.
GTEST_API_ std::vector<std::string> GetArgvs(); GTEST_API_ const ::std::vector<testing::internal::string>& GetArgvs();
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
std::vector<std::string> GetInjectableArgvs(); const ::std::vector<testing::internal::string>& GetInjectableArgvs();
// Deprecated: pass the args vector by value instead. void SetInjectableArgvs(const ::std::vector<testing::internal::string>*
void SetInjectableArgvs(const std::vector<std::string>* new_argvs); new_argvs);
void SetInjectableArgvs(const std::vector<std::string>& new_argvs);
#if GTEST_HAS_GLOBAL_STRING
void SetInjectableArgvs(const std::vector< ::string>& new_argvs);
#endif // GTEST_HAS_GLOBAL_STRING
void ClearInjectableArgvs();
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
@ -1817,7 +1706,7 @@ class GTEST_API_ Mutex {
// by the linker. // by the linker.
MutexType type_; MutexType type_;
long critical_section_init_phase_; // NOLINT long critical_section_init_phase_; // NOLINT
GTEST_CRITICAL_SECTION* critical_section_; _RTL_CRITICAL_SECTION* critical_section_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
}; };
@ -2151,7 +2040,7 @@ extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
// Implements thread-local storage on pthreads-based systems. // Implements thread-local storage on pthreads-based systems.
template <typename T> template <typename T>
class GTEST_API_ ThreadLocal { class ThreadLocal {
public: public:
ThreadLocal() ThreadLocal()
: key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {} : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
@ -2283,7 +2172,7 @@ class GTestMutexLock {
typedef GTestMutexLock MutexLock; typedef GTestMutexLock MutexLock;
template <typename T> template <typename T>
class GTEST_API_ ThreadLocal { class ThreadLocal {
public: public:
ThreadLocal() : value_() {} ThreadLocal() : value_() {}
explicit ThreadLocal(const T& value) : value_(value) {} explicit ThreadLocal(const T& value) : value_(value) {}
@ -2302,13 +2191,12 @@ class GTEST_API_ ThreadLocal {
GTEST_API_ size_t GetThreadCount(); GTEST_API_ size_t GetThreadCount();
// Passing non-POD classes through ellipsis (...) crashes the ARM // Passing non-POD classes through ellipsis (...) crashes the ARM
// compiler and generates a warning in Sun Studio before 12u4. The Nokia Symbian // compiler and generates a warning in Sun Studio. The Nokia Symbian
// and the IBM XL C/C++ compiler try to instantiate a copy constructor // and the IBM XL C/C++ compiler try to instantiate a copy constructor
// for objects passed through ellipsis (...), failing for uncopyable // for objects passed through ellipsis (...), failing for uncopyable
// objects. We define this to ensure that only POD is passed through // objects. We define this to ensure that only POD is passed through
// ellipsis on these systems. // ellipsis on these systems.
#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || \ #if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
(defined(__SUNPRO_CC) && __SUNPRO_CC < 0x5130)
// We lose support for NULL detection where the compiler doesn't like // We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...). // passing non-POD classes through ellipsis (...).
# define GTEST_ELLIPSIS_NEEDS_POD_ 1 # define GTEST_ELLIPSIS_NEEDS_POD_ 1
@ -2334,13 +2222,6 @@ template <bool bool_value> const bool bool_constant<bool_value>::value;
typedef bool_constant<false> false_type; typedef bool_constant<false> false_type;
typedef bool_constant<true> true_type; typedef bool_constant<true> true_type;
template <typename T, typename U>
struct is_same : public false_type {};
template <typename T>
struct is_same<T, T> : public true_type {};
template <typename T> template <typename T>
struct is_pointer : public false_type {}; struct is_pointer : public false_type {};
@ -2352,7 +2233,6 @@ struct IteratorTraits {
typedef typename Iterator::value_type value_type; typedef typename Iterator::value_type value_type;
}; };
template <typename T> template <typename T>
struct IteratorTraits<T*> { struct IteratorTraits<T*> {
typedef T value_type; typedef T value_type;
@ -2518,7 +2398,7 @@ inline int Close(int fd) { return close(fd); }
inline const char* StrError(int errnum) { return strerror(errnum); } inline const char* StrError(int errnum) { return strerror(errnum); }
#endif #endif
inline const char* GetEnv(const char* name) { inline const char* GetEnv(const char* name) {
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE | GTEST_OS_WINDOWS_RT
// We are on Windows CE, which has no environment variables. // We are on Windows CE, which has no environment variables.
static_cast<void>(name); // To prevent 'unused argument' warning. static_cast<void>(name); // To prevent 'unused argument' warning.
return NULL; return NULL;
@ -2648,15 +2528,15 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds.
# define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) # define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
# define GTEST_DECLARE_int32_(name) \ # define GTEST_DECLARE_int32_(name) \
GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
# define GTEST_DECLARE_string_(name) \ #define GTEST_DECLARE_string_(name) \
GTEST_API_ extern ::std::string GTEST_FLAG(name) GTEST_API_ extern ::std::string GTEST_FLAG(name)
// Macros for defining flags. // Macros for defining flags.
# define GTEST_DEFINE_bool_(name, default_val, doc) \ #define GTEST_DEFINE_bool_(name, default_val, doc) \
GTEST_API_ bool GTEST_FLAG(name) = (default_val) GTEST_API_ bool GTEST_FLAG(name) = (default_val)
# define GTEST_DEFINE_int32_(name, default_val, doc) \ #define GTEST_DEFINE_int32_(name, default_val, doc) \
GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
# define GTEST_DEFINE_string_(name, default_val, doc) \ #define GTEST_DEFINE_string_(name, default_val, doc) \
GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val)
#endif // !defined(GTEST_DECLARE_bool_) #endif // !defined(GTEST_DECLARE_bool_)
@ -2679,8 +2559,7 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value);
// corresponding to the given Google Test flag. // corresponding to the given Google Test flag.
bool BoolFromGTestEnv(const char* flag, bool default_val); bool BoolFromGTestEnv(const char* flag, bool default_val);
GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
std::string OutputFlagAlsoCheckEnvVar(); std::string StringFromGTestEnv(const char* flag, const char* default_val);
const char* StringFromGTestEnv(const char* flag, const char* default_val);
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing

View File

@ -27,6 +27,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
// //
// The Google C++ Testing Framework (Google Test) // The Google C++ Testing Framework (Google Test)
// //
@ -34,8 +35,7 @@
// Google Test. They are subject to change without notice. They should not used // Google Test. They are subject to change without notice. They should not used
// by code external to Google Test. // by code external to Google Test.
// //
// This header file is #included by // This header file is #included by <gtest/internal/gtest-internal.h>.
// gtest/internal/gtest-internal.h.
// It should not be #included by other files. // It should not be #included by other files.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_

View File

@ -66,18 +66,22 @@
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick exists to
// prevent the accidental inclusion of gtest-internal-inl.h in the
// user's code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
namespace testing { namespace testing {
// Constants. // Constants.
// The default death test style. // The default death test style.
// static const char kDefaultDeathTestStyle[] = "fast";
// This is defined in internal/gtest-port.h as "fast", but can be overridden by
// a definition in internal/custom/gtest-port.h. The recommended value, which is
// used internally at Google, is "threadsafe".
static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
GTEST_DEFINE_string_( GTEST_DEFINE_string_(
death_test_style, death_test_style,
@ -255,7 +259,7 @@ enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
// message is propagated back to the parent process. Otherwise, the // message is propagated back to the parent process. Otherwise, the
// message is simply printed to stderr. In either case, the program // message is simply printed to stderr. In either case, the program
// then exits with status 1. // then exits with status 1.
static void DeathTestAbort(const std::string& message) { void DeathTestAbort(const std::string& message) {
// On a POSIX system, this function may be called from a threadsafe-style // On a POSIX system, this function may be called from a threadsafe-style
// death test child process, which operates on a very small stack. Use // death test child process, which operates on a very small stack. Use
// the heap for any additional non-minuscule memory requirements. // the heap for any additional non-minuscule memory requirements.
@ -559,13 +563,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
break; break;
case DIED: case DIED:
if (status_ok) { if (status_ok) {
# if GTEST_USES_PCRE
// PCRE regexes support embedded NULs.
// GTEST_USES_PCRE is defined only in google3 mode
const bool matched = RE::PartialMatch(error_message, *regex());
# else
const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
# endif // GTEST_USES_PCRE
if (matched) { if (matched) {
success = true; success = true;
} else { } else {
@ -885,10 +883,11 @@ class ExecDeathTest : public ForkingDeathTest {
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
virtual TestRole AssumeRole(); virtual TestRole AssumeRole();
private: private:
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() { static ::std::vector<testing::internal::string>
::std::vector<std::string> args = GetInjectableArgvs(); GetArgvsForDeathTestChildProcess() {
::std::vector<testing::internal::string> args = GetInjectableArgvs();
# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) # if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
::std::vector<std::string> extra_args = ::std::vector<testing::internal::string> extra_args =
GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_(); GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
args.insert(args.end(), extra_args.begin(), extra_args.end()); args.insert(args.end(), extra_args.begin(), extra_args.end());
# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) # endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
@ -987,7 +986,6 @@ static int ExecDeathTestChildMain(void* child_arg) {
} }
# endif // !GTEST_OS_QNX # endif // !GTEST_OS_QNX
# if GTEST_HAS_CLONE
// Two utility routines that together determine the direction the stack // Two utility routines that together determine the direction the stack
// grows. // grows.
// This could be accomplished more elegantly by a single recursive // This could be accomplished more elegantly by a single recursive
@ -997,22 +995,20 @@ static int ExecDeathTestChildMain(void* child_arg) {
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining // GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
// StackLowerThanAddress into StackGrowsDown, which then doesn't give // StackLowerThanAddress into StackGrowsDown, which then doesn't give
// correct answer. // correct answer.
static void StackLowerThanAddress(const void* ptr, void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
bool* result) GTEST_NO_INLINE_; void StackLowerThanAddress(const void* ptr, bool* result) {
static void StackLowerThanAddress(const void* ptr, bool* result) {
int dummy; int dummy;
*result = (&dummy < ptr); *result = (&dummy < ptr);
} }
// Make sure AddressSanitizer does not tamper with the stack here. // Make sure AddressSanitizer does not tamper with the stack here.
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
static bool StackGrowsDown() { bool StackGrowsDown() {
int dummy; int dummy;
bool result; bool result;
StackLowerThanAddress(&dummy, &result); StackLowerThanAddress(&dummy, &result);
return result; return result;
} }
# endif // GTEST_HAS_CLONE
// Spawns a child process with the same executable as the current process in // Spawns a child process with the same executable as the current process in
// a thread-safe manner and instructs it to run the death test. The // a thread-safe manner and instructs it to run the death test. The
@ -1228,7 +1224,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
// Recreates the pipe and event handles from the provided parameters, // Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe // signals the event, and returns a file descriptor wrapped around the pipe
// handle. This function is called in the child process only. // handle. This function is called in the child process only.
static int GetStatusFileDescriptor(unsigned int parent_process_id, int GetStatusFileDescriptor(unsigned int parent_process_id,
size_t write_handle_as_size_t, size_t write_handle_as_size_t,
size_t event_handle_as_size_t) { size_t event_handle_as_size_t) {
AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
@ -1247,7 +1243,7 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
reinterpret_cast<HANDLE>(write_handle_as_size_t); reinterpret_cast<HANDLE>(write_handle_as_size_t);
HANDLE dup_write_handle; HANDLE dup_write_handle;
// The newly initialized handle is accessible only in the parent // The newly initialized handle is accessible only in in the parent
// process. To obtain one accessible within the child, we need to use // process. To obtain one accessible within the child, we need to use
// DuplicateHandle. // DuplicateHandle.
if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,

View File

@ -26,12 +26,14 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: keith.ray@gmail.com (Keith Ray)
#include "gtest/gtest-message.h"
#include "gtest/internal/gtest-filepath.h" #include "gtest/internal/gtest-filepath.h"
#include "gtest/internal/gtest-port.h"
#include <stdlib.h> #include <stdlib.h>
#include "gtest/internal/gtest-port.h"
#include "gtest/gtest-message.h"
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE
# include <windows.h> # include <windows.h>
@ -46,8 +48,6 @@
# include <climits> // Some Linux distributions define PATH_MAX here. # include <climits> // Some Linux distributions define PATH_MAX here.
#endif // GTEST_OS_WINDOWS_MOBILE #endif // GTEST_OS_WINDOWS_MOBILE
#include "gtest/internal/gtest-string.h"
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
# define GTEST_PATH_MAX_ _MAX_PATH # define GTEST_PATH_MAX_ _MAX_PATH
#elif defined(PATH_MAX) #elif defined(PATH_MAX)
@ -58,6 +58,8 @@
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX # define GTEST_PATH_MAX_ _POSIX_PATH_MAX
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#include "gtest/internal/gtest-string.h"
namespace testing { namespace testing {
namespace internal { namespace internal {
@ -128,7 +130,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
return *this; return *this;
} }
// Returns a pointer to the last occurrence of a valid path separator in // Returns a pointer to the last occurence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path // the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found. // separators. Returns NULL if no path separator was found.
const char* FilePath::FindLastPathSeparator() const { const char* FilePath::FindLastPathSeparator() const {

View File

@ -37,6 +37,14 @@
#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ #ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
#define GTEST_SRC_GTEST_INTERNAL_INL_H_ #define GTEST_SRC_GTEST_INTERNAL_INL_H_
// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
// part of Google Test's implementation; otherwise it's undefined.
#if !GTEST_IMPLEMENTATION_
// If this file is included from the user's code, just say no.
# error "gtest-internal-inl.h is part of Google Test's internal implementation."
# error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_
#ifndef _WIN32_WCE #ifndef _WIN32_WCE
# include <errno.h> # include <errno.h>
#endif // !_WIN32_WCE #endif // !_WIN32_WCE
@ -59,7 +67,7 @@
# include <windows.h> // NOLINT # include <windows.h> // NOLINT
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#include "gtest/gtest.h" #include "gtest/gtest.h" // NOLINT
#include "gtest/gtest-spi.h" #include "gtest/gtest-spi.h"
namespace testing { namespace testing {
@ -86,7 +94,6 @@ const char kFilterFlag[] = "filter";
const char kListTestsFlag[] = "list_tests"; const char kListTestsFlag[] = "list_tests";
const char kOutputFlag[] = "output"; const char kOutputFlag[] = "output";
const char kPrintTimeFlag[] = "print_time"; const char kPrintTimeFlag[] = "print_time";
const char kPrintUTF8Flag[] = "print_utf8";
const char kRandomSeedFlag[] = "random_seed"; const char kRandomSeedFlag[] = "random_seed";
const char kRepeatFlag[] = "repeat"; const char kRepeatFlag[] = "repeat";
const char kShuffleFlag[] = "shuffle"; const char kShuffleFlag[] = "shuffle";
@ -167,7 +174,6 @@ class GTestFlagSaver {
list_tests_ = GTEST_FLAG(list_tests); list_tests_ = GTEST_FLAG(list_tests);
output_ = GTEST_FLAG(output); output_ = GTEST_FLAG(output);
print_time_ = GTEST_FLAG(print_time); print_time_ = GTEST_FLAG(print_time);
print_utf8_ = GTEST_FLAG(print_utf8);
random_seed_ = GTEST_FLAG(random_seed); random_seed_ = GTEST_FLAG(random_seed);
repeat_ = GTEST_FLAG(repeat); repeat_ = GTEST_FLAG(repeat);
shuffle_ = GTEST_FLAG(shuffle); shuffle_ = GTEST_FLAG(shuffle);
@ -189,7 +195,6 @@ class GTestFlagSaver {
GTEST_FLAG(list_tests) = list_tests_; GTEST_FLAG(list_tests) = list_tests_;
GTEST_FLAG(output) = output_; GTEST_FLAG(output) = output_;
GTEST_FLAG(print_time) = print_time_; GTEST_FLAG(print_time) = print_time_;
GTEST_FLAG(print_utf8) = print_utf8_;
GTEST_FLAG(random_seed) = random_seed_; GTEST_FLAG(random_seed) = random_seed_;
GTEST_FLAG(repeat) = repeat_; GTEST_FLAG(repeat) = repeat_;
GTEST_FLAG(shuffle) = shuffle_; GTEST_FLAG(shuffle) = shuffle_;
@ -211,7 +216,6 @@ class GTestFlagSaver {
bool list_tests_; bool list_tests_;
std::string output_; std::string output_;
bool print_time_; bool print_time_;
bool print_utf8_;
internal::Int32 random_seed_; internal::Int32 random_seed_;
internal::Int32 repeat_; internal::Int32 repeat_;
bool shuffle_; bool shuffle_;
@ -422,7 +426,7 @@ class OsStackTraceGetterInterface {
// in the trace. // in the trace.
// skip_count - the number of top frames to be skipped; doesn't count // skip_count - the number of top frames to be skipped; doesn't count
// against max_depth. // against max_depth.
virtual std::string CurrentStackTrace(int max_depth, int skip_count) = 0; virtual string CurrentStackTrace(int max_depth, int skip_count) = 0;
// UponLeavingGTest() should be called immediately before Google Test calls // UponLeavingGTest() should be called immediately before Google Test calls
// user code. It saves some information about the current stack that // user code. It saves some information about the current stack that
@ -442,7 +446,7 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface {
public: public:
OsStackTraceGetter() {} OsStackTraceGetter() {}
virtual std::string CurrentStackTrace(int max_depth, int skip_count); virtual string CurrentStackTrace(int max_depth, int skip_count);
virtual void UponLeavingGTest(); virtual void UponLeavingGTest();
private: private:
@ -660,11 +664,13 @@ class GTEST_API_ UnitTestImpl {
tear_down_tc)->AddTestInfo(test_info); tear_down_tc)->AddTestInfo(test_info);
} }
#if GTEST_HAS_PARAM_TEST
// Returns ParameterizedTestCaseRegistry object used to keep track of // Returns ParameterizedTestCaseRegistry object used to keep track of
// value-parameterized tests and instantiate and register them. // value-parameterized tests and instantiate and register them.
internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
return parameterized_test_registry_; return parameterized_test_registry_;
} }
#endif // GTEST_HAS_PARAM_TEST
// Sets the TestCase object for the test that's currently running. // Sets the TestCase object for the test that's currently running.
void set_current_test_case(TestCase* a_current_test_case) { void set_current_test_case(TestCase* a_current_test_case) {
@ -839,12 +845,14 @@ class GTEST_API_ UnitTestImpl {
// shuffled order. // shuffled order.
std::vector<int> test_case_indices_; std::vector<int> test_case_indices_;
#if GTEST_HAS_PARAM_TEST
// ParameterizedTestRegistry object used to register value-parameterized // ParameterizedTestRegistry object used to register value-parameterized
// tests. // tests.
internal::ParameterizedTestCaseRegistry parameterized_test_registry_; internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
// Indicates whether RegisterParameterizedTests() has been called already. // Indicates whether RegisterParameterizedTests() has been called already.
bool parameterized_tests_registered_; bool parameterized_tests_registered_;
#endif // GTEST_HAS_PARAM_TEST
// Index of the last death test case registered. Initially -1. // Index of the last death test case registered. Initially -1.
int last_death_test_case_; int last_death_test_case_;
@ -1024,7 +1032,7 @@ class TestResultAccessor {
#if GTEST_CAN_STREAM_RESULTS_ #if GTEST_CAN_STREAM_RESULTS_
// Streams test results to the given port on the given host machine. // Streams test results to the given port on the given host machine.
class StreamingListener : public EmptyTestEventListener { class GTEST_API_ StreamingListener : public EmptyTestEventListener {
public: public:
// Abstract base class for writing strings to a socket. // Abstract base class for writing strings to a socket.
class AbstractSocketWriter { class AbstractSocketWriter {
@ -1032,19 +1040,21 @@ class StreamingListener : public EmptyTestEventListener {
virtual ~AbstractSocketWriter() {} virtual ~AbstractSocketWriter() {}
// Sends a string to the socket. // Sends a string to the socket.
virtual void Send(const std::string& message) = 0; virtual void Send(const string& message) = 0;
// Closes the socket. // Closes the socket.
virtual void CloseConnection() {} virtual void CloseConnection() {}
// Sends a string and a newline to the socket. // Sends a string and a newline to the socket.
void SendLn(const std::string& message) { Send(message + "\n"); } void SendLn(const string& message) {
Send(message + "\n");
}
}; };
// Concrete class for actually writing strings to a socket. // Concrete class for actually writing strings to a socket.
class SocketWriter : public AbstractSocketWriter { class SocketWriter : public AbstractSocketWriter {
public: public:
SocketWriter(const std::string& host, const std::string& port) SocketWriter(const string& host, const string& port)
: sockfd_(-1), host_name_(host), port_num_(port) { : sockfd_(-1), host_name_(host), port_num_(port) {
MakeConnection(); MakeConnection();
} }
@ -1055,7 +1065,7 @@ class StreamingListener : public EmptyTestEventListener {
} }
// Sends a string to the socket. // Sends a string to the socket.
virtual void Send(const std::string& message) { virtual void Send(const string& message) {
GTEST_CHECK_(sockfd_ != -1) GTEST_CHECK_(sockfd_ != -1)
<< "Send() can be called only when there is a connection."; << "Send() can be called only when there is a connection.";
@ -1081,19 +1091,17 @@ class StreamingListener : public EmptyTestEventListener {
} }
int sockfd_; // socket file descriptor int sockfd_; // socket file descriptor
const std::string host_name_; const string host_name_;
const std::string port_num_; const string port_num_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
}; // class SocketWriter }; // class SocketWriter
// Escapes '=', '&', '%', and '\n' characters in str as "%xx". // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
static std::string UrlEncode(const char* str); static string UrlEncode(const char* str);
StreamingListener(const std::string& host, const std::string& port) StreamingListener(const string& host, const string& port)
: socket_writer_(new SocketWriter(host, port)) { : socket_writer_(new SocketWriter(host, port)) { Start(); }
Start();
}
explicit StreamingListener(AbstractSocketWriter* socket_writer) explicit StreamingListener(AbstractSocketWriter* socket_writer)
: socket_writer_(socket_writer) { Start(); } : socket_writer_(socket_writer) { Start(); }
@ -1154,13 +1162,13 @@ class StreamingListener : public EmptyTestEventListener {
private: private:
// Sends the given message and a newline to the socket. // Sends the given message and a newline to the socket.
void SendLn(const std::string& message) { socket_writer_->SendLn(message); } void SendLn(const string& message) { socket_writer_->SendLn(message); }
// Called at the start of streaming to notify the receiver what // Called at the start of streaming to notify the receiver what
// protocol we are using. // protocol we are using.
void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
std::string FormatBool(bool value) { return value ? "1" : "0"; } string FormatBool(bool value) { return value ? "1" : "0"; }
const scoped_ptr<AbstractSocketWriter> socket_writer_; const scoped_ptr<AbstractSocketWriter> socket_writer_;

View File

@ -67,7 +67,15 @@
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h"
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick exists to
// prevent the accidental inclusion of gtest-internal-inl.h in the
// user's code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
namespace testing { namespace testing {
namespace internal { namespace internal {
@ -85,7 +93,7 @@ const int kStdErrFileno = STDERR_FILENO;
namespace { namespace {
template <typename T> template <typename T>
T ReadProcFileField(const std::string& filename, int field) { T ReadProcFileField(const string& filename, int field) {
std::string dummy; std::string dummy;
std::ifstream file(filename.c_str()); std::ifstream file(filename.c_str());
while (field-- > 0) { while (field-- > 0) {
@ -99,7 +107,7 @@ T ReadProcFileField(const std::string& filename, int field) {
// Returns the number of active threads, or 0 when there is an error. // Returns the number of active threads, or 0 when there is an error.
size_t GetThreadCount() { size_t GetThreadCount() {
const std::string filename = const string filename =
(Message() << "/proc/" << getpid() << "/stat").GetString(); (Message() << "/proc/" << getpid() << "/stat").GetString();
return ReadProcFileField<int>(filename, 19); return ReadProcFileField<int>(filename, 19);
} }
@ -488,7 +496,7 @@ class ThreadLocalRegistryImpl {
FALSE, FALSE,
thread_id); thread_id);
GTEST_CHECK_(thread != NULL); GTEST_CHECK_(thread != NULL);
// We need to pass a valid thread ID pointer into CreateThread for it // We need to to pass a valid thread ID pointer into CreateThread for it
// to work correctly under Win98. // to work correctly under Win98.
DWORD watcher_thread_id; DWORD watcher_thread_id;
HANDLE watcher_thread = ::CreateThread( HANDLE watcher_thread = ::CreateThread(
@ -663,7 +671,7 @@ bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
} }
// Helper function used by ValidateRegex() to format error messages. // Helper function used by ValidateRegex() to format error messages.
static std::string FormatRegexSyntaxError(const char* regex, int index) { std::string FormatRegexSyntaxError(const char* regex, int index) {
return (Message() << "Syntax error at index " << index return (Message() << "Syntax error at index " << index
<< " in simple regular expression \"" << regex << "\": ").GetString(); << " in simple regular expression \"" << regex << "\": ").GetString();
} }
@ -915,7 +923,6 @@ GTestLog::~GTestLog() {
posix::Abort(); posix::Abort();
} }
} }
// Disable Microsoft deprecation warnings for POSIX functions called from // Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close) // this class (creat, dup, dup2, and close)
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
@ -1008,8 +1015,7 @@ static CapturedStream* g_captured_stderr = NULL;
static CapturedStream* g_captured_stdout = NULL; static CapturedStream* g_captured_stdout = NULL;
// Starts capturing an output stream (stdout/stderr). // Starts capturing an output stream (stdout/stderr).
static void CaptureStream(int fd, const char* stream_name, void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
CapturedStream** stream) {
if (*stream != NULL) { if (*stream != NULL) {
GTEST_LOG_(FATAL) << "Only one " << stream_name GTEST_LOG_(FATAL) << "Only one " << stream_name
<< " capturer can exist at a time."; << " capturer can exist at a time.";
@ -1018,7 +1024,7 @@ static void CaptureStream(int fd, const char* stream_name,
} }
// Stops capturing the output stream and returns the captured string. // Stops capturing the output stream and returns the captured string.
static std::string GetCapturedStream(CapturedStream** captured_stream) { std::string GetCapturedStream(CapturedStream** captured_stream) {
const std::string content = (*captured_stream)->GetCapturedString(); const std::string content = (*captured_stream)->GetCapturedString();
delete *captured_stream; delete *captured_stream;
@ -1049,9 +1055,23 @@ std::string GetCapturedStderr() {
#endif // GTEST_HAS_STREAM_REDIRECTION #endif // GTEST_HAS_STREAM_REDIRECTION
std::string TempDir() {
#if GTEST_OS_WINDOWS_MOBILE
return "\\temp\\";
#elif GTEST_OS_WINDOWS
const char* temp_dir = posix::GetEnv("TEMP");
if (temp_dir == NULL || temp_dir[0] == '\0')
return "\\temp\\";
else if (temp_dir[strlen(temp_dir) - 1] == '\\')
return temp_dir;
else
return std::string(temp_dir) + "\\";
#elif GTEST_OS_LINUX_ANDROID
return "/sdcard/";
#else
return "/tmp/";
#endif // GTEST_OS_WINDOWS_MOBILE
}
size_t GetFileSize(FILE* file) { size_t GetFileSize(FILE* file) {
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
@ -1081,36 +1101,22 @@ std::string ReadEntireFile(FILE* file) {
} }
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
static const std::vector<std::string>* g_injected_test_argvs = NULL; // Owned.
std::vector<std::string> GetInjectableArgvs() { static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
NULL; // Owned.
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
if (g_injected_test_argvs != argvs)
delete g_injected_test_argvs;
g_injected_test_argvs = argvs;
}
const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
if (g_injected_test_argvs != NULL) { if (g_injected_test_argvs != NULL) {
return *g_injected_test_argvs; return *g_injected_test_argvs;
} }
return GetArgvs(); return GetArgvs();
} }
void SetInjectableArgvs(const std::vector<std::string>* new_argvs) {
if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs;
g_injected_test_argvs = new_argvs;
}
void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
SetInjectableArgvs(
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
}
#if GTEST_HAS_GLOBAL_STRING
void SetInjectableArgvs(const std::vector< ::string>& new_argvs) {
SetInjectableArgvs(
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
}
#endif // GTEST_HAS_GLOBAL_STRING
void ClearInjectableArgvs() {
delete g_injected_test_argvs;
g_injected_test_argvs = NULL;
}
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE
@ -1185,12 +1191,11 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
bool BoolFromGTestEnv(const char* flag, bool default_value) { bool BoolFromGTestEnv(const char* flag, bool default_value) {
#if defined(GTEST_GET_BOOL_FROM_ENV_) #if defined(GTEST_GET_BOOL_FROM_ENV_)
return GTEST_GET_BOOL_FROM_ENV_(flag, default_value); return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
#else #endif // defined(GTEST_GET_BOOL_FROM_ENV_)
const std::string env_var = FlagToEnvVar(flag); const std::string env_var = FlagToEnvVar(flag);
const char* const string_value = posix::GetEnv(env_var.c_str()); const char* const string_value = posix::GetEnv(env_var.c_str());
return string_value == NULL ? return string_value == NULL ?
default_value : strcmp(string_value, "0") != 0; default_value : strcmp(string_value, "0") != 0;
#endif // defined(GTEST_GET_BOOL_FROM_ENV_)
} }
// Reads and returns a 32-bit integer stored in the environment // Reads and returns a 32-bit integer stored in the environment
@ -1199,7 +1204,7 @@ bool BoolFromGTestEnv(const char* flag, bool default_value) {
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
#if defined(GTEST_GET_INT32_FROM_ENV_) #if defined(GTEST_GET_INT32_FROM_ENV_)
return GTEST_GET_INT32_FROM_ENV_(flag, default_value); return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
#else #endif // defined(GTEST_GET_INT32_FROM_ENV_)
const std::string env_var = FlagToEnvVar(flag); const std::string env_var = FlagToEnvVar(flag);
const char* const string_value = posix::GetEnv(env_var.c_str()); const char* const string_value = posix::GetEnv(env_var.c_str());
if (string_value == NULL) { if (string_value == NULL) {
@ -1217,36 +1222,37 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
} }
return result; return result;
#endif // defined(GTEST_GET_INT32_FROM_ENV_)
}
// As a special case for the 'output' flag, if GTEST_OUTPUT is not
// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
// system. The value of XML_OUTPUT_FILE is a filename without the
// "xml:" prefix of GTEST_OUTPUT.
// Note that this is meant to be called at the call site so it does
// not check that the flag is 'output'
// In essence this checks an env variable called XML_OUTPUT_FILE
// and if it is set we prepend "xml:" to its value, if it not set we return ""
std::string OutputFlagAlsoCheckEnvVar(){
std::string default_value_for_output_flag = "";
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
if (NULL != xml_output_file_env) {
default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
}
return default_value_for_output_flag;
} }
// Reads and returns the string environment variable corresponding to // Reads and returns the string environment variable corresponding to
// the given flag; if it's not set, returns default_value. // the given flag; if it's not set, returns default_value.
const char* StringFromGTestEnv(const char* flag, const char* default_value) { std::string StringFromGTestEnv(const char* flag, const char* default_value) {
#if defined(GTEST_GET_STRING_FROM_ENV_) #if defined(GTEST_GET_STRING_FROM_ENV_)
return GTEST_GET_STRING_FROM_ENV_(flag, default_value); return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
#else
const std::string env_var = FlagToEnvVar(flag);
const char* const value = posix::GetEnv(env_var.c_str());
return value == NULL ? default_value : value;
#endif // defined(GTEST_GET_STRING_FROM_ENV_) #endif // defined(GTEST_GET_STRING_FROM_ENV_)
const std::string env_var = FlagToEnvVar(flag);
const char* value = posix::GetEnv(env_var.c_str());
if (value != NULL) {
return value;
}
// As a special case for the 'output' flag, if GTEST_OUTPUT is not
// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
// system. The value of XML_OUTPUT_FILE is a filename without the
// "xml:" prefix of GTEST_OUTPUT.
//
// The net priority order after flag processing is thus:
// --gtest_output command line flag
// GTEST_OUTPUT environment variable
// XML_OUTPUT_FILE environment variable
// 'default_value'
if (strcmp(flag, "output") == 0) {
value = posix::GetEnv("XML_OUTPUT_FILE");
if (value != NULL) {
return std::string("xml:") + value;
}
}
return default_value;
} }
} // namespace internal } // namespace internal

View File

@ -43,13 +43,12 @@
// defines Foo. // defines Foo.
#include "gtest/gtest-printers.h" #include "gtest/gtest-printers.h"
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <cctype>
#include <cwchar> #include <cwchar>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "src/gtest-internal-inl.h"
namespace testing { namespace testing {
@ -124,7 +123,7 @@ namespace internal {
// Depending on the value of a char (or wchar_t), we print it in one // Depending on the value of a char (or wchar_t), we print it in one
// of three formats: // of three formats:
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), // - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
// - as a hexadecimal escape sequence (e.g. '\x7F'), or // - as a hexidecimal escape sequence (e.g. '\x7F'), or
// - as a special escape sequence (e.g. '\r', '\n'). // - as a special escape sequence (e.g. '\r', '\n').
enum CharFormat { enum CharFormat {
kAsIs, kAsIs,
@ -181,10 +180,7 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
*os << static_cast<char>(c); *os << static_cast<char>(c);
return kAsIs; return kAsIs;
} else { } else {
ostream::fmtflags flags = os->flags(); *os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
*os << "\\x" << std::hex << std::uppercase
<< static_cast<int>(static_cast<UnsignedChar>(c));
os->flags(flags);
return kHexEscape; return kHexEscape;
} }
} }
@ -231,7 +227,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
return; return;
*os << " (" << static_cast<int>(c); *os << " (" << static_cast<int>(c);
// For more convenience, we print c's code again in hexadecimal, // For more convenience, we print c's code again in hexidecimal,
// unless c was already printed in the form '\x##' or the code is in // unless c was already printed in the form '\x##' or the code is in
// [1, 9]. // [1, 9].
if (format == kHexEscape || (1 <= c && c <= 9)) { if (format == kHexEscape || (1 <= c && c <= 9)) {
@ -263,12 +259,11 @@ template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static CharFormat PrintCharsAsStringTo( static void PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) { const CharType* begin, size_t len, ostream* os) {
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
*os << kQuoteBegin; *os << kQuoteBegin;
bool is_previous_hex = false; bool is_previous_hex = false;
CharFormat print_format = kAsIs;
for (size_t index = 0; index < len; ++index) { for (size_t index = 0; index < len; ++index) {
const CharType cur = begin[index]; const CharType cur = begin[index];
if (is_previous_hex && IsXDigit(cur)) { if (is_previous_hex && IsXDigit(cur)) {
@ -278,13 +273,8 @@ static CharFormat PrintCharsAsStringTo(
*os << "\" " << kQuoteBegin; *os << "\" " << kQuoteBegin;
} }
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
// Remember if any characters required hex escaping.
if (is_previous_hex) {
print_format = kHexEscape;
}
} }
*os << "\""; *os << "\"";
return print_format;
} }
// Prints a (const) char/wchar_t array of 'len' elements, starting at address // Prints a (const) char/wchar_t array of 'len' elements, starting at address
@ -354,90 +344,15 @@ void PrintTo(const wchar_t* s, ostream* os) {
} }
#endif // wchar_t is native #endif // wchar_t is native
namespace {
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length; i++) {
unsigned char ch = *s++;
if (std::iscntrl(ch)) {
switch (ch) {
case '\t':
case '\n':
case '\r':
break;
default:
return true;
}
}
}
return false;
}
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
bool IsValidUTF8(const char* str, size_t length) {
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length;) {
unsigned char lead = s[i++];
if (lead <= 0x7f) {
continue; // single-byte character (ASCII) 0..7F
}
if (lead < 0xc2) {
return false; // trail byte or non-shortest form
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
++i; // 2-byte character
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
// check for non-shortest form and surrogate
(lead != 0xe0 || s[i] >= 0xa0) &&
(lead != 0xed || s[i] < 0xa0)) {
i += 2; // 3-byte character
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
IsUTF8TrailByte(s[i + 2]) &&
// check for non-shortest form
(lead != 0xf0 || s[i] >= 0x90) &&
(lead != 0xf4 || s[i] < 0x90)) {
i += 3; // 4-byte character
} else {
return false;
}
}
return true;
}
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
if (!ContainsUnprintableControlCodes(str, length) &&
IsValidUTF8(str, length)) {
*os << "\n As Text: \"" << str << "\"";
}
}
} // anonymous namespace
// Prints a ::string object. // Prints a ::string object.
#if GTEST_HAS_GLOBAL_STRING #if GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::string& s, ostream* os) { void PrintStringTo(const ::string& s, ostream* os) {
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) { PrintCharsAsStringTo(s.data(), s.size(), os);
if (GTEST_FLAG(print_utf8)) {
ConditionalPrintAsText(s.data(), s.size(), os);
}
}
} }
#endif // GTEST_HAS_GLOBAL_STRING #endif // GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::std::string& s, ostream* os) { void PrintStringTo(const ::std::string& s, ostream* os) {
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) { PrintCharsAsStringTo(s.data(), s.size(), os);
if (GTEST_FLAG(print_utf8)) {
ConditionalPrintAsText(s.data(), s.size(), os);
}
}
} }
// Prints a ::wstring object. // Prints a ::wstring object.

View File

@ -32,7 +32,15 @@
// The Google C++ Testing Framework (Google Test) // The Google C++ Testing Framework (Google Test)
#include "gtest/gtest-test-part.h" #include "gtest/gtest-test-part.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick exists to
// prevent the accidental inclusion of gtest-internal-inl.h in the
// user's code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
namespace testing { namespace testing {

Some files were not shown because too many files have changed in this diff Show More