Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
669e7b7454 | ||
![]() |
62a57630cc | ||
![]() |
240f8e56e4 | ||
![]() |
3b3ee4a4db |
109
.clang-format
109
.clang-format
@ -1,109 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Google
|
||||
# Generated with clang-format 5.0.0
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeCategories:
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IndentCaseLabels: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Auto
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -37,9 +37,9 @@
|
||||
/examples/twopass_encoder
|
||||
/examples/vp8_multi_resolution_encoder
|
||||
/examples/vp8cx_set_ref
|
||||
/examples/vp9cx_set_ref
|
||||
/examples/vp9_lossless_encoder
|
||||
/examples/vp9_spatial_svc_encoder
|
||||
/examples/vp9_spatial_scalable_encoder
|
||||
/examples/vpx_temporal_scalable_patterns
|
||||
/examples/vpx_temporal_svc_encoder
|
||||
/ivfdec
|
||||
/ivfdec.dox
|
||||
@ -50,9 +50,6 @@
|
||||
/samples.dox
|
||||
/test_intra_pred_speed
|
||||
/test_libvpx
|
||||
/tools.dox
|
||||
/tools/*.dox
|
||||
/tools/tiny_ssim
|
||||
/vp8_api1_migration.dox
|
||||
/vp[89x]_rtcd.h
|
||||
/vpx.pc
|
||||
|
12
.mailmap
12
.mailmap
@ -3,8 +3,6 @@ Aℓex Converse <aconverse@google.com>
|
||||
Aℓex Converse <aconverse@google.com> <alex.converse@gmail.com>
|
||||
Alexis Ballier <aballier@gentoo.org> <alexis.ballier@gmail.com>
|
||||
Alpha Lam <hclam@google.com> <hclam@chromium.org>
|
||||
Chris Cunningham <chcunningham@chromium.org>
|
||||
Daniele Castagna <dcastagna@chromium.org> <dcastagna@google.com>
|
||||
Deb Mukherjee <debargha@google.com>
|
||||
Erik Niemeyer <erik.a.niemeyer@intel.com> <erik.a.niemeyer@gmail.com>
|
||||
Guillaume Martres <gmartres@google.com> <smarter3@gmail.com>
|
||||
@ -15,28 +13,20 @@ Jim Bankoski <jimbankoski@google.com>
|
||||
Johann Koenig <johannkoenig@google.com>
|
||||
Johann Koenig <johannkoenig@google.com> <johann.koenig@duck.com>
|
||||
Johann Koenig <johannkoenig@google.com> <johann.koenig@gmail.com>
|
||||
Johann Koenig <johannkoenig@google.com> <johannkoenig@chromium.org>
|
||||
John Koleszar <jkoleszar@google.com>
|
||||
Joshua Litt <joshualitt@google.com> <joshualitt@chromium.org>
|
||||
Marco Paniconi <marpan@google.com>
|
||||
Marco Paniconi <marpan@google.com> <marpan@chromium.org>
|
||||
Pascal Massimino <pascal.massimino@gmail.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.derivaz@argondesign.com>
|
||||
Ralph Giles <giles@xiph.org> <giles@entropywave.com>
|
||||
Ralph Giles <giles@xiph.org> <giles@mozilla.com>
|
||||
Ronald S. Bultje <rsbultje@gmail.com> <rbultje@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> <levytamar82@gmail.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> Tim Terriberry <tterriberry@mozilla.com>
|
||||
Tom Finegan <tomfinegan@google.com>
|
||||
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> <yaowu@xuyaowu.com>
|
||||
Yaowu Xu <yaowu@google.com> <Yaowu Xu>
|
||||
|
38
AUTHORS
38
AUTHORS
@ -3,13 +3,11 @@
|
||||
|
||||
Aaron Watry <awatry@gmail.com>
|
||||
Abo Talib Mahfoodh <ab.mahfoodh@gmail.com>
|
||||
Adam Xu <adam@xuyaowu.com>
|
||||
Adrian Grange <agrange@google.com>
|
||||
Aℓex Converse <aconverse@google.com>
|
||||
Ahmad Sharif <asharif@google.com>
|
||||
Aleksey Vasenev <margtu-fivt@ya.ru>
|
||||
Alexander Potapenko <glider@google.com>
|
||||
Alexander Voronov <avoronov@graphics.cs.msu.ru>
|
||||
Alexandra Hájková <alexandra.khirnova@gmail.com>
|
||||
Alexis Ballier <aballier@gentoo.org>
|
||||
Alok Ahuja <waveletcoeff@gmail.com>
|
||||
Alpha Lam <hclam@google.com>
|
||||
@ -17,7 +15,6 @@ A.Mahfoodh <ab.mahfoodh@gmail.com>
|
||||
Ami Fischman <fischman@chromium.org>
|
||||
Andoni Morales Alastruey <ylatuya@gmail.com>
|
||||
Andres Mejia <mcitadel@gmail.com>
|
||||
Andrew Lewis <andrewlewis@google.com>
|
||||
Andrew Russell <anrussell@google.com>
|
||||
Angie Chiang <angiebird@google.com>
|
||||
Aron Rosenberg <arosenberg@logitech.com>
|
||||
@ -25,14 +22,10 @@ Attila Nagy <attilanagy@google.com>
|
||||
Brion Vibber <bvibber@wikimedia.org>
|
||||
changjun.yang <changjun.yang@intel.com>
|
||||
Charles 'Buck' Krasic <ckrasic@google.com>
|
||||
Cheng Chen <chengchen@google.com>
|
||||
chm <chm@rock-chips.com>
|
||||
Chris Cunningham <chcunningham@chromium.org>
|
||||
Christian Duvivier <cduvivier@google.com>
|
||||
Daniele Castagna <dcastagna@chromium.org>
|
||||
Daniel Kang <ddkang@google.com>
|
||||
Deb Mukherjee <debargha@google.com>
|
||||
Deepa K G <deepa.kg@ittiam.com>
|
||||
Dim Temp <dimtemp0@gmail.com>
|
||||
Dmitry Kovalev <dkovalev@google.com>
|
||||
Dragan Mrdjan <dmrdjan@mips.com>
|
||||
@ -43,21 +36,17 @@ Fabio Pedretti <fabio.ped@libero.it>
|
||||
Frank Galligan <fgalligan@google.com>
|
||||
Fredrik Söderquist <fs@opera.com>
|
||||
Fritz Koenig <frkoenig@google.com>
|
||||
Gabriel Marin <gmx@chromium.org>
|
||||
Gaute Strokkenes <gaute.strokkenes@broadcom.com>
|
||||
Geza Lore <gezalore@gmail.com>
|
||||
Ghislain MARY <ghislainmary2@gmail.com>
|
||||
Giuseppe Scrivano <gscrivano@gnu.org>
|
||||
Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com>
|
||||
Gregor Jasny <gjasny@gmail.com>
|
||||
Guillaume Martres <gmartres@google.com>
|
||||
Guillermo Ballester Valor <gbvalor@gmail.com>
|
||||
Hangyu Kuang <hkuang@google.com>
|
||||
Hanno Böck <hanno@hboeck.de>
|
||||
Han Shen <shenhan@google.com>
|
||||
Henrik Lundin <hlundin@google.com>
|
||||
Hui Su <huisu@google.com>
|
||||
Ivan Krasin <krasin@chromium.org>
|
||||
Ivan Maltz <ivanmaltz@google.com>
|
||||
Jacek Caban <cjacek@gmail.com>
|
||||
Jacky Chen <jackychen@google.com>
|
||||
@ -67,13 +56,10 @@ James Zern <jzern@google.com>
|
||||
Jan Gerber <j@mailb.org>
|
||||
Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Janne Salonen <jsalonen@google.com>
|
||||
Jean-Yves Avenard <jyavenard@mozilla.com>
|
||||
Jeff Faust <jfaust@google.com>
|
||||
Jeff Muizelaar <jmuizelaar@mozilla.com>
|
||||
Jeff Petkau <jpet@chromium.org>
|
||||
Jerome Jiang <jianj@google.com>
|
||||
Jia Jia <jia.jia@linaro.org>
|
||||
Jian Zhou <zhoujian@google.com>
|
||||
Jim Bankoski <jimbankoski@google.com>
|
||||
Jingning Han <jingning@google.com>
|
||||
Joey Parrish <joeyparrish@google.com>
|
||||
@ -86,11 +72,8 @@ Joshua Litt <joshualitt@google.com>
|
||||
Julia Robson <juliamrobson@gmail.com>
|
||||
Justin Clift <justin@salasaga.org>
|
||||
Justin Lebar <justin.lebar@gmail.com>
|
||||
Kaustubh Raste <kaustubh.raste@imgtec.com>
|
||||
KO Myung-Hun <komh@chollian.net>
|
||||
Kyle Siefring <kylesiefring@gmail.com>
|
||||
Lawrence Velázquez <larryv@macports.org>
|
||||
Linfeng Zhang <linfengz@google.com>
|
||||
Lou Quillio <louquillio@google.com>
|
||||
Luca Barbato <lu_zero@gentoo.org>
|
||||
Makoto Kato <makoto.kt@gmail.com>
|
||||
@ -104,12 +87,8 @@ Michael Kohler <michaelkohler@live.com>
|
||||
Mike Frysinger <vapier@chromium.org>
|
||||
Mike Hommey <mhommey@mozilla.com>
|
||||
Mikhal Shemer <mikhal@google.com>
|
||||
Min Chen <chenm003@gmail.com>
|
||||
Minghai Shang <minghai@google.com>
|
||||
Min Ye <yeemmi@google.com>
|
||||
Moriyoshi Koizumi <mozo@mozo.jp>
|
||||
Morton Jonuschat <yabawock@gmail.com>
|
||||
Nathan E. Egge <negge@mozilla.com>
|
||||
Nico Weber <thakis@chromium.org>
|
||||
Parag Salasakar <img.mips1@gmail.com>
|
||||
Pascal Massimino <pascal.massimino@gmail.com>
|
||||
@ -118,34 +97,24 @@ Paul Wilkins <paulwilkins@google.com>
|
||||
Pavol Rusnak <stick@gk2.sk>
|
||||
Paweł Hajdan <phajdan@google.com>
|
||||
Pengchong Jin <pengchong@google.com>
|
||||
Peter Boström <pbos@chromium.org>
|
||||
Peter Collingbourne <pcc@chromium.org>
|
||||
Peter de Rivaz <peter.derivaz@gmail.com>
|
||||
Philip Jägenstedt <philipj@opera.com>
|
||||
Priit Laes <plaes@plaes.org>
|
||||
Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
|
||||
Rafaël Carré <funman@videolan.org>
|
||||
Rafael de Lucena Valle <rafaeldelucena@gmail.com>
|
||||
Rahul Chaudhry <rahulchaudhry@google.com>
|
||||
Ralph Giles <giles@xiph.org>
|
||||
Ranjit Kumar Tulabandu <ranjit.tulabandu@ittiam.com>
|
||||
Rob Bradford <rob@linux.intel.com>
|
||||
Ronald S. Bultje <rsbultje@gmail.com>
|
||||
Rui Ueyama <ruiu@google.com>
|
||||
Sami Pietilä <samipietila@google.com>
|
||||
Sarah Parker <sarahparker@google.com>
|
||||
Sasi Inguva <isasi@google.com>
|
||||
Scott Graham <scottmg@chromium.org>
|
||||
Scott LaVarnway <slavarnway@google.com>
|
||||
Sean McGovern <gseanmcg@gmail.com>
|
||||
Sergey Kolomenkin <kolomenkin@gmail.com>
|
||||
Sergey Ulanov <sergeyu@chromium.org>
|
||||
Shimon Doodkin <helpmepro1@gmail.com>
|
||||
Shiyou Yin <yinshiyou-hf@loongson.cn>
|
||||
Shunyao Li <shunyaoli@google.com>
|
||||
Stefan Holmer <holmer@google.com>
|
||||
Suman Sunkara <sunkaras@google.com>
|
||||
Sylvestre Ledru <sylvestre@mozilla.com>
|
||||
Taekhyun Kim <takim@nvidia.com>
|
||||
Takanori MATSUURA <t.matsuu@gmail.com>
|
||||
Tamar Levy <tamar.levy@intel.com>
|
||||
@ -155,15 +124,10 @@ Thijs Vermeir <thijsvermeir@gmail.com>
|
||||
Tim Kopp <tkopp@google.com>
|
||||
Timothy B. Terriberry <tterribe@xiph.org>
|
||||
Tom Finegan <tomfinegan@google.com>
|
||||
Tristan Matthews <le.businessman@gmail.com>
|
||||
Urvang Joshi <urvang@google.com>
|
||||
Vignesh Venkatasubramanian <vigneshv@google.com>
|
||||
Vlad Tsyrklevich <vtsyrklevich@chromium.org>
|
||||
Yaowu Xu <yaowu@google.com>
|
||||
Yi Luo <luoyi@google.com>
|
||||
Yongzhe Wang <yongzhe@google.com>
|
||||
Yunqing Wang <yunqingwang@google.com>
|
||||
Yury Gitman <yuryg@google.com>
|
||||
Zoe Liu <zoeliu@google.com>
|
||||
Google Inc.
|
||||
The Mozilla Foundation
|
||||
|
73
CHANGELOG
73
CHANGELOG
@ -1,73 +1,6 @@
|
||||
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"
|
||||
This release improves upon the VP9 encoder and speeds up the encoding and
|
||||
decoding processes.
|
||||
|
||||
- Upgrading:
|
||||
This release is ABI compatible with 1.6.0.
|
||||
|
||||
- Enhancements:
|
||||
Faster VP9 encoding and decoding.
|
||||
High bit depth builds now provide similar speed for 8 bit encode and decode
|
||||
for x86 targets. Other platforms and higher bit depth improvements are in
|
||||
progress.
|
||||
|
||||
- Bug Fixes:
|
||||
A variety of fuzzing issues.
|
||||
|
||||
2016-07-20 v1.6.0 "Khaki Campbell Duck"
|
||||
This release improves upon the VP9 encoder and speeds up the encoding and
|
||||
decoding processes.
|
||||
|
||||
- Upgrading:
|
||||
This release is ABI incompatible with 1.5.0 due to a new 'color_range' enum
|
||||
in vpx_image and some minor changes to the VP8_COMP structure.
|
||||
|
||||
The default key frame interval for VP9 has changed from 128 to 9999.
|
||||
|
||||
- Enhancement:
|
||||
A core focus has been performance for low end Intel processors. SSSE3
|
||||
instructions such as 'pshufb' have been avoided and instructions have been
|
||||
reordered to better accommodate the more constrained pipelines.
|
||||
|
||||
As a result, devices based on Celeron processors have seen substantial
|
||||
decoding improvements. From Indian Runner Duck to Javan Whistling Duck,
|
||||
decoding speed improved between 10 and 30%. Between Javan Whistling Duck
|
||||
and Khaki Campbell Duck, it improved another 10 to 15%.
|
||||
|
||||
While Celeron benefited most, Core-i5 also improved 5% and 10% between the
|
||||
respective releases.
|
||||
|
||||
Realtime performance for WebRTC for both speed and quality has received a
|
||||
lot of attention.
|
||||
|
||||
- Bug Fixes:
|
||||
A number of fuzzing issues, found variously by Mozilla, Chromium and others,
|
||||
have been fixed and we strongly recommend updating.
|
||||
Next Release
|
||||
- Incompatible changes:
|
||||
The VP9 encoder's default keyframe interval changed to 128 from 9999.
|
||||
|
||||
2015-11-09 v1.5.0 "Javan Whistling Duck"
|
||||
This release improves upon the VP9 encoder and speeds up the encoding and
|
||||
|
74
README
74
README
@ -1,4 +1,4 @@
|
||||
README - 24 January 2018
|
||||
README - 23 March 2015
|
||||
|
||||
Welcome to the WebM VP8/VP9 Codec SDK!
|
||||
|
||||
@ -9,26 +9,22 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
|
||||
1. Prerequisites
|
||||
|
||||
* All x86 targets require the Yasm[1] assembler be installed[2].
|
||||
* All Windows builds require that Cygwin[3] be installed.
|
||||
* Building the documentation requires Doxygen[4]. If you do not
|
||||
* All x86 targets require the Yasm[1] assembler be installed.
|
||||
* All Windows builds require that Cygwin[2] be installed.
|
||||
* Building the documentation requires Doxygen[3]. If you do not
|
||||
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
|
||||
many *nix platforms, as well as MinGW and Cygwin. If coreutils is not
|
||||
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.
|
||||
|
||||
[1]: http://www.tortall.net/projects/yasm
|
||||
[2]: For Visual Studio the base yasm binary (not vsyasm) should be in the
|
||||
PATH for Visual Studio. For VS2017 it is sufficient to rename
|
||||
yasm-<version>-<arch>.exe to yasm.exe and place it in:
|
||||
Program Files (x86)/Microsoft Visual Studio/2017/<level>/Common7/Tools/
|
||||
[3]: http://www.cygwin.com
|
||||
[4]: http://www.doxygen.org
|
||||
[5]: http://curl.haxx.se
|
||||
[6]: http://www.microbrew.org/tools/md5sha1sum/
|
||||
[2]: http://www.cygwin.com
|
||||
[3]: http://www.doxygen.org
|
||||
[4]: http://curl.haxx.se
|
||||
[5]: http://www.microbrew.org/tools/md5sha1sum/
|
||||
|
||||
2. Out-of-tree builds
|
||||
Out of tree builds are a supported method of building the application. For
|
||||
@ -45,24 +41,16 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
used to get a list of supported options:
|
||||
$ ../libvpx/configure --help
|
||||
|
||||
4. Compiler analyzers
|
||||
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
|
||||
4. Cross development
|
||||
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
|
||||
--help output of the configure script. As of this writing, the list of
|
||||
available targets is:
|
||||
|
||||
arm64-android-gcc
|
||||
armv6-linux-rvct
|
||||
armv6-linux-gcc
|
||||
armv6-none-rvct
|
||||
arm64-darwin-gcc
|
||||
arm64-linux-gcc
|
||||
armv7-android-gcc
|
||||
armv7-darwin-gcc
|
||||
armv7-linux-rvct
|
||||
@ -71,13 +59,9 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
armv7-win32-vs11
|
||||
armv7-win32-vs12
|
||||
armv7-win32-vs14
|
||||
armv7-win32-vs15
|
||||
armv7s-darwin-gcc
|
||||
armv8-linux-gcc
|
||||
mips32-linux-gcc
|
||||
mips64-linux-gcc
|
||||
ppc64-linux-gcc
|
||||
ppc64le-linux-gcc
|
||||
sparc-solaris-gcc
|
||||
x86-android-gcc
|
||||
x86-darwin8-gcc
|
||||
@ -89,19 +73,19 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
x86-darwin12-gcc
|
||||
x86-darwin13-gcc
|
||||
x86-darwin14-gcc
|
||||
x86-darwin15-gcc
|
||||
x86-darwin16-gcc
|
||||
x86-iphonesimulator-gcc
|
||||
x86-linux-gcc
|
||||
x86-linux-icc
|
||||
x86-os2-gcc
|
||||
x86-solaris-gcc
|
||||
x86-win32-gcc
|
||||
x86-win32-vs7
|
||||
x86-win32-vs8
|
||||
x86-win32-vs9
|
||||
x86-win32-vs10
|
||||
x86-win32-vs11
|
||||
x86-win32-vs12
|
||||
x86-win32-vs14
|
||||
x86-win32-vs15
|
||||
x86_64-android-gcc
|
||||
x86_64-darwin9-gcc
|
||||
x86_64-darwin10-gcc
|
||||
@ -109,18 +93,17 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
x86_64-darwin12-gcc
|
||||
x86_64-darwin13-gcc
|
||||
x86_64-darwin14-gcc
|
||||
x86_64-darwin15-gcc
|
||||
x86_64-darwin16-gcc
|
||||
x86_64-iphonesimulator-gcc
|
||||
x86_64-linux-gcc
|
||||
x86_64-linux-icc
|
||||
x86_64-solaris-gcc
|
||||
x86_64-win64-gcc
|
||||
x86_64-win64-vs8
|
||||
x86_64-win64-vs9
|
||||
x86_64-win64-vs10
|
||||
x86_64-win64-vs11
|
||||
x86_64-win64-vs12
|
||||
x86_64-win64-vs14
|
||||
x86_64-win64-vs15
|
||||
generic-gnu
|
||||
|
||||
The generic-gnu target, in conjunction with the CROSS environment variable,
|
||||
@ -136,7 +119,7 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be
|
||||
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.
|
||||
This defaults to config.log. This should give a good indication of what went
|
||||
wrong. If not, contact us for support.
|
||||
@ -149,22 +132,7 @@ VP8/VP9 TEST VECTORS:
|
||||
$ ./configure --enable-unit-tests
|
||||
$ LIBVPX_TEST_DATA_PATH=../libvpx-test-data make testdata
|
||||
|
||||
CODE STYLE:
|
||||
The coding style used by this project is enforced with clang-format using the
|
||||
configuration contained in the .clang-format file in the root of the
|
||||
repository.
|
||||
|
||||
Before pushing changes for review you can format your code with:
|
||||
# Apply clang-format to modified .c, .h and .cc files
|
||||
$ clang-format -i --style=file \
|
||||
$(git diff --name-only --diff-filter=ACMR '*.[hc]' '*.cc')
|
||||
|
||||
Check the .clang-format file for the version used to generate it if there is
|
||||
any difference between your local formatting and the review system.
|
||||
|
||||
See also: http://clang.llvm.org/docs/ClangFormat.html
|
||||
|
||||
SUPPORT
|
||||
This library is an open source project supported by its community. Please
|
||||
email webm-discuss@webmproject.org for help.
|
||||
please email webm-discuss@webmproject.org for help.
|
||||
|
||||
|
127
args.c
127
args.c
@ -8,12 +8,12 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "args.h"
|
||||
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_ports/msvc.h"
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__
|
||||
@ -22,36 +22,42 @@ extern void die(const char *fmt, ...) __attribute__((noreturn));
|
||||
extern void die(const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
|
||||
struct arg arg_init(char **argv) {
|
||||
struct arg a;
|
||||
|
||||
a.argv = argv;
|
||||
a.argv = argv;
|
||||
a.argv_step = 1;
|
||||
a.name = NULL;
|
||||
a.val = NULL;
|
||||
a.def = NULL;
|
||||
a.name = NULL;
|
||||
a.val = NULL;
|
||||
a.def = NULL;
|
||||
return a;
|
||||
}
|
||||
|
||||
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
|
||||
struct arg arg;
|
||||
|
||||
if (!argv[0] || argv[0][0] != '-') return 0;
|
||||
if (!argv[0] || argv[0][0] != '-')
|
||||
return 0;
|
||||
|
||||
arg = arg_init(argv);
|
||||
|
||||
if (def->short_name && strlen(arg.argv[0]) == strlen(def->short_name) + 1 &&
|
||||
!strcmp(arg.argv[0] + 1, def->short_name)) {
|
||||
if (def->short_name
|
||||
&& strlen(arg.argv[0]) == strlen(def->short_name) + 1
|
||||
&& !strcmp(arg.argv[0] + 1, def->short_name)) {
|
||||
|
||||
arg.name = arg.argv[0] + 1;
|
||||
arg.val = def->has_val ? arg.argv[1] : NULL;
|
||||
arg.argv_step = def->has_val ? 2 : 1;
|
||||
} else if (def->long_name) {
|
||||
const size_t name_len = strlen(def->long_name);
|
||||
|
||||
if (strlen(arg.argv[0]) >= name_len + 2 && arg.argv[0][1] == '-' &&
|
||||
!strncmp(arg.argv[0] + 2, def->long_name, name_len) &&
|
||||
(arg.argv[0][name_len + 2] == '=' ||
|
||||
arg.argv[0][name_len + 2] == '\0')) {
|
||||
if (strlen(arg.argv[0]) >= name_len + 2
|
||||
&& arg.argv[0][1] == '-'
|
||||
&& !strncmp(arg.argv[0] + 2, def->long_name, name_len)
|
||||
&& (arg.argv[0][name_len + 2] == '='
|
||||
|| arg.argv[0][name_len + 2] == '\0')) {
|
||||
|
||||
arg.name = arg.argv[0] + 2;
|
||||
arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
|
||||
arg.argv_step = 1;
|
||||
@ -64,7 +70,8 @@ int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
|
||||
if (arg.name && arg.val && !def->has_val)
|
||||
die("Error: option %s requires no argument.\n", arg.name);
|
||||
|
||||
if (arg.name && (arg.val || !def->has_val)) {
|
||||
if (arg.name
|
||||
&& (arg.val || !def->has_val)) {
|
||||
arg.def = def;
|
||||
*arg_ = arg;
|
||||
return 1;
|
||||
@ -73,12 +80,15 @@ int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char *arg_next(struct arg *arg) {
|
||||
if (arg->argv[0]) arg->argv += arg->argv_step;
|
||||
if (arg->argv[0])
|
||||
arg->argv += arg->argv_step;
|
||||
|
||||
return *arg->argv;
|
||||
}
|
||||
|
||||
|
||||
char **argv_dup(int argc, const char **argv) {
|
||||
char **new_argv = malloc((argc + 1) * sizeof(*argv));
|
||||
|
||||
@ -87,8 +97,9 @@ char **argv_dup(int argc, const char **argv) {
|
||||
return new_argv;
|
||||
}
|
||||
|
||||
|
||||
void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
|
||||
char option_text[40] = { 0 };
|
||||
char option_text[40] = {0};
|
||||
|
||||
for (; *defs; defs++) {
|
||||
const struct arg_def *def = *defs;
|
||||
@ -98,12 +109,15 @@ void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
|
||||
if (def->short_name && def->long_name) {
|
||||
char *comma = def->has_val ? "," : ", ";
|
||||
|
||||
snprintf(option_text, 37, "-%s%s%s --%s%6s", def->short_name, short_val,
|
||||
comma, def->long_name, long_val);
|
||||
snprintf(option_text, 37, "-%s%s%s --%s%6s",
|
||||
def->short_name, short_val, comma,
|
||||
def->long_name, long_val);
|
||||
} else if (def->short_name)
|
||||
snprintf(option_text, 37, "-%s%s", def->short_name, short_val);
|
||||
snprintf(option_text, 37, "-%s%s",
|
||||
def->short_name, short_val);
|
||||
else if (def->long_name)
|
||||
snprintf(option_text, 37, " --%s%s", def->long_name, long_val);
|
||||
snprintf(option_text, 37, " --%s%s",
|
||||
def->long_name, long_val);
|
||||
|
||||
fprintf(fp, " %-37s\t%s\n", option_text, def->desc);
|
||||
|
||||
@ -113,103 +127,110 @@ void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
|
||||
fprintf(fp, " %-37s\t ", "");
|
||||
|
||||
for (listptr = def->enums; listptr->name; listptr++)
|
||||
fprintf(fp, "%s%s", listptr->name, listptr[1].name ? ", " : "\n");
|
||||
fprintf(fp, "%s%s", listptr->name,
|
||||
listptr[1].name ? ", " : "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int arg_parse_uint(const struct arg *arg) {
|
||||
uint32_t rawval;
|
||||
char *endptr;
|
||||
|
||||
rawval = (uint32_t)strtoul(arg->val, &endptr, 10);
|
||||
unsigned int arg_parse_uint(const struct arg *arg) {
|
||||
long int rawval;
|
||||
char *endptr;
|
||||
|
||||
rawval = strtol(arg->val, &endptr, 10);
|
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') {
|
||||
if (rawval <= UINT_MAX) return rawval;
|
||||
if (rawval >= 0 && rawval <= UINT_MAX)
|
||||
return rawval;
|
||||
|
||||
die("Option %s: Value %ld out of range for unsigned int\n", arg->name,
|
||||
rawval);
|
||||
die("Option %s: Value %ld out of range for unsigned int\n",
|
||||
arg->name, rawval);
|
||||
}
|
||||
|
||||
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int arg_parse_int(const struct arg *arg) {
|
||||
int32_t rawval;
|
||||
char *endptr;
|
||||
long int rawval;
|
||||
char *endptr;
|
||||
|
||||
rawval = (int32_t)strtol(arg->val, &endptr, 10);
|
||||
rawval = strtol(arg->val, &endptr, 10);
|
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') {
|
||||
if (rawval >= INT_MIN && rawval <= INT_MAX) return (int)rawval;
|
||||
if (rawval >= INT_MIN && rawval <= INT_MAX)
|
||||
return rawval;
|
||||
|
||||
die("Option %s: Value %ld out of range for signed int\n", arg->name,
|
||||
rawval);
|
||||
die("Option %s: Value %ld out of range for signed int\n",
|
||||
arg->name, rawval);
|
||||
}
|
||||
|
||||
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct vpx_rational {
|
||||
int num; /**< fraction numerator */
|
||||
int den; /**< fraction denominator */
|
||||
};
|
||||
struct vpx_rational arg_parse_rational(const struct arg *arg) {
|
||||
long int rawval;
|
||||
char *endptr;
|
||||
struct vpx_rational rat;
|
||||
long int rawval;
|
||||
char *endptr;
|
||||
struct vpx_rational rat;
|
||||
|
||||
/* parse numerator */
|
||||
rawval = strtol(arg->val, &endptr, 10);
|
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '/') {
|
||||
if (rawval >= INT_MIN && rawval <= INT_MAX)
|
||||
rat.num = (int)rawval;
|
||||
else
|
||||
die("Option %s: Value %ld out of range for signed int\n", arg->name,
|
||||
rawval);
|
||||
} else
|
||||
die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
|
||||
rat.num = rawval;
|
||||
else die("Option %s: Value %ld out of range for signed int\n",
|
||||
arg->name, rawval);
|
||||
} else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
|
||||
|
||||
/* parse denominator */
|
||||
rawval = strtol(endptr + 1, &endptr, 10);
|
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') {
|
||||
if (rawval >= INT_MIN && rawval <= INT_MAX)
|
||||
rat.den = (int)rawval;
|
||||
else
|
||||
die("Option %s: Value %ld out of range for signed int\n", arg->name,
|
||||
rawval);
|
||||
} else
|
||||
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
|
||||
rat.den = rawval;
|
||||
else die("Option %s: Value %ld out of range for signed int\n",
|
||||
arg->name, rawval);
|
||||
} else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
|
||||
|
||||
return rat;
|
||||
}
|
||||
|
||||
|
||||
int arg_parse_enum(const struct arg *arg) {
|
||||
const struct arg_enum_list *listptr;
|
||||
long int rawval;
|
||||
char *endptr;
|
||||
long int rawval;
|
||||
char *endptr;
|
||||
|
||||
/* First see if the value can be parsed as a raw value */
|
||||
rawval = strtol(arg->val, &endptr, 10);
|
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') {
|
||||
/* Got a raw value, make sure it's valid */
|
||||
for (listptr = arg->def->enums; listptr->name; listptr++)
|
||||
if (listptr->val == rawval) return (int)rawval;
|
||||
if (listptr->val == rawval)
|
||||
return rawval;
|
||||
}
|
||||
|
||||
/* Next see if it can be parsed as a string */
|
||||
for (listptr = arg->def->enums; listptr->name; listptr++)
|
||||
if (!strcmp(arg->val, listptr->name)) return listptr->val;
|
||||
if (!strcmp(arg->val, listptr->name))
|
||||
return listptr->val;
|
||||
|
||||
die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int arg_parse_enum_or_int(const struct arg *arg) {
|
||||
if (arg->def->enums) return arg_parse_enum(arg);
|
||||
if (arg->def->enums)
|
||||
return arg_parse_enum(arg);
|
||||
return arg_parse_int(arg);
|
||||
}
|
||||
|
27
args.h
27
args.h
@ -8,6 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ARGS_H_
|
||||
#define ARGS_H_
|
||||
#include <stdio.h>
|
||||
@ -17,33 +18,29 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct arg {
|
||||
char **argv;
|
||||
const char *name;
|
||||
const char *val;
|
||||
unsigned int argv_step;
|
||||
const struct arg_def *def;
|
||||
char **argv;
|
||||
const char *name;
|
||||
const char *val;
|
||||
unsigned int argv_step;
|
||||
const struct arg_def *def;
|
||||
};
|
||||
|
||||
struct arg_enum_list {
|
||||
const char *name;
|
||||
int val;
|
||||
int val;
|
||||
};
|
||||
#define ARG_ENUM_LIST_END \
|
||||
{ 0 }
|
||||
#define ARG_ENUM_LIST_END {0}
|
||||
|
||||
typedef struct arg_def {
|
||||
const char *short_name;
|
||||
const char *long_name;
|
||||
int has_val;
|
||||
int has_val;
|
||||
const char *desc;
|
||||
const struct arg_enum_list *enums;
|
||||
} arg_def_t;
|
||||
#define ARG_DEF(s, l, v, d) \
|
||||
{ s, l, v, d, NULL }
|
||||
#define ARG_DEF_ENUM(s, l, v, d, e) \
|
||||
{ s, l, v, d, e }
|
||||
#define ARG_DEF_LIST_END \
|
||||
{ 0 }
|
||||
#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL}
|
||||
#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e}
|
||||
#define ARG_DEF_LIST_END {0}
|
||||
|
||||
struct arg arg_init(char **argv);
|
||||
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
|
||||
|
2
build/.gitattributes
vendored
Normal file
2
build/.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*-vs8/*.rules -crlf
|
||||
*-msvs/*.rules -crlf
|
1
build/.gitignore
vendored
Normal file
1
build/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
x86*-win32-vs*
|
@ -29,6 +29,11 @@
|
||||
# include $(CLEAR_VARS)
|
||||
# include jni/libvpx/build/make/Android.mk
|
||||
#
|
||||
# There are currently two TARGET_ARCH_ABI targets for ARM.
|
||||
# armeabi and armeabi-v7a. armeabi-v7a is selected by creating an
|
||||
# Application.mk in the jni directory that contains:
|
||||
# APP_ABI := armeabi-v7a
|
||||
#
|
||||
# By default libvpx will detect at runtime the existance of NEON extension.
|
||||
# For this we import the 'cpufeatures' module from the NDK sources.
|
||||
# libvpx can also be configured without this runtime detection method.
|
||||
@ -37,44 +42,28 @@
|
||||
# --disable-neon-asm
|
||||
# will remove any NEON dependency.
|
||||
|
||||
# To change to building armeabi, run ./libvpx/configure again, but with
|
||||
# --target=armv6-android-gcc and modify the Application.mk file to
|
||||
# set APP_ABI := armeabi
|
||||
#
|
||||
# Running ndk-build will build libvpx and include it in your project.
|
||||
#
|
||||
|
||||
# Alternatively, building the examples and unit tests can be accomplished in the
|
||||
# following way:
|
||||
#
|
||||
# Create a standalone toolchain from the NDK:
|
||||
# https://developer.android.com/ndk/guides/standalone_toolchain.html
|
||||
#
|
||||
# For example - to test on arm64 devices with clang:
|
||||
# $NDK/build/tools/make_standalone_toolchain.py \
|
||||
# --arch arm64 --install-dir=/tmp/my-android-toolchain
|
||||
# export PATH=/tmp/my-android-toolchain/bin:$PATH
|
||||
# CROSS=aarch64-linux-android- CC=clang CXX=clang++ /path/to/libvpx/configure \
|
||||
# --target=arm64-android-gcc
|
||||
#
|
||||
# Push the resulting binaries to a device and run them:
|
||||
# adb push test_libvpx /data/tmp/test_libvpx
|
||||
# adb shell /data/tmp/test_libvpx --gtest_filter=\*Sixtap\*
|
||||
#
|
||||
# Make sure to push the test data as well and set LIBVPX_TEST_DATA
|
||||
|
||||
CONFIG_DIR := $(LOCAL_PATH)/
|
||||
LIBVPX_PATH := $(LOCAL_PATH)/libvpx
|
||||
ASM_CNV_PATH_LOCAL := $(TARGET_ARCH_ABI)/ads2gas
|
||||
ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL)
|
||||
ifneq ($(V),1)
|
||||
qexec := @
|
||||
endif
|
||||
|
||||
# Use the makefiles generated by upstream configure to determine which files to
|
||||
# build. Also set any architecture-specific flags.
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
include $(CONFIG_DIR)libs-armv7-android-gcc.mk
|
||||
LOCAL_ARM_MODE := arm
|
||||
else ifeq ($(TARGET_ARCH_ABI),armeabi)
|
||||
include $(CONFIG_DIR)libs-armv6-android-gcc.mk
|
||||
LOCAL_ARM_MODE := arm
|
||||
else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
|
||||
include $(CONFIG_DIR)libs-arm64-android-gcc.mk
|
||||
include $(CONFIG_DIR)libs-armv8-android-gcc.mk
|
||||
LOCAL_ARM_MODE := arm
|
||||
else ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
include $(CONFIG_DIR)libs-x86-android-gcc.mk
|
||||
@ -104,10 +93,10 @@ LOCAL_CFLAGS := -O3
|
||||
# like x86inc.asm and x86_abi_support.asm
|
||||
LOCAL_ASMFLAGS := -I$(LIBVPX_PATH)
|
||||
|
||||
.PRECIOUS: %.asm.S
|
||||
$(ASM_CNV_PATH)/libvpx/%.asm.S: $(LIBVPX_PATH)/%.asm
|
||||
$(qexec)mkdir -p $(dir $@)
|
||||
$(qexec)$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@
|
||||
.PRECIOUS: %.asm.s
|
||||
$(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm
|
||||
@mkdir -p $(dir $@)
|
||||
@$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@
|
||||
|
||||
# For building *_rtcd.h, which have rules in libs.mk
|
||||
TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
|
||||
@ -135,7 +124,7 @@ endif
|
||||
|
||||
# Pull out assembly files, splitting NEON from the rest. This is
|
||||
# done to specify that the NEON assembly files use NEON assembler flags.
|
||||
# x86 assembly matches %.asm, arm matches %.asm.S
|
||||
# x86 assembly matches %.asm, arm matches %.asm.s
|
||||
|
||||
# x86:
|
||||
|
||||
@ -143,44 +132,31 @@ CODEC_SRCS_ASM_X86 = $(filter %.asm, $(CODEC_SRCS_UNIQUE))
|
||||
LOCAL_SRC_FILES += $(foreach file, $(CODEC_SRCS_ASM_X86), libvpx/$(file))
|
||||
|
||||
# arm:
|
||||
CODEC_SRCS_ASM_ARM_ALL = $(filter %.asm.S, $(CODEC_SRCS_UNIQUE))
|
||||
CODEC_SRCS_ASM_ARM_ALL = $(filter %.asm.s, $(CODEC_SRCS_UNIQUE))
|
||||
CODEC_SRCS_ASM_ARM = $(foreach v, \
|
||||
$(CODEC_SRCS_ASM_ARM_ALL), \
|
||||
$(if $(findstring neon,$(v)),,$(v)))
|
||||
CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.S, \
|
||||
$(ASM_CNV_PATH_LOCAL)/libvpx/%.S, \
|
||||
CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.s, \
|
||||
$(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
|
||||
$(CODEC_SRCS_ASM_ARM))
|
||||
LOCAL_SRC_FILES += $(CODEC_SRCS_ASM_ADS2GAS)
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
ASM_INCLUDES := vpx_dsp/arm/idct_neon.asm.S
|
||||
CODEC_SRCS_ASM_NEON = $(foreach v, \
|
||||
$(CODEC_SRCS_ASM_ARM_ALL),\
|
||||
$(if $(findstring neon,$(v)),$(v),))
|
||||
CODEC_SRCS_ASM_NEON := $(filter-out $(addprefix %, $(ASM_INCLUDES)), \
|
||||
$(CODEC_SRCS_ASM_NEON))
|
||||
CODEC_SRCS_ASM_NEON_ADS2GAS = $(patsubst %.S, \
|
||||
$(ASM_CNV_PATH_LOCAL)/libvpx/%.S, \
|
||||
CODEC_SRCS_ASM_NEON_ADS2GAS = $(patsubst %.s, \
|
||||
$(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
|
||||
$(CODEC_SRCS_ASM_NEON))
|
||||
LOCAL_SRC_FILES += $(patsubst %.S, \
|
||||
%.S.neon, \
|
||||
LOCAL_SRC_FILES += $(patsubst %.s, \
|
||||
%.s.neon, \
|
||||
$(CODEC_SRCS_ASM_NEON_ADS2GAS))
|
||||
|
||||
NEON_ASM_TARGETS = $(patsubst %.S, \
|
||||
$(ASM_CNV_PATH)/libvpx/%.S, \
|
||||
$(CODEC_SRCS_ASM_NEON))
|
||||
# add a dependency to the full path to the ads2gas output to ensure the
|
||||
# includes are converted first.
|
||||
ifneq ($(strip $(NEON_ASM_TARGETS)),)
|
||||
$(NEON_ASM_TARGETS): $(addprefix $(ASM_CNV_PATH)/libvpx/, $(ASM_INCLUDES))
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += \
|
||||
-DHAVE_CONFIG_H=vpx_config.h \
|
||||
-I$(LIBVPX_PATH) \
|
||||
-I$(ASM_CNV_PATH) \
|
||||
-I$(ASM_CNV_PATH)/libvpx
|
||||
-I$(ASM_CNV_PATH)
|
||||
|
||||
LOCAL_MODULE := libvpx
|
||||
|
||||
@ -198,11 +174,13 @@ endif
|
||||
ifeq ($(CONFIG_VP9), yes)
|
||||
$$(rtcd_dep_template_SRCS): vp9_rtcd.h
|
||||
endif
|
||||
ifeq ($(CONFIG_VP10), yes)
|
||||
$$(rtcd_dep_template_SRCS): vp10_rtcd.h
|
||||
endif
|
||||
$$(rtcd_dep_template_SRCS): vpx_scale_rtcd.h
|
||||
$$(rtcd_dep_template_SRCS): vpx_dsp_rtcd.h
|
||||
|
||||
rtcd_dep_template_CONFIG_ASM_ABIS := x86 x86_64 armeabi-v7a
|
||||
ifneq ($$(findstring $(TARGET_ARCH_ABI),$$(rtcd_dep_template_CONFIG_ASM_ABIS)),)
|
||||
ifneq ($(findstring $(TARGET_ARCH_ABI),x86 x86_64),)
|
||||
$$(rtcd_dep_template_SRCS): vpx_config.asm
|
||||
endif
|
||||
endef
|
||||
@ -212,17 +190,16 @@ $(eval $(call rtcd_dep_template))
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@echo "Clean: ads2gas files [$(TARGET_ARCH_ABI)]"
|
||||
$(qexec)$(RM) $(CODEC_SRCS_ASM_ADS2GAS) $(CODEC_SRCS_ASM_NEON_ADS2GAS)
|
||||
$(qexec)$(RM) -r $(ASM_CNV_PATH)
|
||||
$(qexec)$(RM) $(CLEAN-OBJS)
|
||||
@$(RM) $(CODEC_SRCS_ASM_ADS2GAS) $(CODEC_SRCS_ASM_NEON_ADS2GAS)
|
||||
@$(RM) -r $(ASM_CNV_PATH)
|
||||
@$(RM) $(CLEAN-OBJS)
|
||||
|
||||
ifeq ($(ENABLE_SHARED),1)
|
||||
LOCAL_CFLAGS += -fPIC
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
else
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
|
||||
$(call import-module,android/cpufeatures)
|
||||
$(call import-module,cpufeatures)
|
||||
endif
|
||||
|
@ -26,7 +26,7 @@ test-no-data-check:: .DEFAULT
|
||||
testdata:: .DEFAULT
|
||||
utiltest: .DEFAULT
|
||||
exampletest-no-data-check utiltest-no-data-check: .DEFAULT
|
||||
test_%: .DEFAULT ;
|
||||
|
||||
|
||||
# Note: md5sum is not installed on OS X, but openssl is. Openssl may not be
|
||||
# installed on cygwin, so we need to autodetect here.
|
||||
@ -90,7 +90,7 @@ all:
|
||||
|
||||
.PHONY: clean
|
||||
clean::
|
||||
rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.S.o=.asm.S)
|
||||
rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.s.o=.asm.s)
|
||||
rm -f $(CLEAN-OBJS)
|
||||
|
||||
.PHONY: clean
|
||||
@ -119,32 +119,29 @@ utiltest:
|
||||
test-no-data-check::
|
||||
exampletest-no-data-check utiltest-no-data-check:
|
||||
|
||||
# Force to realign stack always on OS/2
|
||||
# Add compiler flags for intrinsic files
|
||||
ifeq ($(TOOLCHAIN), x86-os2-gcc)
|
||||
CFLAGS += -mstackrealign
|
||||
STACKREALIGN=-mstackrealign
|
||||
else
|
||||
STACKREALIGN=
|
||||
endif
|
||||
|
||||
# x86[_64]
|
||||
$(BUILD_PFX)%_mmx.c.d: CFLAGS += -mmmx
|
||||
$(BUILD_PFX)%_mmx.c.o: CFLAGS += -mmmx
|
||||
$(BUILD_PFX)%_sse2.c.d: CFLAGS += -msse2
|
||||
$(BUILD_PFX)%_sse2.c.o: CFLAGS += -msse2
|
||||
$(BUILD_PFX)%_sse3.c.d: CFLAGS += -msse3
|
||||
$(BUILD_PFX)%_sse3.c.o: CFLAGS += -msse3
|
||||
$(BUILD_PFX)%_ssse3.c.d: CFLAGS += -mssse3
|
||||
$(BUILD_PFX)%_ssse3.c.o: CFLAGS += -mssse3
|
||||
$(BUILD_PFX)%_sse4.c.d: CFLAGS += -msse4.1
|
||||
$(BUILD_PFX)%_sse4.c.o: CFLAGS += -msse4.1
|
||||
$(BUILD_PFX)%_avx.c.d: CFLAGS += -mavx
|
||||
$(BUILD_PFX)%_avx.c.o: CFLAGS += -mavx
|
||||
$(BUILD_PFX)%_avx2.c.d: CFLAGS += -mavx2
|
||||
$(BUILD_PFX)%_avx2.c.o: CFLAGS += -mavx2
|
||||
$(BUILD_PFX)%_avx512.c.d: CFLAGS += -mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl
|
||||
$(BUILD_PFX)%_avx512.c.o: CFLAGS += -mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl
|
||||
|
||||
# POWER
|
||||
$(BUILD_PFX)%_vsx.c.d: CFLAGS += -maltivec -mvsx
|
||||
$(BUILD_PFX)%_vsx.c.o: CFLAGS += -maltivec -mvsx
|
||||
$(BUILD_PFX)%_sse2.c.d: CFLAGS += -msse2 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_sse2.c.o: CFLAGS += -msse2 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_sse3.c.d: CFLAGS += -msse3 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_sse3.c.o: CFLAGS += -msse3 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_ssse3.c.d: CFLAGS += -mssse3 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_ssse3.c.o: CFLAGS += -mssse3 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_sse4.c.d: CFLAGS += -msse4.1 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_sse4.c.o: CFLAGS += -msse4.1 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_avx.c.d: CFLAGS += -mavx $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_avx.c.o: CFLAGS += -mavx $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_avx2.c.d: CFLAGS += -mavx2 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%_avx2.c.o: CFLAGS += -mavx2 $(STACKREALIGN)
|
||||
$(BUILD_PFX)%vp9_reconintra.c.d: CFLAGS += $(STACKREALIGN)
|
||||
$(BUILD_PFX)%vp9_reconintra.c.o: CFLAGS += $(STACKREALIGN)
|
||||
|
||||
$(BUILD_PFX)%.c.d: %.c
|
||||
$(if $(quiet),@echo " [DEP] $@")
|
||||
@ -187,13 +184,13 @@ $(BUILD_PFX)%.asm.o: %.asm
|
||||
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
|
||||
$(qexec)$(AS) $(ASFLAGS) -o $@ $<
|
||||
|
||||
$(BUILD_PFX)%.S.d: %.S
|
||||
$(BUILD_PFX)%.s.d: %.s
|
||||
$(if $(quiet),@echo " [DEP] $@")
|
||||
$(qexec)mkdir -p $(dir $@)
|
||||
$(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
|
||||
--build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
|
||||
|
||||
$(BUILD_PFX)%.S.o: %.S
|
||||
$(BUILD_PFX)%.s.o: %.s
|
||||
$(if $(quiet),@echo " [AS] $@")
|
||||
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
|
||||
$(qexec)$(AS) $(ASFLAGS) -o $@ $<
|
||||
@ -205,8 +202,8 @@ $(BUILD_PFX)%.c.S: %.c
|
||||
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
|
||||
$(qexec)$(CC) -S $(CFLAGS) -o $@ $<
|
||||
|
||||
.PRECIOUS: %.asm.S
|
||||
$(BUILD_PFX)%.asm.S: %.asm
|
||||
.PRECIOUS: %.asm.s
|
||||
$(BUILD_PFX)%.asm.s: %.asm
|
||||
$(if $(quiet),@echo " [ASM CONVERSION] $@")
|
||||
$(qexec)mkdir -p $(dir $@)
|
||||
$(qexec)$(ASM_CONVERSION) <$< >$@
|
||||
@ -425,6 +422,7 @@ ifneq ($(call enabled,DIST-SRCS),)
|
||||
DIST-SRCS-yes += build/make/gen_asm_deps.sh
|
||||
DIST-SRCS-yes += build/make/Makefile
|
||||
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_def.sh
|
||||
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_proj.sh
|
||||
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_sln.sh
|
||||
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_vcxproj.sh
|
||||
DIST-SRCS-$(CONFIG_MSVS) += build/make/msvs_common.sh
|
||||
@ -455,5 +453,3 @@ all: $(BUILD_TARGETS)
|
||||
install:: $(INSTALL_TARGETS)
|
||||
dist: $(INSTALL_TARGETS)
|
||||
test::
|
||||
|
||||
.SUFFIXES: # Delete default suffix rules
|
||||
|
@ -23,11 +23,9 @@ use lib $FindBin::Bin;
|
||||
use thumb;
|
||||
|
||||
my $thumb = 0;
|
||||
my $elf = 1;
|
||||
|
||||
foreach my $arg (@ARGV) {
|
||||
$thumb = 1 if ($arg eq "-thumb");
|
||||
$elf = 0 if ($arg eq "-noelf");
|
||||
}
|
||||
|
||||
print "@ This file was created from a .asm file\n";
|
||||
@ -140,13 +138,17 @@ while (<STDIN>)
|
||||
s/DCD(.*)/.long $1/;
|
||||
s/DCB(.*)/.byte $1/;
|
||||
|
||||
# RN to .req
|
||||
if (s/RN\s+([Rr]\d+|lr)/.req $1/)
|
||||
{
|
||||
print;
|
||||
print "$comment_sub$comment\n" if defined $comment;
|
||||
next;
|
||||
}
|
||||
|
||||
# Make function visible to linker, and make additional symbol with
|
||||
# prepended underscore
|
||||
if ($elf) {
|
||||
s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
|
||||
} else {
|
||||
s/EXPORT\s+\|([\$\w]*)\|/.global $1/;
|
||||
}
|
||||
s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
|
||||
s/IMPORT\s+\|([\$\w]*)\|/.global $1/;
|
||||
|
||||
s/EXPORT\s+([\$\w]*)/.global $1/;
|
||||
@ -187,16 +189,11 @@ while (<STDIN>)
|
||||
# eabi_attributes numerical equivalents can be found in the
|
||||
# "ARM IHI 0045C" document.
|
||||
|
||||
if ($elf) {
|
||||
# REQUIRE8 Stack is required to be 8-byte aligned
|
||||
s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
|
||||
# REQUIRE8 Stack is required to be 8-byte aligned
|
||||
s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
|
||||
|
||||
# PRESERVE8 Stack 8-byte align is preserved
|
||||
s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
|
||||
} else {
|
||||
s/\sREQUIRE8//;
|
||||
s/\sPRESERVE8//;
|
||||
}
|
||||
# PRESERVE8 Stack 8-byte align is preserved
|
||||
s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
|
||||
|
||||
# Use PROC and ENDP to give the symbols a .size directive.
|
||||
# This makes them show up properly in debugging tools like gdb and valgrind.
|
||||
@ -213,7 +210,7 @@ while (<STDIN>)
|
||||
my $proc;
|
||||
s/\bENDP\b/@ $&/;
|
||||
$proc = pop(@proc_stack);
|
||||
$_ = "\t.size $proc, .-$proc".$_ if ($proc and $elf);
|
||||
$_ = "\t.size $proc, .-$proc".$_ if ($proc);
|
||||
}
|
||||
|
||||
# EQU directive
|
||||
@ -236,4 +233,4 @@ while (<STDIN>)
|
||||
}
|
||||
|
||||
# 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");
|
||||
|
@ -18,6 +18,12 @@
|
||||
# Usage: cat inputfile | perl ads2gas_apple.pl > outputfile
|
||||
#
|
||||
|
||||
my $chromium = 0;
|
||||
|
||||
foreach my $arg (@ARGV) {
|
||||
$chromium = 1 if ($arg eq "-chromium");
|
||||
}
|
||||
|
||||
print "@ This file was created from a .asm file\n";
|
||||
print "@ using the ads2gas_apple.pl script.\n\n";
|
||||
print "\t.set WIDE_REFERENCE, 0\n";
|
||||
@ -120,6 +126,18 @@ while (<STDIN>)
|
||||
s/DCD(.*)/.long $1/;
|
||||
s/DCB(.*)/.byte $1/;
|
||||
|
||||
# Build a hash of all the register - alias pairs.
|
||||
if (s/(.*)RN(.*)/$1 .req $2/g)
|
||||
{
|
||||
$register_aliases{trim($1)} = trim($2);
|
||||
next;
|
||||
}
|
||||
|
||||
while (($key, $value) = each(%register_aliases))
|
||||
{
|
||||
s/\b$key\b/$value/g;
|
||||
}
|
||||
|
||||
# Make function visible to linker, and make additional symbol with
|
||||
# prepended underscore
|
||||
s/EXPORT\s+\|([\$\w]*)\|/.globl _$1\n\t.globl $1/;
|
||||
@ -200,5 +218,18 @@ while (<STDIN>)
|
||||
s/\bMEND\b/.endm/; # No need to tell it where to stop assembling
|
||||
next if /^\s*END\s*$/;
|
||||
|
||||
# Clang used by Chromium differs slightly from clang in XCode in what it
|
||||
# will accept in the assembly.
|
||||
if ($chromium) {
|
||||
s/qsubaddx/qsax/i;
|
||||
s/qaddsubx/qasx/i;
|
||||
s/ldrneb/ldrbne/i;
|
||||
s/ldrneh/ldrhne/i;
|
||||
s/(vqshrun\.s16 .*, \#)0$/${1}8/i;
|
||||
|
||||
# http://llvm.org/bugs/show_bug.cgi?id=16022
|
||||
s/\.include/#include/;
|
||||
}
|
||||
|
||||
print;
|
||||
}
|
||||
|
@ -185,7 +185,6 @@ add_extralibs() {
|
||||
#
|
||||
# Boolean Manipulation Functions
|
||||
#
|
||||
|
||||
enable_feature(){
|
||||
set_all yes $*
|
||||
}
|
||||
@ -202,20 +201,6 @@ disabled(){
|
||||
eval test "x\$$1" = "xno"
|
||||
}
|
||||
|
||||
enable_codec(){
|
||||
enabled "${1}" || echo " enabling ${1}"
|
||||
enable_feature "${1}"
|
||||
|
||||
is_in "${1}" vp8 vp9 && enable_feature "${1}_encoder" "${1}_decoder"
|
||||
}
|
||||
|
||||
disable_codec(){
|
||||
disabled "${1}" || echo " disabling ${1}"
|
||||
disable_feature "${1}"
|
||||
|
||||
is_in "${1}" vp8 vp9 && disable_feature "${1}_encoder" "${1}_decoder"
|
||||
}
|
||||
|
||||
# Iterates through positional parameters, checks to confirm the parameter has
|
||||
# not been explicitly (force) disabled, and enables the setting controlled by
|
||||
# the parameter when the setting is not disabled.
|
||||
@ -403,23 +388,6 @@ check_gcc_machine_option() {
|
||||
fi
|
||||
}
|
||||
|
||||
# tests for -m$2, -m$3, -m$4... toggling the feature given in $1.
|
||||
check_gcc_machine_options() {
|
||||
feature="$1"
|
||||
shift
|
||||
flags="-m$1"
|
||||
shift
|
||||
for opt in $*; do
|
||||
flags="$flags -m$opt"
|
||||
done
|
||||
|
||||
if enabled gcc && ! disabled "$feature" && ! check_cflags $flags; then
|
||||
RTCD_OPTIONS="${RTCD_OPTIONS}--disable-$feature "
|
||||
else
|
||||
soft_enable "$feature"
|
||||
fi
|
||||
}
|
||||
|
||||
write_common_config_banner() {
|
||||
print_webm_license config.mk "##" ""
|
||||
echo '# This file automatically generated by configure. Do not edit!' >> config.mk
|
||||
@ -553,20 +521,22 @@ process_common_cmdline() {
|
||||
;;
|
||||
--enable-?*|--disable-?*)
|
||||
eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
|
||||
if is_in ${option} ${ARCH_EXT_LIST}; then
|
||||
if echo "${ARCH_EXT_LIST}" | grep "^ *$option\$" >/dev/null; then
|
||||
[ $action = "disable" ] && RTCD_OPTIONS="${RTCD_OPTIONS}--disable-${option} "
|
||||
elif [ $action = "disable" ] && ! disabled $option ; then
|
||||
is_in ${option} ${CMDLINE_SELECT} || die_unknown $opt
|
||||
echo "${CMDLINE_SELECT}" | grep "^ *$option\$" >/dev/null ||
|
||||
die_unknown $opt
|
||||
log_echo " disabling $option"
|
||||
elif [ $action = "enable" ] && ! enabled $option ; then
|
||||
is_in ${option} ${CMDLINE_SELECT} || die_unknown $opt
|
||||
echo "${CMDLINE_SELECT}" | grep "^ *$option\$" >/dev/null ||
|
||||
die_unknown $opt
|
||||
log_echo " enabling $option"
|
||||
fi
|
||||
${action}_feature $option
|
||||
;;
|
||||
--require-?*)
|
||||
eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
|
||||
if is_in ${option} ${ARCH_EXT_LIST}; then
|
||||
if echo "${ARCH_EXT_LIST}" none | grep "^ *$option\$" >/dev/null; then
|
||||
RTCD_OPTIONS="${RTCD_OPTIONS}${opt} "
|
||||
else
|
||||
die_unknown $opt
|
||||
@ -652,7 +622,7 @@ setup_gnu_toolchain() {
|
||||
AS=${AS:-${CROSS}as}
|
||||
STRIP=${STRIP:-${CROSS}strip}
|
||||
NM=${NM:-${CROSS}nm}
|
||||
AS_SFX=.S
|
||||
AS_SFX=.s
|
||||
EXE_SFX=
|
||||
}
|
||||
|
||||
@ -668,34 +638,18 @@ show_darwin_sdk_major_version() {
|
||||
xcrun --sdk $1 --show-sdk-version 2>/dev/null | cut -d. -f1
|
||||
}
|
||||
|
||||
# Print the Xcode version.
|
||||
show_xcode_version() {
|
||||
xcodebuild -version | head -n1 | cut -d' ' -f2
|
||||
}
|
||||
|
||||
# Fails when Xcode version is less than 6.3.
|
||||
check_xcode_minimum_version() {
|
||||
xcode_major=$(show_xcode_version | cut -f1 -d.)
|
||||
xcode_minor=$(show_xcode_version | cut -f2 -d.)
|
||||
xcode_min_major=6
|
||||
xcode_min_minor=3
|
||||
if [ ${xcode_major} -lt ${xcode_min_major} ]; then
|
||||
return 1
|
||||
fi
|
||||
if [ ${xcode_major} -eq ${xcode_min_major} ] \
|
||||
&& [ ${xcode_minor} -lt ${xcode_min_minor} ]; then
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
process_common_toolchain() {
|
||||
if [ -z "$toolchain" ]; then
|
||||
gcctarget="${CHOST:-$(gcc -dumpmachine 2> /dev/null)}"
|
||||
|
||||
# detect tgt_isa
|
||||
case "$gcctarget" in
|
||||
aarch64*)
|
||||
tgt_isa=arm64
|
||||
;;
|
||||
armv6*)
|
||||
tgt_isa=armv6
|
||||
;;
|
||||
armv7*-hardfloat* | armv7*-gnueabihf | arm-*-gnueabihf)
|
||||
tgt_isa=armv7
|
||||
float_abi=hard
|
||||
@ -713,18 +667,6 @@ process_common_toolchain() {
|
||||
*sparc*)
|
||||
tgt_isa=sparc
|
||||
;;
|
||||
power*64*-*)
|
||||
tgt_isa=ppc64
|
||||
;;
|
||||
power*)
|
||||
tgt_isa=ppc
|
||||
;;
|
||||
*mips64el*)
|
||||
tgt_isa=mips64
|
||||
;;
|
||||
*mips32el*)
|
||||
tgt_isa=mips32
|
||||
;;
|
||||
esac
|
||||
|
||||
# detect tgt_os
|
||||
@ -753,20 +695,9 @@ process_common_toolchain() {
|
||||
tgt_isa=x86_64
|
||||
tgt_os=darwin15
|
||||
;;
|
||||
*darwin16*)
|
||||
tgt_isa=x86_64
|
||||
tgt_os=darwin16
|
||||
;;
|
||||
*darwin17*)
|
||||
tgt_isa=x86_64
|
||||
tgt_os=darwin17
|
||||
;;
|
||||
x86_64*mingw32*)
|
||||
tgt_os=win64
|
||||
;;
|
||||
x86_64*cygwin*)
|
||||
tgt_os=win64
|
||||
;;
|
||||
*mingw32*|*cygwin*)
|
||||
[ -z "$tgt_isa" ] && tgt_isa=x86
|
||||
tgt_os=win32
|
||||
@ -814,23 +745,13 @@ process_common_toolchain() {
|
||||
mips*)
|
||||
enable_feature mips
|
||||
;;
|
||||
ppc*)
|
||||
enable_feature ppc
|
||||
;;
|
||||
esac
|
||||
|
||||
# PIC is probably what we want when building shared libs
|
||||
enabled shared && soft_enable pic
|
||||
|
||||
# Minimum iOS version for all target platforms (darwin and iphonesimulator).
|
||||
# Shared library framework builds are only possible on iOS 8 and later.
|
||||
if enabled shared; then
|
||||
IOS_VERSION_OPTIONS="--enable-shared"
|
||||
IOS_VERSION_MIN="8.0"
|
||||
else
|
||||
IOS_VERSION_OPTIONS=""
|
||||
IOS_VERSION_MIN="6.0"
|
||||
fi
|
||||
IOS_VERSION_MIN="6.0"
|
||||
|
||||
# Handle darwin variants. Newer SDKs allow targeting older
|
||||
# platforms, so use the newest one available.
|
||||
@ -885,14 +806,6 @@ process_common_toolchain() {
|
||||
add_cflags "-mmacosx-version-min=10.11"
|
||||
add_ldflags "-mmacosx-version-min=10.11"
|
||||
;;
|
||||
*-darwin16-*)
|
||||
add_cflags "-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-*)
|
||||
add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}"
|
||||
add_ldflags "-miphoneos-version-min=${IOS_VERSION_MIN}"
|
||||
@ -930,6 +843,36 @@ process_common_toolchain() {
|
||||
if disabled neon && enabled neon_asm; then
|
||||
die "Disabling neon while keeping neon-asm is not supported"
|
||||
fi
|
||||
case ${toolchain} in
|
||||
# Apple iOS SDKs no longer support armv6 as of the version 9
|
||||
# release (coincides with release of Xcode 7). Only enable media
|
||||
# when using earlier SDK releases.
|
||||
*-darwin*)
|
||||
if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then
|
||||
soft_enable media
|
||||
else
|
||||
soft_disable media
|
||||
RTCD_OPTIONS="${RTCD_OPTIONS}--disable-media "
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
soft_enable media
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
armv6)
|
||||
case ${toolchain} in
|
||||
*-darwin*)
|
||||
if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then
|
||||
soft_enable media
|
||||
else
|
||||
die "Your iOS SDK does not support armv6."
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
soft_enable media
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -941,6 +884,7 @@ process_common_toolchain() {
|
||||
setup_gnu_toolchain
|
||||
arch_int=${tgt_isa##armv}
|
||||
arch_int=${arch_int%%te}
|
||||
check_add_asflags --defsym ARCHITECTURE=${arch_int}
|
||||
tune_cflags="-mtune="
|
||||
if [ ${tgt_isa} = "armv7" ] || [ ${tgt_isa} = "armv7s" ]; then
|
||||
if [ -z "${float_abi}" ]; then
|
||||
@ -957,9 +901,6 @@ EOF
|
||||
check_add_cflags -mfpu=neon #-ftree-vectorize
|
||||
check_add_asflags -mfpu=neon
|
||||
fi
|
||||
elif [ ${tgt_isa} = "arm64" ] || [ ${tgt_isa} = "armv8" ]; then
|
||||
check_add_cflags -march=armv8-a
|
||||
check_add_asflags -march=armv8-a
|
||||
else
|
||||
check_add_cflags -march=${tgt_isa}
|
||||
check_add_asflags -march=${tgt_isa}
|
||||
@ -967,19 +908,6 @@ EOF
|
||||
|
||||
enabled debug && add_asflags -g
|
||||
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
|
||||
asm_conversion_cmd="$asm_conversion_cmd -thumb"
|
||||
check_add_cflags -mthumb
|
||||
@ -988,7 +916,7 @@ EOF
|
||||
;;
|
||||
vs*)
|
||||
asm_conversion_cmd="${source_path}/build/make/ads2armasm_ms.pl"
|
||||
AS_SFX=.S
|
||||
AS_SFX=.s
|
||||
msvs_arch_dir=arm-msvs
|
||||
disable_feature multithread
|
||||
disable_feature unit_tests
|
||||
@ -998,7 +926,6 @@ EOF
|
||||
# only "AppContainerApplication" which requires an AppxManifest.
|
||||
# Therefore disable the examples, just build the library.
|
||||
disable_feature examples
|
||||
disable_feature tools
|
||||
fi
|
||||
;;
|
||||
rvct)
|
||||
@ -1041,50 +968,43 @@ EOF
|
||||
;;
|
||||
|
||||
android*)
|
||||
if [ -n "${sdk_path}" ]; then
|
||||
SDK_PATH=${sdk_path}
|
||||
COMPILER_LOCATION=`find "${SDK_PATH}" \
|
||||
-name "arm-linux-androideabi-gcc*" -print -quit`
|
||||
TOOLCHAIN_PATH=${COMPILER_LOCATION%/*}/arm-linux-androideabi-
|
||||
CC=${TOOLCHAIN_PATH}gcc
|
||||
CXX=${TOOLCHAIN_PATH}g++
|
||||
AR=${TOOLCHAIN_PATH}ar
|
||||
LD=${TOOLCHAIN_PATH}gcc
|
||||
AS=${TOOLCHAIN_PATH}as
|
||||
STRIP=${TOOLCHAIN_PATH}strip
|
||||
NM=${TOOLCHAIN_PATH}nm
|
||||
SDK_PATH=${sdk_path}
|
||||
COMPILER_LOCATION=`find "${SDK_PATH}" \
|
||||
-name "arm-linux-androideabi-gcc*" -print -quit`
|
||||
TOOLCHAIN_PATH=${COMPILER_LOCATION%/*}/arm-linux-androideabi-
|
||||
CC=${TOOLCHAIN_PATH}gcc
|
||||
CXX=${TOOLCHAIN_PATH}g++
|
||||
AR=${TOOLCHAIN_PATH}ar
|
||||
LD=${TOOLCHAIN_PATH}gcc
|
||||
AS=${TOOLCHAIN_PATH}as
|
||||
STRIP=${TOOLCHAIN_PATH}strip
|
||||
NM=${TOOLCHAIN_PATH}nm
|
||||
|
||||
if [ -z "${alt_libc}" ]; then
|
||||
alt_libc=`find "${SDK_PATH}" -name arch-arm -print | \
|
||||
awk '{n = split($0,a,"/"); \
|
||||
if [ -z "${alt_libc}" ]; then
|
||||
alt_libc=`find "${SDK_PATH}" -name arch-arm -print | \
|
||||
awk '{n = split($0,a,"/"); \
|
||||
split(a[n-1],b,"-"); \
|
||||
print $0 " " b[2]}' | \
|
||||
sort -g -k 2 | \
|
||||
awk '{ print $1 }' | tail -1`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d "${alt_libc}" ]; then
|
||||
add_cflags "--sysroot=${alt_libc}"
|
||||
add_ldflags "--sysroot=${alt_libc}"
|
||||
fi
|
||||
if [ -d "${alt_libc}" ]; then
|
||||
add_cflags "--sysroot=${alt_libc}"
|
||||
add_ldflags "--sysroot=${alt_libc}"
|
||||
fi
|
||||
|
||||
# linker flag that routes around a CPU bug in some
|
||||
# Cortex-A8 implementations (NDK Dev Guide)
|
||||
add_ldflags "-Wl,--fix-cortex-a8"
|
||||
# linker flag that routes around a CPU bug in some
|
||||
# Cortex-A8 implementations (NDK Dev Guide)
|
||||
add_ldflags "-Wl,--fix-cortex-a8"
|
||||
|
||||
enable_feature pic
|
||||
soft_enable realtime_only
|
||||
if [ ${tgt_isa} = "armv7" ]; then
|
||||
soft_enable runtime_cpu_detect
|
||||
fi
|
||||
if enabled runtime_cpu_detect; then
|
||||
add_cflags "-I${SDK_PATH}/sources/android/cpufeatures"
|
||||
fi
|
||||
else
|
||||
echo "Assuming standalone build with NDK toolchain."
|
||||
echo "See build/make/Android.mk for details."
|
||||
check_add_ldflags -static
|
||||
soft_enable unit_tests
|
||||
enable_feature pic
|
||||
soft_enable realtime_only
|
||||
if [ ${tgt_isa} = "armv7" ]; then
|
||||
soft_enable runtime_cpu_detect
|
||||
fi
|
||||
if enabled runtime_cpu_detect; then
|
||||
add_cflags "-I${SDK_PATH}/sources/android/cpufeatures"
|
||||
fi
|
||||
;;
|
||||
|
||||
@ -1097,7 +1017,7 @@ EOF
|
||||
STRIP="$(${XCRUN_FIND} strip)"
|
||||
NM="$(${XCRUN_FIND} nm)"
|
||||
RANLIB="$(${XCRUN_FIND} ranlib)"
|
||||
AS_SFX=.S
|
||||
AS_SFX=.s
|
||||
LD="${CXX:-$(${XCRUN_FIND} ld)}"
|
||||
|
||||
# ASFLAGS is written here instead of using check_add_asflags
|
||||
@ -1124,19 +1044,6 @@ EOF
|
||||
[ -d "${try_dir}" ] && add_ldflags -L"${try_dir}"
|
||||
done
|
||||
|
||||
case ${tgt_isa} in
|
||||
armv7|armv7s|armv8|arm64)
|
||||
if enabled neon && ! check_xcode_minimum_version; then
|
||||
soft_disable neon
|
||||
log_echo " neon disabled: upgrade Xcode (need v6.3+)."
|
||||
if enabled neon_asm; then
|
||||
soft_disable neon_asm
|
||||
log_echo " neon_asm disabled: upgrade Xcode (need v6.3+)."
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
asm_conversion_cmd="${source_path}/build/make/ads2gas_apple.pl"
|
||||
|
||||
if [ "$(show_darwin_sdk_major_version iphoneos)" -gt 8 ]; then
|
||||
@ -1186,13 +1093,13 @@ EOF
|
||||
if [ -n "${tune_cpu}" ]; then
|
||||
case ${tune_cpu} in
|
||||
p5600)
|
||||
check_add_cflags -mips32r5 -mload-store-pairs
|
||||
check_add_cflags -mips32r5 -funroll-loops -mload-store-pairs
|
||||
check_add_cflags -msched-weight -mhard-float -mfp64
|
||||
check_add_asflags -mips32r5 -mhard-float -mfp64
|
||||
check_add_ldflags -mfp64
|
||||
;;
|
||||
i6400|p6600)
|
||||
check_add_cflags -mips64r6 -mabi=64 -msched-weight
|
||||
i6400)
|
||||
check_add_cflags -mips64r6 -mabi=64 -funroll-loops -msched-weight
|
||||
check_add_cflags -mload-store-pairs -mhard-float -mfp64
|
||||
check_add_asflags -mips64r6 -mabi=64 -mhard-float -mfp64
|
||||
check_add_ldflags -mips64r6 -mabi=64 -mfp64
|
||||
@ -1206,25 +1113,12 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
if enabled mmi; then
|
||||
tgt_isa=loongson3a
|
||||
check_add_ldflags -march=loongson3a
|
||||
fi
|
||||
|
||||
check_add_cflags -march=${tgt_isa}
|
||||
check_add_asflags -march=${tgt_isa}
|
||||
check_add_asflags -KPIC
|
||||
;;
|
||||
ppc*)
|
||||
link_with_cc=gcc
|
||||
setup_gnu_toolchain
|
||||
check_gcc_machine_option "vsx"
|
||||
;;
|
||||
x86*)
|
||||
case ${tgt_os} in
|
||||
android)
|
||||
soft_enable realtime_only
|
||||
;;
|
||||
win*)
|
||||
enabled gcc && add_cflags -fno-common
|
||||
;;
|
||||
@ -1277,13 +1171,6 @@ EOF
|
||||
AS=msvs
|
||||
msvs_arch_dir=x86-msvs
|
||||
vc_version=${tgt_cc##vs}
|
||||
case $vc_version in
|
||||
7|8|9|10|11|12|13|14)
|
||||
echo "${tgt_cc} does not support avx512, disabling....."
|
||||
RTCD_OPTIONS="${RTCD_OPTIONS}--disable-avx512 "
|
||||
soft_disable avx512
|
||||
;;
|
||||
esac
|
||||
case $vc_version in
|
||||
7|8|9|10)
|
||||
echo "${tgt_cc} does not support avx/avx2, disabling....."
|
||||
@ -1328,12 +1215,8 @@ EOF
|
||||
elif disabled $ext; then
|
||||
disable_exts="yes"
|
||||
else
|
||||
if [ "$ext" = "avx512" ]; then
|
||||
check_gcc_machine_options $ext avx512f avx512cd avx512bw avx512dq avx512vl
|
||||
else
|
||||
# use the shortened version for the flag: sse4_1 -> sse4
|
||||
check_gcc_machine_option ${ext%_*} $ext
|
||||
fi
|
||||
# use the shortened version for the flag: sse4_1 -> sse4
|
||||
check_gcc_machine_option ${ext%_*} $ext
|
||||
fi
|
||||
done
|
||||
|
||||
@ -1359,6 +1242,7 @@ EOF
|
||||
esac
|
||||
log_echo " using $AS"
|
||||
fi
|
||||
[ "${AS##*/}" = nasm ] && add_asflags -Ox
|
||||
AS_SFX=.asm
|
||||
case ${tgt_os} in
|
||||
win32)
|
||||
@ -1367,7 +1251,7 @@ EOF
|
||||
EXE_SFX=.exe
|
||||
;;
|
||||
win64)
|
||||
add_asflags -f win64
|
||||
add_asflags -f x64
|
||||
enabled debug && add_asflags -g cv8
|
||||
EXE_SFX=.exe
|
||||
;;
|
||||
@ -1394,8 +1278,7 @@ EOF
|
||||
add_cflags ${sim_arch}
|
||||
add_ldflags ${sim_arch}
|
||||
|
||||
if [ "$(disabled external_build)" ] &&
|
||||
[ "$(show_darwin_sdk_major_version iphonesimulator)" -gt 8 ]; then
|
||||
if [ "$(show_darwin_sdk_major_version iphonesimulator)" -gt 8 ]; then
|
||||
# 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
|
||||
# do nothing here.
|
||||
@ -1453,6 +1336,10 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${tgt_isa}" = "x86_64" ] || [ "${tgt_isa}" = "x86" ]; then
|
||||
soft_enable use_x86inc
|
||||
fi
|
||||
|
||||
# Position Independent Code (PIC) support, for building relocatable
|
||||
# shared objects
|
||||
enabled gcc && enabled pic && check_add_cflags -fPIC
|
||||
@ -1482,7 +1369,6 @@ EOF
|
||||
*-win*-vs*)
|
||||
;;
|
||||
*-android-gcc)
|
||||
# bionic includes basic pthread functionality, obviating -lpthread.
|
||||
;;
|
||||
*)
|
||||
check_header pthread.h && add_extralibs -lpthread
|
||||
@ -1502,10 +1388,6 @@ EOF
|
||||
echo "msa optimizations are available only for little endian platforms"
|
||||
disable_feature msa
|
||||
fi
|
||||
if enabled mmi; then
|
||||
echo "mmi optimizations are available only for little endian platforms"
|
||||
disable_feature mmi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
490
build/make/gen_msvs_proj.sh
Executable file
490
build/make/gen_msvs_proj.sh
Executable file
@ -0,0 +1,490 @@
|
||||
#!/bin/bash
|
||||
##
|
||||
## Copyright (c) 2010 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.
|
||||
##
|
||||
|
||||
self=$0
|
||||
self_basename=${self##*/}
|
||||
self_dirname=$(dirname "$0")
|
||||
|
||||
. "$self_dirname/msvs_common.sh"|| exit 127
|
||||
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
|
||||
|
||||
This script generates a Visual Studio project file from a list of source
|
||||
code files.
|
||||
|
||||
Options:
|
||||
--help Print this message
|
||||
--exe Generate a project for building an Application
|
||||
--lib Generate a project for creating a static library
|
||||
--dll Generate a project for creating a dll
|
||||
--static-crt Use the static C runtime (/MT)
|
||||
--target=isa-os-cc Target specifier (required)
|
||||
--out=filename Write output to a file [stdout]
|
||||
--name=project_name Name of the project (required)
|
||||
--proj-guid=GUID GUID to use for the project
|
||||
--module-def=filename File containing export definitions (for DLLs)
|
||||
--ver=version Version (7,8,9) of visual studio to generate for
|
||||
--src-path-bare=dir Path to root of source tree
|
||||
-Ipath/to/include Additional include directories
|
||||
-DFLAG[=value] Preprocessor macros to define
|
||||
-Lpath/to/lib Additional library search paths
|
||||
-llibname Library to link against
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
generate_filter() {
|
||||
local var=$1
|
||||
local name=$2
|
||||
local pats=$3
|
||||
local file_list_sz
|
||||
local i
|
||||
local f
|
||||
local saveIFS="$IFS"
|
||||
local pack
|
||||
echo "generating filter '$name' from ${#file_list[@]} files" >&2
|
||||
IFS=*
|
||||
|
||||
open_tag Filter \
|
||||
Name=$name \
|
||||
Filter=$pats \
|
||||
UniqueIdentifier=`generate_uuid` \
|
||||
|
||||
file_list_sz=${#file_list[@]}
|
||||
for i in ${!file_list[@]}; do
|
||||
f=${file_list[i]}
|
||||
for pat in ${pats//;/$IFS}; do
|
||||
if [ "${f##*.}" == "$pat" ]; then
|
||||
unset file_list[i]
|
||||
|
||||
objf=$(echo ${f%.*}.obj \
|
||||
| sed -e "s,$src_path_bare,," \
|
||||
-e 's/^[\./]\+//g' -e 's,[:/ ],_,g')
|
||||
open_tag File RelativePath="$f"
|
||||
|
||||
if [ "$pat" == "asm" ] && $asm_use_custom_step; then
|
||||
# Avoid object file name collisions, i.e. vpx_config.c and
|
||||
# vpx_config.asm produce the same object file without
|
||||
# this additional suffix.
|
||||
objf=${objf%.obj}_asm.obj
|
||||
for plat in "${platforms[@]}"; do
|
||||
for cfg in Debug Release; do
|
||||
open_tag FileConfiguration \
|
||||
Name="${cfg}|${plat}" \
|
||||
|
||||
tag Tool \
|
||||
Name="VCCustomBuildTool" \
|
||||
Description="Assembling \$(InputFileName)" \
|
||||
CommandLine="$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)\\$objf" \
|
||||
Outputs="\$(IntDir)\\$objf" \
|
||||
|
||||
close_tag FileConfiguration
|
||||
done
|
||||
done
|
||||
fi
|
||||
if [ "$pat" == "c" ] || \
|
||||
[ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then
|
||||
for plat in "${platforms[@]}"; do
|
||||
for cfg in Debug Release; do
|
||||
open_tag FileConfiguration \
|
||||
Name="${cfg}|${plat}" \
|
||||
|
||||
tag Tool \
|
||||
Name="VCCLCompilerTool" \
|
||||
ObjectFile="\$(IntDir)\\$objf" \
|
||||
|
||||
close_tag FileConfiguration
|
||||
done
|
||||
done
|
||||
fi
|
||||
close_tag File
|
||||
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
close_tag Filter
|
||||
IFS="$saveIFS"
|
||||
}
|
||||
|
||||
# Process command line
|
||||
unset target
|
||||
for opt in "$@"; do
|
||||
optval="${opt#*=}"
|
||||
case "$opt" in
|
||||
--help|-h) show_help
|
||||
;;
|
||||
--target=*) target="${optval}"
|
||||
;;
|
||||
--out=*) outfile="$optval"
|
||||
;;
|
||||
--name=*) name="${optval}"
|
||||
;;
|
||||
--proj-guid=*) guid="${optval}"
|
||||
;;
|
||||
--module-def=*) link_opts="${link_opts} ModuleDefinitionFile=${optval}"
|
||||
;;
|
||||
--exe) proj_kind="exe"
|
||||
;;
|
||||
--dll) proj_kind="dll"
|
||||
;;
|
||||
--lib) proj_kind="lib"
|
||||
;;
|
||||
--src-path-bare=*)
|
||||
src_path_bare=$(fix_path "$optval")
|
||||
src_path_bare=${src_path_bare%/}
|
||||
;;
|
||||
--static-crt) use_static_runtime=true
|
||||
;;
|
||||
--ver=*)
|
||||
vs_ver="$optval"
|
||||
case "$optval" in
|
||||
[789])
|
||||
;;
|
||||
*) die Unrecognized Visual Studio Version in $opt
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I*)
|
||||
opt=${opt##-I}
|
||||
opt=$(fix_path "$opt")
|
||||
opt="${opt%/}"
|
||||
incs="${incs}${incs:+;}"${opt}""
|
||||
yasmincs="${yasmincs} -I"${opt}""
|
||||
;;
|
||||
-D*) defines="${defines}${defines:+;}${opt##-D}"
|
||||
;;
|
||||
-L*) # fudge . to $(OutDir)
|
||||
if [ "${opt##-L}" == "." ]; then
|
||||
libdirs="${libdirs}${libdirs:+;}"\$(OutDir)""
|
||||
else
|
||||
# Also try directories for this platform/configuration
|
||||
opt=${opt##-L}
|
||||
opt=$(fix_path "$opt")
|
||||
libdirs="${libdirs}${libdirs:+;}"${opt}""
|
||||
libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)/\$(ConfigurationName)""
|
||||
libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)""
|
||||
fi
|
||||
;;
|
||||
-l*) libs="${libs}${libs:+ }${opt##-l}.lib"
|
||||
;;
|
||||
-*) die_unknown $opt
|
||||
;;
|
||||
*)
|
||||
# The paths in file_list are fixed outside of the loop.
|
||||
file_list[${#file_list[@]}]="$opt"
|
||||
case "$opt" in
|
||||
*.asm) uses_asm=true
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Make one call to fix_path for file_list to improve performance.
|
||||
fix_file_list file_list
|
||||
|
||||
outfile=${outfile:-/dev/stdout}
|
||||
guid=${guid:-`generate_uuid`}
|
||||
asm_use_custom_step=false
|
||||
uses_asm=${uses_asm:-false}
|
||||
case "${vs_ver:-8}" in
|
||||
7) vs_ver_id="7.10"
|
||||
asm_use_custom_step=$uses_asm
|
||||
warn_64bit='Detect64BitPortabilityProblems=true'
|
||||
;;
|
||||
8) vs_ver_id="8.00"
|
||||
asm_use_custom_step=$uses_asm
|
||||
warn_64bit='Detect64BitPortabilityProblems=true'
|
||||
;;
|
||||
9) vs_ver_id="9.00"
|
||||
asm_use_custom_step=$uses_asm
|
||||
warn_64bit='Detect64BitPortabilityProblems=false'
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -n "$name" ] || die "Project name (--name) must be specified!"
|
||||
[ -n "$target" ] || die "Target (--target) must be specified!"
|
||||
|
||||
if ${use_static_runtime:-false}; then
|
||||
release_runtime=0
|
||||
debug_runtime=1
|
||||
lib_sfx=mt
|
||||
else
|
||||
release_runtime=2
|
||||
debug_runtime=3
|
||||
lib_sfx=md
|
||||
fi
|
||||
|
||||
# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
|
||||
# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
|
||||
# debug exe, so this may need to be refactored later.
|
||||
for lib in ${libs}; do
|
||||
if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
|
||||
lib=${lib%.lib}d.lib
|
||||
fi
|
||||
debug_libs="${debug_libs}${debug_libs:+ }${lib}"
|
||||
done
|
||||
|
||||
|
||||
# List Keyword for this target
|
||||
case "$target" in
|
||||
x86*) keyword="ManagedCProj"
|
||||
;;
|
||||
*) die "Unsupported target $target!"
|
||||
esac
|
||||
|
||||
# List of all platforms supported for this target
|
||||
case "$target" in
|
||||
x86_64*)
|
||||
platforms[0]="x64"
|
||||
asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} "\$(InputPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} "\$(InputPath)""
|
||||
;;
|
||||
x86*)
|
||||
platforms[0]="Win32"
|
||||
asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} "\$(InputPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} "\$(InputPath)""
|
||||
;;
|
||||
*) die "Unsupported target $target!"
|
||||
;;
|
||||
esac
|
||||
|
||||
generate_vcproj() {
|
||||
case "$proj_kind" in
|
||||
exe) vs_ConfigurationType=1
|
||||
;;
|
||||
dll) vs_ConfigurationType=2
|
||||
;;
|
||||
*) vs_ConfigurationType=4
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
|
||||
open_tag VisualStudioProject \
|
||||
ProjectType="Visual C++" \
|
||||
Version="${vs_ver_id}" \
|
||||
Name="${name}" \
|
||||
ProjectGUID="{${guid}}" \
|
||||
RootNamespace="${name}" \
|
||||
Keyword="${keyword}" \
|
||||
|
||||
open_tag Platforms
|
||||
for plat in "${platforms[@]}"; do
|
||||
tag Platform Name="$plat"
|
||||
done
|
||||
close_tag Platforms
|
||||
|
||||
open_tag Configurations
|
||||
for plat in "${platforms[@]}"; do
|
||||
plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
|
||||
open_tag Configuration \
|
||||
Name="Debug|$plat" \
|
||||
OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
|
||||
IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
|
||||
ConfigurationType="$vs_ConfigurationType" \
|
||||
CharacterSet="1" \
|
||||
|
||||
case "$target" in
|
||||
x86*)
|
||||
case "$name" in
|
||||
vpx)
|
||||
tag Tool \
|
||||
Name="VCCLCompilerTool" \
|
||||
Optimization="0" \
|
||||
AdditionalIncludeDirectories="$incs" \
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
|
||||
RuntimeLibrary="$debug_runtime" \
|
||||
UsePrecompiledHeader="0" \
|
||||
WarningLevel="3" \
|
||||
DebugInformationFormat="2" \
|
||||
$warn_64bit \
|
||||
|
||||
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="true"
|
||||
;;
|
||||
*)
|
||||
tag Tool \
|
||||
Name="VCCLCompilerTool" \
|
||||
Optimization="0" \
|
||||
AdditionalIncludeDirectories="$incs" \
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
|
||||
RuntimeLibrary="$debug_runtime" \
|
||||
UsePrecompiledHeader="0" \
|
||||
WarningLevel="3" \
|
||||
DebugInformationFormat="2" \
|
||||
$warn_64bit \
|
||||
|
||||
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="true"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$proj_kind" in
|
||||
exe)
|
||||
case "$target" in
|
||||
x86*)
|
||||
case "$name" in
|
||||
*)
|
||||
tag Tool \
|
||||
Name="VCLinkerTool" \
|
||||
AdditionalDependencies="$debug_libs \$(NoInherit)" \
|
||||
AdditionalLibraryDirectories="$libdirs" \
|
||||
GenerateDebugInformation="true" \
|
||||
ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
lib)
|
||||
case "$target" in
|
||||
x86*)
|
||||
tag Tool \
|
||||
Name="VCLibrarianTool" \
|
||||
OutputFile="\$(OutDir)/${name}${lib_sfx}d.lib" \
|
||||
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
dll)
|
||||
tag Tool \
|
||||
Name="VCLinkerTool" \
|
||||
AdditionalDependencies="\$(NoInherit)" \
|
||||
LinkIncremental="2" \
|
||||
GenerateDebugInformation="true" \
|
||||
AssemblyDebug="1" \
|
||||
TargetMachine="1" \
|
||||
$link_opts \
|
||||
|
||||
;;
|
||||
esac
|
||||
|
||||
close_tag Configuration
|
||||
|
||||
open_tag Configuration \
|
||||
Name="Release|$plat" \
|
||||
OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
|
||||
IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
|
||||
ConfigurationType="$vs_ConfigurationType" \
|
||||
CharacterSet="1" \
|
||||
WholeProgramOptimization="0" \
|
||||
|
||||
case "$target" in
|
||||
x86*)
|
||||
case "$name" in
|
||||
vpx)
|
||||
tag Tool \
|
||||
Name="VCCLCompilerTool" \
|
||||
Optimization="2" \
|
||||
FavorSizeorSpeed="1" \
|
||||
AdditionalIncludeDirectories="$incs" \
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
|
||||
RuntimeLibrary="$release_runtime" \
|
||||
UsePrecompiledHeader="0" \
|
||||
WarningLevel="3" \
|
||||
DebugInformationFormat="0" \
|
||||
$warn_64bit \
|
||||
|
||||
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs"
|
||||
;;
|
||||
*)
|
||||
tag Tool \
|
||||
Name="VCCLCompilerTool" \
|
||||
AdditionalIncludeDirectories="$incs" \
|
||||
Optimization="2" \
|
||||
FavorSizeorSpeed="1" \
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
|
||||
RuntimeLibrary="$release_runtime" \
|
||||
UsePrecompiledHeader="0" \
|
||||
WarningLevel="3" \
|
||||
DebugInformationFormat="0" \
|
||||
$warn_64bit \
|
||||
|
||||
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$proj_kind" in
|
||||
exe)
|
||||
case "$target" in
|
||||
x86*)
|
||||
case "$name" in
|
||||
*)
|
||||
tag Tool \
|
||||
Name="VCLinkerTool" \
|
||||
AdditionalDependencies="$libs \$(NoInherit)" \
|
||||
AdditionalLibraryDirectories="$libdirs" \
|
||||
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
lib)
|
||||
case "$target" in
|
||||
x86*)
|
||||
tag Tool \
|
||||
Name="VCLibrarianTool" \
|
||||
OutputFile="\$(OutDir)/${name}${lib_sfx}.lib" \
|
||||
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
dll) # note differences to debug version: LinkIncremental, AssemblyDebug
|
||||
tag Tool \
|
||||
Name="VCLinkerTool" \
|
||||
AdditionalDependencies="\$(NoInherit)" \
|
||||
LinkIncremental="1" \
|
||||
GenerateDebugInformation="true" \
|
||||
TargetMachine="1" \
|
||||
$link_opts \
|
||||
|
||||
;;
|
||||
esac
|
||||
|
||||
close_tag Configuration
|
||||
done
|
||||
close_tag Configurations
|
||||
|
||||
open_tag Files
|
||||
generate_filter srcs "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx"
|
||||
generate_filter hdrs "Header Files" "h;hm;inl;inc;xsd"
|
||||
generate_filter resrcs "Resource Files" "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
generate_filter resrcs "Build Files" "mk"
|
||||
close_tag Files
|
||||
|
||||
tag Globals
|
||||
close_tag VisualStudioProject
|
||||
|
||||
# This must be done from within the {} subshell
|
||||
echo "Ignored files list (${#file_list[@]} items) is:" >&2
|
||||
for f in "${file_list[@]}"; do
|
||||
echo " $f" >&2
|
||||
done
|
||||
}
|
||||
|
||||
generate_vcproj |
|
||||
sed -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile}
|
||||
|
||||
exit
|
||||
<!--
|
||||
TODO: Add any files not captured by filters.
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
-->
|
@ -25,7 +25,7 @@ files.
|
||||
Options:
|
||||
--help Print this message
|
||||
--out=outfile Redirect output to a file
|
||||
--ver=version Version (7,8,9,10,11,12,14,15) of visual studio to generate for
|
||||
--ver=version Version (7,8,9,10,11,12,14) of visual studio to generate for
|
||||
--target=isa-os-cc Target specifier
|
||||
EOF
|
||||
exit 1
|
||||
@ -55,11 +55,16 @@ indent_pop() {
|
||||
|
||||
parse_project() {
|
||||
local file=$1
|
||||
local name=`grep RootNamespace "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
|
||||
local guid=`grep ProjectGuid "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
|
||||
if [ "$sfx" = "vcproj" ]; then
|
||||
local name=`grep Name "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
|
||||
local guid=`grep ProjectGUID "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
|
||||
else
|
||||
local name=`grep RootNamespace "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
|
||||
local guid=`grep ProjectGuid "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
|
||||
fi
|
||||
|
||||
# save the project GUID to a varaible, normalizing to the basename of the
|
||||
# vcxproj file without the extension
|
||||
# vcproj file without the extension
|
||||
local var
|
||||
var=${file##*/}
|
||||
var=${var%%.${sfx}}
|
||||
@ -67,8 +72,13 @@ parse_project() {
|
||||
eval "${var}_name=$name"
|
||||
eval "${var}_guid=$guid"
|
||||
|
||||
cur_config_list=`grep -B1 'Label="Configuration"' $file |
|
||||
grep Condition | cut -d\' -f4`
|
||||
if [ "$sfx" = "vcproj" ]; then
|
||||
cur_config_list=`grep -A1 '<Configuration' $file |
|
||||
grep Name | cut -d\" -f2`
|
||||
else
|
||||
cur_config_list=`grep -B1 'Label="Configuration"' $file |
|
||||
grep Condition | cut -d\' -f4`
|
||||
fi
|
||||
new_config_list=$(for i in $config_list $cur_config_list; do
|
||||
echo $i
|
||||
done | sort | uniq)
|
||||
@ -93,6 +103,25 @@ process_project() {
|
||||
eval "${var}_guid=$guid"
|
||||
|
||||
echo "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$name\", \"$file\", \"$guid\""
|
||||
indent_push
|
||||
|
||||
eval "local deps=\"\${${var}_deps}\""
|
||||
if [ -n "$deps" ] && [ "$sfx" = "vcproj" ]; then
|
||||
echo "${indent}ProjectSection(ProjectDependencies) = postProject"
|
||||
indent_push
|
||||
|
||||
for dep in $deps; do
|
||||
eval "local dep_guid=\${${dep}_guid}"
|
||||
[ -z "${dep_guid}" ] && die "Unknown GUID for $dep (dependency of $var)"
|
||||
echo "${indent}$dep_guid = $dep_guid"
|
||||
done
|
||||
|
||||
indent_pop
|
||||
echo "${indent}EndProjectSection"
|
||||
|
||||
fi
|
||||
|
||||
indent_pop
|
||||
echo "EndProject"
|
||||
}
|
||||
|
||||
@ -162,7 +191,11 @@ process_makefile() {
|
||||
IFS=$'\r'$'\n'
|
||||
local TAB=$'\t'
|
||||
cat <<EOF
|
||||
ifeq (\$(CONFIG_VS_VERSION),7)
|
||||
MSBUILD_TOOL := devenv.com
|
||||
else
|
||||
MSBUILD_TOOL := msbuild.exe
|
||||
endif
|
||||
found_devenv := \$(shell which \$(MSBUILD_TOOL) >/dev/null 2>&1 && echo yes)
|
||||
.nodevenv.once:
|
||||
${TAB}@echo " * \$(MSBUILD_TOOL) not found in path."
|
||||
@ -171,7 +204,7 @@ ${TAB}@echo " * You will have to build all configurations manually using the"
|
||||
${TAB}@echo " * Visual Studio IDE. To allow make to build them automatically,"
|
||||
${TAB}@echo " * add the Common7/IDE directory of your Visual Studio"
|
||||
${TAB}@echo " * installation to your path, eg:"
|
||||
${TAB}@echo " * C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE"
|
||||
${TAB}@echo " * C:\Program Files\Microsoft Visual Studio 8\Common7\IDE"
|
||||
${TAB}@echo " * "
|
||||
${TAB}@touch \$@
|
||||
CLEAN-OBJS += \$(if \$(found_devenv),,.nodevenv.once)
|
||||
@ -188,9 +221,16 @@ clean::
|
||||
${TAB}rm -rf "$platform"/"$config"
|
||||
.PHONY: $nows_sln_config
|
||||
ifneq (\$(found_devenv),)
|
||||
ifeq (\$(CONFIG_VS_VERSION),7)
|
||||
$nows_sln_config: $outfile
|
||||
${TAB}\$(MSBUILD_TOOL) $outfile -build "$config"
|
||||
|
||||
else
|
||||
$nows_sln_config: $outfile
|
||||
${TAB}\$(MSBUILD_TOOL) $outfile -m -t:Build \\
|
||||
${TAB}${TAB}-p:Configuration="$config" -p:Platform="$platform"
|
||||
|
||||
endif
|
||||
else
|
||||
$nows_sln_config: $outfile .nodevenv.once
|
||||
${TAB}@echo " * Skipping build of $sln_config (\$(MSBUILD_TOOL) not in path)."
|
||||
@ -215,12 +255,23 @@ for opt in "$@"; do
|
||||
;;
|
||||
--ver=*) vs_ver="$optval"
|
||||
case $optval in
|
||||
10|11|12|14|15)
|
||||
[789]|10|11|12|14)
|
||||
;;
|
||||
*) die Unrecognized Visual Studio Version in $opt
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
--ver=*) vs_ver="$optval"
|
||||
case $optval in
|
||||
7) sln_vers="8.00"
|
||||
sln_vers_str="Visual Studio .NET 2003"
|
||||
;;
|
||||
[89])
|
||||
;;
|
||||
*) die "Unrecognized Visual Studio Version '$optval' in $opt"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
--target=*) target="${optval}"
|
||||
;;
|
||||
-*) die_unknown $opt
|
||||
@ -230,7 +281,16 @@ for opt in "$@"; do
|
||||
done
|
||||
outfile=${outfile:-/dev/stdout}
|
||||
mkoutfile=${mkoutfile:-/dev/stdout}
|
||||
case "${vs_ver:-10}" in
|
||||
case "${vs_ver:-8}" in
|
||||
7) sln_vers="8.00"
|
||||
sln_vers_str="Visual Studio .NET 2003"
|
||||
;;
|
||||
8) sln_vers="9.00"
|
||||
sln_vers_str="Visual Studio 2005"
|
||||
;;
|
||||
9) sln_vers="10.00"
|
||||
sln_vers_str="Visual Studio 2008"
|
||||
;;
|
||||
10) sln_vers="11.00"
|
||||
sln_vers_str="Visual Studio 2010"
|
||||
;;
|
||||
@ -240,14 +300,18 @@ case "${vs_ver:-10}" in
|
||||
12) sln_vers="12.00"
|
||||
sln_vers_str="Visual Studio 2013"
|
||||
;;
|
||||
14) sln_vers="12.00"
|
||||
14) sln_vers="14.00"
|
||||
sln_vers_str="Visual Studio 2015"
|
||||
;;
|
||||
15) sln_vers="12.00"
|
||||
sln_vers_str="Visual Studio 2017"
|
||||
esac
|
||||
case "${vs_ver:-8}" in
|
||||
[789])
|
||||
sfx=vcproj
|
||||
;;
|
||||
10|11|12|14)
|
||||
sfx=vcxproj
|
||||
;;
|
||||
esac
|
||||
sfx=vcxproj
|
||||
|
||||
for f in "${file_list[@]}"; do
|
||||
parse_project $f
|
||||
|
@ -34,7 +34,7 @@ Options:
|
||||
--name=project_name Name of the project (required)
|
||||
--proj-guid=GUID GUID to use for the project
|
||||
--module-def=filename File containing export definitions (for DLLs)
|
||||
--ver=version Version (10,11,12,14,15) of visual studio to generate for
|
||||
--ver=version Version (10,11,12,14) of visual studio to generate for
|
||||
--src-path-bare=dir Path to root of source tree
|
||||
-Ipath/to/include Additional include directories
|
||||
-DFLAG[=value] Preprocessor macros to define
|
||||
@ -82,7 +82,7 @@ generate_filter() {
|
||||
| sed -e "s,$src_path_bare,," \
|
||||
-e 's/^[\./]\+//g' -e 's,[:/ ],_,g')
|
||||
|
||||
if ([ "$pat" == "asm" ] || [ "$pat" == "s" ] || [ "$pat" == "S" ]) && $asm_use_custom_step; then
|
||||
if ([ "$pat" == "asm" ] || [ "$pat" == "s" ]) && $asm_use_custom_step; then
|
||||
# Avoid object file name collisions, i.e. vpx_config.c and
|
||||
# vpx_config.asm produce the same object file without
|
||||
# this additional suffix.
|
||||
@ -168,7 +168,7 @@ for opt in "$@"; do
|
||||
--ver=*)
|
||||
vs_ver="$optval"
|
||||
case "$optval" in
|
||||
10|11|12|14|15)
|
||||
10|11|12|14)
|
||||
;;
|
||||
*) die Unrecognized Visual Studio Version in $opt
|
||||
;;
|
||||
@ -203,7 +203,7 @@ for opt in "$@"; do
|
||||
# The paths in file_list are fixed outside of the loop.
|
||||
file_list[${#file_list[@]}]="$opt"
|
||||
case "$opt" in
|
||||
*.asm|*.[Ss]) uses_asm=true
|
||||
*.asm|*.s) uses_asm=true
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
@ -218,7 +218,7 @@ guid=${guid:-`generate_uuid`}
|
||||
asm_use_custom_step=false
|
||||
uses_asm=${uses_asm:-false}
|
||||
case "${vs_ver:-11}" in
|
||||
10|11|12|14|15)
|
||||
10|11|12|14)
|
||||
asm_use_custom_step=$uses_asm
|
||||
;;
|
||||
esac
|
||||
@ -347,9 +347,6 @@ generate_vcxproj() {
|
||||
if [ "$vs_ver" = "14" ]; then
|
||||
tag_content PlatformToolset v140
|
||||
fi
|
||||
if [ "$vs_ver" = "15" ]; then
|
||||
tag_content PlatformToolset v141
|
||||
fi
|
||||
tag_content CharacterSet Unicode
|
||||
if [ "$config" = "Release" ]; then
|
||||
tag_content WholeProgramOptimization true
|
||||
@ -455,7 +452,7 @@ generate_vcxproj() {
|
||||
done
|
||||
|
||||
open_tag ItemGroup
|
||||
generate_filter "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s;S"
|
||||
generate_filter "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s"
|
||||
close_tag ItemGroup
|
||||
open_tag ItemGroup
|
||||
generate_filter "Header Files" "h;hm;inl;inc;xsd"
|
||||
|
@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>VPX</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.webmproject.VPX</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>VPX</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${VERSION}</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${VERSION}</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>${IOS_VERSION_MIN}</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>VPXFullVersion</key>
|
||||
<string>${FULLVERSION}</string>
|
||||
</dict>
|
||||
</plist>
|
@ -35,8 +35,8 @@ ARM_TARGETS="arm64-darwin-gcc
|
||||
armv7s-darwin-gcc"
|
||||
SIM_TARGETS="x86-iphonesimulator-gcc
|
||||
x86_64-iphonesimulator-gcc"
|
||||
OSX_TARGETS="x86-darwin16-gcc
|
||||
x86_64-darwin16-gcc"
|
||||
OSX_TARGETS="x86-darwin15-gcc
|
||||
x86_64-darwin15-gcc"
|
||||
TARGETS="${ARM_TARGETS} ${SIM_TARGETS}"
|
||||
|
||||
# Configures for the target specified by $1, and invokes make with the dist
|
||||
@ -196,12 +196,7 @@ build_framework() {
|
||||
for target in ${targets}; do
|
||||
build_target "${target}"
|
||||
target_dist_dir="${BUILD_ROOT}/${target}/${DIST_DIR}"
|
||||
if [ "${ENABLE_SHARED}" = "yes" ]; then
|
||||
local suffix="dylib"
|
||||
else
|
||||
local suffix="a"
|
||||
fi
|
||||
lib_list="${lib_list} ${target_dist_dir}/lib/libvpx.${suffix}"
|
||||
lib_list="${lib_list} ${target_dist_dir}/lib/libvpx.a"
|
||||
done
|
||||
|
||||
cd "${ORIG_PWD}"
|
||||
@ -220,18 +215,6 @@ build_framework() {
|
||||
# Copy in vpx_version.h.
|
||||
cp -p "${BUILD_ROOT}/${target}/vpx_version.h" "${HEADER_DIR}"
|
||||
|
||||
if [ "${ENABLE_SHARED}" = "yes" ]; then
|
||||
# Adjust the dylib's name so dynamic linking in apps works as expected.
|
||||
install_name_tool -id '@rpath/VPX.framework/VPX' ${FRAMEWORK_DIR}/VPX
|
||||
|
||||
# Copy in Info.plist.
|
||||
cat "${SCRIPT_DIR}/ios-Info.plist" \
|
||||
| sed "s/\${FULLVERSION}/${FULLVERSION}/g" \
|
||||
| sed "s/\${VERSION}/${VERSION}/g" \
|
||||
| sed "s/\${IOS_VERSION_MIN}/${IOS_VERSION_MIN}/g" \
|
||||
> "${FRAMEWORK_DIR}/Info.plist"
|
||||
fi
|
||||
|
||||
# Confirm VPX.framework/VPX contains the targets requested.
|
||||
verify_framework_targets ${targets}
|
||||
|
||||
@ -269,9 +252,8 @@ iosbuild_usage() {
|
||||
cat << EOF
|
||||
Usage: ${0##*/} [arguments]
|
||||
--help: Display this message and exit.
|
||||
--enable-shared: Build a dynamic framework for use on iOS 8 or later.
|
||||
--extra-configure-args <args>: Extra args to pass when configuring libvpx.
|
||||
--macosx: Uses darwin16 targets instead of iphonesimulator targets for x86
|
||||
--macosx: Uses darwin15 targets instead of iphonesimulator targets for x86
|
||||
and x86_64. Allows linking to framework when builds target MacOSX
|
||||
instead of iOS.
|
||||
--preserve-build-output: Do not delete the build directory.
|
||||
@ -308,9 +290,6 @@ while [ -n "$1" ]; do
|
||||
iosbuild_usage
|
||||
exit
|
||||
;;
|
||||
--enable-shared)
|
||||
ENABLE_SHARED=yes
|
||||
;;
|
||||
--preserve-build-output)
|
||||
PRESERVE_BUILD_OUTPUT=yes
|
||||
;;
|
||||
@ -338,21 +317,6 @@ while [ -n "$1" ]; do
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "${ENABLE_SHARED}" = "yes" ]; then
|
||||
CONFIGURE_ARGS="--enable-shared ${CONFIGURE_ARGS}"
|
||||
fi
|
||||
|
||||
FULLVERSION=$("${SCRIPT_DIR}"/version.sh --bare "${LIBVPX_SOURCE_DIR}")
|
||||
VERSION=$(echo "${FULLVERSION}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+).*$/\1/')
|
||||
|
||||
if [ "$ENABLE_SHARED" = "yes" ]; then
|
||||
IOS_VERSION_OPTIONS="--enable-shared"
|
||||
IOS_VERSION_MIN="8.0"
|
||||
else
|
||||
IOS_VERSION_OPTIONS=""
|
||||
IOS_VERSION_MIN="6.0"
|
||||
fi
|
||||
|
||||
if [ "${VERBOSE}" = "yes" ]; then
|
||||
cat << EOF
|
||||
BUILD_ROOT=${BUILD_ROOT}
|
||||
@ -368,13 +332,8 @@ cat << EOF
|
||||
ORIG_PWD=${ORIG_PWD}
|
||||
PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT}
|
||||
TARGETS="$(print_list "" ${TARGETS})"
|
||||
ENABLE_SHARED=${ENABLE_SHARED}
|
||||
OSX_TARGETS="${OSX_TARGETS}"
|
||||
SIM_TARGETS="${SIM_TARGETS}"
|
||||
SCRIPT_DIR="${SCRIPT_DIR}"
|
||||
FULLVERSION="${FULLVERSION}"
|
||||
VERSION="${VERSION}"
|
||||
IOS_VERSION_MIN="${IOS_VERSION_MIN}"
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
@ -41,15 +41,6 @@ fix_path() {
|
||||
# Corrects the paths in file_list in one pass for efficiency.
|
||||
# $1 is the name of the array to be modified.
|
||||
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
|
||||
files=$(fix_path "${array_ref[@]}")
|
||||
local IFS=$'\n'
|
||||
|
@ -1,13 +1,4 @@
|
||||
#!/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';
|
||||
use warnings;
|
||||
@ -209,7 +200,6 @@ sub filter {
|
||||
sub common_top() {
|
||||
my $include_guard = uc($opts{sym})."_H_";
|
||||
print <<EOF;
|
||||
// This file is generated. Do not edit.
|
||||
#ifndef ${include_guard}
|
||||
#define ${include_guard}
|
||||
|
||||
@ -345,36 +335,6 @@ EOF
|
||||
common_bottom;
|
||||
}
|
||||
|
||||
sub ppc() {
|
||||
determine_indirection("c", @ALL_ARCHS);
|
||||
|
||||
# Assign the helper variable for each enabled extension
|
||||
foreach my $opt (@ALL_ARCHS) {
|
||||
my $opt_uc = uc $opt;
|
||||
eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
|
||||
}
|
||||
|
||||
common_top;
|
||||
print <<EOF;
|
||||
#include "vpx_config.h"
|
||||
|
||||
#ifdef RTCD_C
|
||||
#include "vpx_ports/ppc.h"
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
int flags = ppc_simd_caps();
|
||||
(void)flags;
|
||||
EOF
|
||||
|
||||
set_function_pointers("c", @ALL_ARCHS);
|
||||
|
||||
print <<EOF;
|
||||
}
|
||||
#endif
|
||||
EOF
|
||||
common_bottom;
|
||||
}
|
||||
|
||||
sub unoptimized() {
|
||||
determine_indirection "c";
|
||||
common_top;
|
||||
@ -401,10 +361,10 @@ EOF
|
||||
|
||||
&require("c");
|
||||
if ($opts{arch} eq 'x86') {
|
||||
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2 avx512/);
|
||||
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/);
|
||||
x86;
|
||||
} elsif ($opts{arch} eq 'x86_64') {
|
||||
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2 avx512/);
|
||||
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/);
|
||||
@REQUIRES = filter(keys %required ? keys %required : qw/mmx sse sse2/);
|
||||
&require(@REQUIRES);
|
||||
x86;
|
||||
@ -421,22 +381,20 @@ if ($opts{arch} eq 'x86') {
|
||||
@ALL_ARCHS = filter("$opts{arch}", qw/msa/);
|
||||
last;
|
||||
}
|
||||
if (/HAVE_MMI=yes/) {
|
||||
@ALL_ARCHS = filter("$opts{arch}", qw/mmi/);
|
||||
last;
|
||||
}
|
||||
}
|
||||
close CONFIG_FILE;
|
||||
mips;
|
||||
} elsif ($opts{arch} eq 'armv6') {
|
||||
@ALL_ARCHS = filter(qw/media/);
|
||||
arm;
|
||||
} elsif ($opts{arch} =~ /armv7\w?/) {
|
||||
@ALL_ARCHS = filter(qw/neon_asm neon/);
|
||||
@ALL_ARCHS = filter(qw/media neon_asm neon/);
|
||||
@REQUIRES = filter(keys %required ? keys %required : qw/media/);
|
||||
&require(@REQUIRES);
|
||||
arm;
|
||||
} elsif ($opts{arch} eq 'armv8' || $opts{arch} eq 'arm64' ) {
|
||||
@ALL_ARCHS = filter(qw/neon/);
|
||||
arm;
|
||||
} elsif ($opts{arch} =~ /^ppc/ ) {
|
||||
@ALL_ARCHS = filter(qw/vsx/);
|
||||
ppc;
|
||||
} else {
|
||||
unoptimized;
|
||||
}
|
||||
|
@ -54,6 +54,13 @@ sub FixThumbInstructions($$)
|
||||
# "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;
|
||||
|
||||
# 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
|
||||
# for switching from arm to thumb (and only in armv7), but not
|
||||
# from thumb to arm.
|
||||
|
@ -60,7 +60,6 @@ if [ ${bare} ]; then
|
||||
echo "${changelog_version}${git_version_id}" > $$.tmp
|
||||
else
|
||||
cat<<EOF>$$.tmp
|
||||
// This file is generated. Do not edit.
|
||||
#define VERSION_MAJOR $major_version
|
||||
#define VERSION_MINOR $minor_version
|
||||
#define VERSION_PATCH $patch_version
|
||||
|
@ -1,4 +1,4 @@
|
||||
# This file is used by git cl to get repository specific information.
|
||||
GERRIT_HOST: True
|
||||
# This file is used by gcl to get repository specific information.
|
||||
GERRIT_HOST: chromium-review.googlesource.com
|
||||
GERRIT_PORT: 29418
|
||||
CODE_REVIEW_SERVER: chromium-review.googlesource.com
|
||||
GERRIT_SQUASH_UPLOADS: False
|
||||
|
134
configure
vendored
134
configure
vendored
@ -22,7 +22,6 @@ show_help(){
|
||||
Advanced options:
|
||||
${toggle_libs} libraries
|
||||
${toggle_examples} examples
|
||||
${toggle_tools} tools
|
||||
${toggle_docs} documentation
|
||||
${toggle_unit_tests} unit tests
|
||||
${toggle_decode_perf_tests} build decoder perf tests with unit tests
|
||||
@ -41,6 +40,7 @@ Advanced options:
|
||||
hardware decoder compatibility
|
||||
${toggle_vp8} VP8 codec support
|
||||
${toggle_vp9} VP9 codec support
|
||||
${toggle_vp10} VP10 codec support
|
||||
${toggle_internal_stats} output of encoder internal stats for debug, if supported (encoders)
|
||||
${toggle_postproc} postprocessing
|
||||
${toggle_vp9_postproc} vp9 specific postprocessing
|
||||
@ -98,26 +98,22 @@ EOF
|
||||
|
||||
# all_platforms is a list of all supported target platforms. Maintain
|
||||
# alphabetically by architecture, generic-gnu last.
|
||||
all_platforms="${all_platforms} arm64-android-gcc"
|
||||
all_platforms="${all_platforms} armv6-linux-rvct"
|
||||
all_platforms="${all_platforms} armv6-linux-gcc"
|
||||
all_platforms="${all_platforms} armv6-none-rvct"
|
||||
all_platforms="${all_platforms} arm64-darwin-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-darwin-gcc" #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-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-vs12"
|
||||
all_platforms="${all_platforms} armv7-win32-vs14"
|
||||
all_platforms="${all_platforms} armv7-win32-vs15"
|
||||
all_platforms="${all_platforms} armv7s-darwin-gcc"
|
||||
all_platforms="${all_platforms} armv8-linux-gcc"
|
||||
all_platforms="${all_platforms} mips32-linux-gcc"
|
||||
all_platforms="${all_platforms} mips64-linux-gcc"
|
||||
all_platforms="${all_platforms} ppc64-linux-gcc"
|
||||
all_platforms="${all_platforms} ppc64le-linux-gcc"
|
||||
all_platforms="${all_platforms} sparc-solaris-gcc"
|
||||
all_platforms="${all_platforms} x86-android-gcc"
|
||||
all_platforms="${all_platforms} x86-darwin8-gcc"
|
||||
@ -130,19 +126,19 @@ all_platforms="${all_platforms} x86-darwin12-gcc"
|
||||
all_platforms="${all_platforms} x86-darwin13-gcc"
|
||||
all_platforms="${all_platforms} x86-darwin14-gcc"
|
||||
all_platforms="${all_platforms} x86-darwin15-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-linux-gcc"
|
||||
all_platforms="${all_platforms} x86-linux-icc"
|
||||
all_platforms="${all_platforms} x86-os2-gcc"
|
||||
all_platforms="${all_platforms} x86-solaris-gcc"
|
||||
all_platforms="${all_platforms} x86-win32-gcc"
|
||||
all_platforms="${all_platforms} x86-win32-vs7"
|
||||
all_platforms="${all_platforms} x86-win32-vs8"
|
||||
all_platforms="${all_platforms} x86-win32-vs9"
|
||||
all_platforms="${all_platforms} x86-win32-vs10"
|
||||
all_platforms="${all_platforms} x86-win32-vs11"
|
||||
all_platforms="${all_platforms} x86-win32-vs12"
|
||||
all_platforms="${all_platforms} x86-win32-vs14"
|
||||
all_platforms="${all_platforms} x86-win32-vs15"
|
||||
all_platforms="${all_platforms} x86_64-android-gcc"
|
||||
all_platforms="${all_platforms} x86_64-darwin9-gcc"
|
||||
all_platforms="${all_platforms} x86_64-darwin10-gcc"
|
||||
@ -151,37 +147,33 @@ all_platforms="${all_platforms} x86_64-darwin12-gcc"
|
||||
all_platforms="${all_platforms} x86_64-darwin13-gcc"
|
||||
all_platforms="${all_platforms} x86_64-darwin14-gcc"
|
||||
all_platforms="${all_platforms} x86_64-darwin15-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-linux-gcc"
|
||||
all_platforms="${all_platforms} x86_64-linux-icc"
|
||||
all_platforms="${all_platforms} x86_64-solaris-gcc"
|
||||
all_platforms="${all_platforms} x86_64-win64-gcc"
|
||||
all_platforms="${all_platforms} x86_64-win64-vs8"
|
||||
all_platforms="${all_platforms} x86_64-win64-vs9"
|
||||
all_platforms="${all_platforms} x86_64-win64-vs10"
|
||||
all_platforms="${all_platforms} x86_64-win64-vs11"
|
||||
all_platforms="${all_platforms} x86_64-win64-vs12"
|
||||
all_platforms="${all_platforms} x86_64-win64-vs14"
|
||||
all_platforms="${all_platforms} x86_64-win64-vs15"
|
||||
all_platforms="${all_platforms} generic-gnu"
|
||||
|
||||
# all_targets is a list of all targets that can be configured
|
||||
# note that these should be in dependency order for now.
|
||||
all_targets="libs examples tools docs"
|
||||
all_targets="libs examples docs"
|
||||
|
||||
# all targets available are enabled, by default.
|
||||
for t in ${all_targets}; do
|
||||
[ -f "${source_path}/${t}.mk" ] && enable_feature ${t}
|
||||
done
|
||||
|
||||
if ! diff --version >/dev/null; then
|
||||
die "diff missing: Try installing diffutils via your package manager."
|
||||
fi
|
||||
|
||||
if ! perl --version >/dev/null; then
|
||||
die "Perl is required to build"
|
||||
fi
|
||||
|
||||
|
||||
if [ "`cd \"${source_path}\" && pwd`" != "`pwd`" ]; then
|
||||
# test to see if source_path already configured
|
||||
if [ -f "${source_path}/vpx_config.h" ]; then
|
||||
@ -203,8 +195,12 @@ if [ ${doxy_major:-0} -ge 1 ]; then
|
||||
fi
|
||||
|
||||
# disable codecs when their source directory does not exist
|
||||
[ -d "${source_path}/vp8" ] || disable_codec vp8
|
||||
[ -d "${source_path}/vp9" ] || disable_codec vp9
|
||||
[ -d "${source_path}/vp8" ] || disable_feature vp8
|
||||
[ -d "${source_path}/vp9" ] || disable_feature vp9
|
||||
[ -d "${source_path}/vp10" ] || disable_feature vp10
|
||||
|
||||
# disable vp10 codec by default
|
||||
disable_feature vp10
|
||||
|
||||
# install everything except the sources, by default. sources will have
|
||||
# to be enabled when doing dist builds, since that's no longer a common
|
||||
@ -226,10 +222,13 @@ CODECS="
|
||||
vp8_decoder
|
||||
vp9_encoder
|
||||
vp9_decoder
|
||||
vp10_encoder
|
||||
vp10_decoder
|
||||
"
|
||||
CODEC_FAMILIES="
|
||||
vp8
|
||||
vp9
|
||||
vp10
|
||||
"
|
||||
|
||||
ARCH_LIST="
|
||||
@ -237,7 +236,6 @@ ARCH_LIST="
|
||||
mips
|
||||
x86
|
||||
x86_64
|
||||
ppc
|
||||
"
|
||||
ARCH_EXT_LIST_X86="
|
||||
mmx
|
||||
@ -248,14 +246,10 @@ ARCH_EXT_LIST_X86="
|
||||
sse4_1
|
||||
avx
|
||||
avx2
|
||||
avx512
|
||||
"
|
||||
|
||||
ARCH_EXT_LIST_LOONGSON="
|
||||
mmi
|
||||
"
|
||||
|
||||
ARCH_EXT_LIST="
|
||||
edsp
|
||||
media
|
||||
neon
|
||||
neon_asm
|
||||
|
||||
@ -265,10 +259,6 @@ ARCH_EXT_LIST="
|
||||
mips64
|
||||
|
||||
${ARCH_EXT_LIST_X86}
|
||||
|
||||
vsx
|
||||
|
||||
${ARCH_EXT_LIST_LOONGSON}
|
||||
"
|
||||
HAVE_LIST="
|
||||
${ARCH_EXT_LIST}
|
||||
@ -277,8 +267,10 @@ HAVE_LIST="
|
||||
unistd_h
|
||||
"
|
||||
EXPERIMENT_LIST="
|
||||
spatial_svc
|
||||
fp_mb_stats
|
||||
emulate_hardware
|
||||
misc_fixes
|
||||
"
|
||||
CONFIG_LIST="
|
||||
dependency_tracking
|
||||
@ -287,6 +279,7 @@ CONFIG_LIST="
|
||||
install_bins
|
||||
install_libs
|
||||
install_srcs
|
||||
use_x86inc
|
||||
debug
|
||||
gprof
|
||||
gcov
|
||||
@ -333,7 +326,6 @@ CONFIG_LIST="
|
||||
better_hw_compatibility
|
||||
experimental
|
||||
size_limit
|
||||
always_adjust_bpm
|
||||
${EXPERIMENT_LIST}
|
||||
"
|
||||
CMDLINE_SELECT="
|
||||
@ -349,6 +341,7 @@ CMDLINE_SELECT="
|
||||
gprof
|
||||
gcov
|
||||
pic
|
||||
use_x86inc
|
||||
optimizations
|
||||
ccache
|
||||
runtime_cpu_detect
|
||||
@ -356,7 +349,6 @@ CMDLINE_SELECT="
|
||||
|
||||
libs
|
||||
examples
|
||||
tools
|
||||
docs
|
||||
libc
|
||||
as
|
||||
@ -393,26 +385,21 @@ CMDLINE_SELECT="
|
||||
better_hw_compatibility
|
||||
vp9_highbitdepth
|
||||
experimental
|
||||
always_adjust_bpm
|
||||
"
|
||||
|
||||
process_cmdline() {
|
||||
for opt do
|
||||
optval="${opt#*=}"
|
||||
case "$opt" in
|
||||
--disable-codecs)
|
||||
for c in ${CODEC_FAMILIES}; do disable_codec $c; done
|
||||
;;
|
||||
--disable-codecs) for c in ${CODECS}; do disable_feature $c; done ;;
|
||||
--enable-?*|--disable-?*)
|
||||
eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
|
||||
if is_in ${option} ${EXPERIMENT_LIST}; then
|
||||
if echo "${EXPERIMENT_LIST}" | grep "^ *$option\$" >/dev/null; then
|
||||
if enabled experimental; then
|
||||
${action}_feature $option
|
||||
else
|
||||
log_echo "Ignoring $opt -- not in experimental mode."
|
||||
fi
|
||||
elif is_in ${option} "${CODECS} ${CODEC_FAMILIES}"; then
|
||||
${action}_codec ${option}
|
||||
else
|
||||
process_common_cmdline $opt
|
||||
fi
|
||||
@ -426,6 +413,14 @@ process_cmdline() {
|
||||
post_process_cmdline() {
|
||||
c=""
|
||||
|
||||
# If the codec family is disabled, disable all components of that family.
|
||||
# If the codec family is enabled, enable all components of that family.
|
||||
log_echo "Configuring selected codecs"
|
||||
for c in ${CODECS}; do
|
||||
disabled ${c%%_*} && disable_feature ${c}
|
||||
enabled ${c%%_*} && enable_feature ${c}
|
||||
done
|
||||
|
||||
# Enable all detected codecs, if they haven't been disabled
|
||||
for c in ${CODECS}; do soft_enable $c; done
|
||||
|
||||
@ -503,7 +498,7 @@ EOF
|
||||
#
|
||||
# Write makefiles for all enabled targets
|
||||
#
|
||||
for tgt in libs examples tools docs solution; do
|
||||
for tgt in libs examples docs solution; do
|
||||
tgt_fn="$tgt-$toolchain.mk"
|
||||
|
||||
if enabled $tgt; then
|
||||
@ -520,18 +515,13 @@ process_detect() {
|
||||
# Can only build shared libs on a subset of platforms. Doing this check
|
||||
# here rather than at option parse time because the target auto-detect
|
||||
# magic happens after the command line has been parsed.
|
||||
case "${tgt_os}" in
|
||||
linux|os2|darwin*|iphonesimulator*)
|
||||
# Supported platforms
|
||||
;;
|
||||
*)
|
||||
if ! enabled linux && ! enabled os2; then
|
||||
if enabled gnu; then
|
||||
echo "--enable-shared is only supported on ELF; assuming this is OK"
|
||||
else
|
||||
die "--enable-shared only supported on ELF, OS/2, and Darwin for now"
|
||||
die "--enable-shared only supported on ELF and OS/2 for now"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if [ -z "$CC" ] || enabled external_build; then
|
||||
echo "Bypassing toolchain for environment detection."
|
||||
@ -594,31 +584,27 @@ process_toolchain() {
|
||||
check_add_cflags -Wall
|
||||
check_add_cflags -Wdeclaration-after-statement
|
||||
check_add_cflags -Wdisabled-optimization
|
||||
check_add_cflags -Wfloat-conversion
|
||||
check_add_cflags -Wparentheses-equality
|
||||
check_add_cflags -Wpointer-arith
|
||||
check_add_cflags -Wtype-limits
|
||||
check_add_cflags -Wcast-qual
|
||||
check_add_cflags -Wvla
|
||||
check_add_cflags -Wimplicit-function-declaration
|
||||
check_add_cflags -Wuninitialized
|
||||
check_add_cflags -Wunused
|
||||
# -Wextra has some tricky cases. Rather than fix them all now, get the
|
||||
# flag for as many files as possible and fix the remaining issues
|
||||
# piecemeal.
|
||||
# https://bugs.chromium.org/p/webm/issues/detail?id=1069
|
||||
check_add_cflags -Wextra
|
||||
# check_add_cflags also adds to cxxflags. gtest does not do well with
|
||||
# these flags so add them explicitly to CFLAGS only.
|
||||
check_cflags -Wundef && add_cflags_only -Wundef
|
||||
check_cflags -Wframe-larger-than=52000 && \
|
||||
add_cflags_only -Wframe-larger-than=52000
|
||||
check_add_cflags -Wunused-variable
|
||||
case ${CC} in
|
||||
*clang*)
|
||||
# libvpx and/or clang have issues with aliasing:
|
||||
# https://code.google.com/p/webm/issues/detail?id=603
|
||||
# work around them until they are fixed
|
||||
check_add_cflags -fno-strict-aliasing
|
||||
;;
|
||||
*) check_add_cflags -Wunused-but-set-variable ;;
|
||||
esac
|
||||
if enabled mips || [ -z "${INLINE}" ]; then
|
||||
enabled extra_warnings || check_add_cflags -Wno-unused-function
|
||||
else
|
||||
check_add_cflags -Wunused-function
|
||||
fi
|
||||
# Avoid this warning for third_party C++ sources. Some reorganization
|
||||
# would be needed to apply this only to test/*.cc.
|
||||
check_cflags -Wshorten-64-to-32 && add_cflags_only -Wshorten-64-to-32
|
||||
fi
|
||||
|
||||
if enabled icc; then
|
||||
@ -666,11 +652,19 @@ process_toolchain() {
|
||||
vs*) enable_feature msvs
|
||||
enable_feature solution
|
||||
vs_version=${tgt_cc##vs}
|
||||
VCPROJ_SFX=vcxproj
|
||||
gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh
|
||||
enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror"
|
||||
case $vs_version in
|
||||
[789])
|
||||
VCPROJ_SFX=vcproj
|
||||
gen_vcproj_cmd=${source_path}/build/make/gen_msvs_proj.sh
|
||||
;;
|
||||
10|11|12|14)
|
||||
VCPROJ_SFX=vcxproj
|
||||
gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh
|
||||
enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror"
|
||||
;;
|
||||
esac
|
||||
all_targets="${all_targets} solution"
|
||||
INLINE="__inline"
|
||||
INLINE="__forceinline"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
35
examples.mk
35
examples.mk
@ -76,7 +76,6 @@ vpxdec.SRCS += tools_common.c tools_common.h
|
||||
vpxdec.SRCS += y4menc.c y4menc.h
|
||||
ifeq ($(CONFIG_LIBYUV),yes)
|
||||
vpxdec.SRCS += $(LIBYUV_SRCS)
|
||||
$(BUILD_PFX)third_party/libyuv/%.cc.o: CXXFLAGS += -Wno-unused-parameter
|
||||
endif
|
||||
ifeq ($(CONFIG_WEBM_IO),yes)
|
||||
vpxdec.SRCS += $(LIBWEBM_COMMON_SRCS)
|
||||
@ -109,17 +108,18 @@ ifeq ($(CONFIG_WEBM_IO),yes)
|
||||
endif
|
||||
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
|
||||
vpxenc.DESCRIPTION = Full featured encoder
|
||||
|
||||
EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_spatial_svc_encoder.c
|
||||
vp9_spatial_svc_encoder.SRCS += args.c args.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 += video_common.h
|
||||
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 += vpxstats.c vpxstats.h
|
||||
vp9_spatial_svc_encoder.GUID = 4A38598D-627D-4505-9C7B-D4020C84100D
|
||||
vp9_spatial_svc_encoder.DESCRIPTION = VP9 Spatial SVC Encoder
|
||||
ifeq ($(CONFIG_SPATIAL_SVC),yes)
|
||||
EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_spatial_svc_encoder.c
|
||||
vp9_spatial_svc_encoder.SRCS += args.c args.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 += video_common.h
|
||||
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 += vpxstats.c vpxstats.h
|
||||
vp9_spatial_svc_encoder.GUID = 4A38598D-627D-4505-9C7B-D4020C84100D
|
||||
vp9_spatial_svc_encoder.DESCRIPTION = VP9 Spatial SVC Encoder
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SHARED),yes)
|
||||
EXAMPLES-$(CONFIG_VP9_ENCODER) += resize_util.c
|
||||
@ -215,17 +215,6 @@ vp8cx_set_ref.SRCS += vpx_ports/msvc.h
|
||||
vp8cx_set_ref.GUID = C5E31F7F-96F6-48BD-BD3E-10EBF6E8057A
|
||||
vp8cx_set_ref.DESCRIPTION = VP8 set encoder reference frame
|
||||
|
||||
ifeq ($(CONFIG_VP9_ENCODER),yes)
|
||||
ifeq ($(CONFIG_DECODERS),yes)
|
||||
EXAMPLES-yes += vp9cx_set_ref.c
|
||||
vp9cx_set_ref.SRCS += ivfenc.h ivfenc.c
|
||||
vp9cx_set_ref.SRCS += tools_common.h tools_common.c
|
||||
vp9cx_set_ref.SRCS += video_common.h
|
||||
vp9cx_set_ref.SRCS += video_writer.h video_writer.c
|
||||
vp9cx_set_ref.GUID = 65D7F14A-2EE6-4293-B958-AB5107A03B55
|
||||
vp9cx_set_ref.DESCRIPTION = VP9 set encoder reference frame
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MULTI_RES_ENCODING),yes)
|
||||
ifeq ($(CONFIG_LIBYUV),yes)
|
||||
|
@ -65,7 +65,8 @@ static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) {
|
||||
static void print_md5(FILE *stream, unsigned char digest[16]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; ++i) fprintf(stream, "%02x", digest[i]);
|
||||
for (i = 0; i < 16; ++i)
|
||||
fprintf(stream, "%02x", digest[i]);
|
||||
}
|
||||
|
||||
static const char *exec_name;
|
||||
@ -85,10 +86,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 3) die("Invalid number of arguments.");
|
||||
if (argc != 3)
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
@ -96,7 +99,8 @@ int main(int argc, char **argv) {
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
if (!decoder)
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
@ -107,8 +111,8 @@ int main(int argc, char **argv) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame =
|
||||
vpx_video_reader_get_frame(reader, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
@ -117,13 +121,14 @@ int main(int argc, char **argv) {
|
||||
|
||||
get_image_md5(img, digest);
|
||||
print_md5(outfile, digest);
|
||||
fprintf(outfile, " img-%dx%d-%04d.i420\n", img->d_w, img->d_h,
|
||||
++frame_cnt);
|
||||
fprintf(outfile, " img-%dx%d-%04d.i420\n",
|
||||
img->d_w, img->d_h, ++frame_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_reader_close(reader);
|
||||
|
||||
|
@ -84,16 +84,18 @@ int main(int argc, char **argv) {
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 4) die("Invalid number of arguments.");
|
||||
if (argc != 4)
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
|
||||
n = (int)strtol(argv[3], &nptr, 0);
|
||||
m = (int)strtol(nptr + 1, NULL, 0);
|
||||
n = strtol(argv[3], &nptr, 0);
|
||||
m = strtol(nptr + 1, NULL, 0);
|
||||
is_range = (*nptr == '-');
|
||||
if (!n || !m || (*nptr != '-' && *nptr != '/'))
|
||||
die("Couldn't parse pattern %s.\n", argv[3]);
|
||||
@ -101,7 +103,8 @@ int main(int argc, char **argv) {
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
if (!decoder)
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
@ -113,8 +116,8 @@ int main(int argc, char **argv) {
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
int skip;
|
||||
const unsigned char *frame =
|
||||
vpx_video_reader_get_frame(reader, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame.");
|
||||
|
||||
@ -136,7 +139,8 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
@ -68,10 +68,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 3) die("Invalid number of arguments.");
|
||||
if (argc != 3)
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
@ -79,7 +81,8 @@ int main(int argc, char **argv) {
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
if (!decoder)
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
@ -88,25 +91,26 @@ int main(int argc, char **argv) {
|
||||
if (res == VPX_CODEC_INCAPABLE)
|
||||
die_codec(&codec, "Postproc not supported by this decoder.");
|
||||
|
||||
if (res) die_codec(&codec, "Failed to initialize decoder.");
|
||||
if (res)
|
||||
die_codec(&codec, "Failed to initialize decoder.");
|
||||
|
||||
while (vpx_video_reader_read_frame(reader)) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame =
|
||||
vpx_video_reader_get_frame(reader, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
|
||||
++frame_cnt;
|
||||
|
||||
if (frame_cnt % 30 == 1) {
|
||||
vp8_postproc_cfg_t pp = { 0, 0, 0 };
|
||||
vp8_postproc_cfg_t pp = {0, 0, 0};
|
||||
|
||||
if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn off postproc.");
|
||||
if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn off postproc.");
|
||||
} else if (frame_cnt % 30 == 16) {
|
||||
vp8_postproc_cfg_t pp = { VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE, 4,
|
||||
0 };
|
||||
vp8_postproc_cfg_t pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE,
|
||||
4, 0};
|
||||
if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn on postproc.");
|
||||
};
|
||||
@ -121,7 +125,8 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
@ -34,8 +34,10 @@ void usage_exit(void) {
|
||||
|
||||
static int parse_dim(char *v, int *width, int *height) {
|
||||
char *x = strchr(v, 'x');
|
||||
if (x == NULL) x = strchr(v, 'X');
|
||||
if (x == NULL) return 0;
|
||||
if (x == NULL)
|
||||
x = strchr(v, 'X');
|
||||
if (x == NULL)
|
||||
return 0;
|
||||
*width = atoi(v);
|
||||
*height = atoi(&x[1]);
|
||||
if (*width <= 0 || *height <= 0)
|
||||
@ -91,25 +93,30 @@ int main(int argc, char *argv[]) {
|
||||
else
|
||||
frames = INT_MAX;
|
||||
|
||||
printf("Input size: %dx%d\n", width, height);
|
||||
printf("Target size: %dx%d, Frames: ", target_width, target_height);
|
||||
printf("Input size: %dx%d\n",
|
||||
width, height);
|
||||
printf("Target size: %dx%d, Frames: ",
|
||||
target_width, target_height);
|
||||
if (frames == INT_MAX)
|
||||
printf("All\n");
|
||||
else
|
||||
printf("%d\n", frames);
|
||||
|
||||
inbuf = (uint8_t *)malloc(width * height * 3 / 2);
|
||||
outbuf = (uint8_t *)malloc(target_width * target_height * 3 / 2);
|
||||
inbuf = (uint8_t*)malloc(width * height * 3 / 2);
|
||||
outbuf = (uint8_t*)malloc(target_width * target_height * 3 / 2);
|
||||
inbuf_u = inbuf + width * height;
|
||||
inbuf_v = inbuf_u + width * height / 4;
|
||||
outbuf_u = outbuf + target_width * target_height;
|
||||
outbuf_v = outbuf_u + target_width * target_height / 4;
|
||||
f = 0;
|
||||
while (f < frames) {
|
||||
if (fread(inbuf, width * height * 3 / 2, 1, fpin) != 1) break;
|
||||
vp9_resize_frame420(inbuf, width, inbuf_u, inbuf_v, width / 2, height,
|
||||
width, outbuf, target_width, outbuf_u, outbuf_v,
|
||||
target_width / 2, target_height, target_width);
|
||||
if (fread(inbuf, width * height * 3 / 2, 1, fpin) != 1)
|
||||
break;
|
||||
vp9_resize_frame420(inbuf, width, inbuf_u, inbuf_v, width / 2,
|
||||
height, width,
|
||||
outbuf, target_width, outbuf_u, outbuf_v,
|
||||
target_width / 2,
|
||||
target_height, target_width);
|
||||
fwrite(outbuf, target_width * target_height * 3 / 2, 1, fpout);
|
||||
f++;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
// VP8 Set Active and ROI Maps
|
||||
// ===========================
|
||||
//
|
||||
@ -85,7 +86,8 @@ static void set_roi_map(const vpx_codec_enc_cfg_t *cfg,
|
||||
roi.static_threshold[3] = 0;
|
||||
|
||||
roi.roi_map = (uint8_t *)malloc(roi.rows * roi.cols);
|
||||
for (i = 0; i < roi.rows * roi.cols; ++i) roi.roi_map[i] = i % 4;
|
||||
for (i = 0; i < roi.rows * roi.cols; ++i)
|
||||
roi.roi_map[i] = i % 4;
|
||||
|
||||
if (vpx_codec_control(codec, VP8E_SET_ROI_MAP, &roi))
|
||||
die_codec(codec, "Failed to set ROI map");
|
||||
@ -96,13 +98,14 @@ static void set_roi_map(const vpx_codec_enc_cfg_t *cfg,
|
||||
static void set_active_map(const vpx_codec_enc_cfg_t *cfg,
|
||||
vpx_codec_ctx_t *codec) {
|
||||
unsigned int i;
|
||||
vpx_active_map_t map = { 0, 0, 0 };
|
||||
vpx_active_map_t map = {0, 0, 0};
|
||||
|
||||
map.rows = (cfg->g_h + 15) / 16;
|
||||
map.cols = (cfg->g_w + 15) / 16;
|
||||
|
||||
map.active_map = (uint8_t *)malloc(map.rows * map.cols);
|
||||
for (i = 0; i < map.rows * map.cols; ++i) map.active_map[i] = i % 2;
|
||||
for (i = 0; i < map.rows * map.cols; ++i)
|
||||
map.active_map[i] = i % 2;
|
||||
|
||||
if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map))
|
||||
die_codec(codec, "Failed to set active map");
|
||||
@ -112,7 +115,7 @@ static void set_active_map(const vpx_codec_enc_cfg_t *cfg,
|
||||
|
||||
static void unset_active_map(const vpx_codec_enc_cfg_t *cfg,
|
||||
vpx_codec_ctx_t *codec) {
|
||||
vpx_active_map_t map = { 0, 0, 0 };
|
||||
vpx_active_map_t map = {0, 0, 0};
|
||||
|
||||
map.rows = (cfg->g_h + 15) / 16;
|
||||
map.cols = (cfg->g_w + 15) / 16;
|
||||
@ -122,21 +125,25 @@ static void unset_active_map(const vpx_codec_enc_cfg_t *cfg,
|
||||
die_codec(codec, "Failed to set active map");
|
||||
}
|
||||
|
||||
static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
|
||||
int frame_index, VpxVideoWriter *writer) {
|
||||
static int encode_frame(vpx_codec_ctx_t *codec,
|
||||
vpx_image_t *img,
|
||||
int frame_index,
|
||||
VpxVideoWriter *writer) {
|
||||
int got_pkts = 0;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(codec, img, frame_index, 1, 0, VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK) die_codec(codec, "Failed to encode frame");
|
||||
const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 0,
|
||||
VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK)
|
||||
die_codec(codec, "Failed to encode frame");
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
|
||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||
const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
|
||||
if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
if (!vpx_video_writer_write_frame(writer,
|
||||
pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
@ -160,11 +167,12 @@ int main(int argc, char **argv) {
|
||||
VpxVideoInfo info;
|
||||
VpxVideoWriter *writer = NULL;
|
||||
const VpxInterface *encoder = NULL;
|
||||
const int fps = 2; // TODO(dkovalev) add command line argument
|
||||
const int fps = 2; // TODO(dkovalev) add command line argument
|
||||
const double bits_per_pixel_per_frame = 0.067;
|
||||
|
||||
exec_name = argv[0];
|
||||
if (argc != 6) die("Invalid number of arguments");
|
||||
if (argc != 6)
|
||||
die("Invalid number of arguments");
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
@ -174,36 +182,40 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
assert(encoder != NULL);
|
||||
info.codec_fourcc = encoder->fourcc;
|
||||
info.frame_width = (int)strtol(argv[2], NULL, 0);
|
||||
info.frame_height = (int)strtol(argv[3], NULL, 0);
|
||||
info.frame_width = strtol(argv[2], NULL, 0);
|
||||
info.frame_height = strtol(argv[3], NULL, 0);
|
||||
info.time_base.numerator = 1;
|
||||
info.time_base.denominator = fps;
|
||||
|
||||
if (info.frame_width <= 0 || info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
|
||||
if (info.frame_width <= 0 ||
|
||||
info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 ||
|
||||
(info.frame_height % 2) != 0) {
|
||||
die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
|
||||
}
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
|
||||
info.frame_height, 1)) {
|
||||
info.frame_height, 1)) {
|
||||
die("Failed to allocate image.");
|
||||
}
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&codec, "Failed to get default codec config.");
|
||||
if (res)
|
||||
die_codec(&codec, "Failed to get default codec config.");
|
||||
|
||||
cfg.g_w = info.frame_width;
|
||||
cfg.g_h = info.frame_height;
|
||||
cfg.g_timebase.num = info.time_base.numerator;
|
||||
cfg.g_timebase.den = info.time_base.denominator;
|
||||
cfg.rc_target_bitrate =
|
||||
(unsigned int)(bits_per_pixel_per_frame * cfg.g_w * cfg.g_h * fps / 1000);
|
||||
cfg.rc_target_bitrate = (unsigned int)(bits_per_pixel_per_frame * cfg.g_w *
|
||||
cfg.g_h * fps / 1000);
|
||||
cfg.g_lag_in_frames = 0;
|
||||
|
||||
writer = vpx_video_writer_open(argv[5], kContainerIVF, &info);
|
||||
if (!writer) die("Failed to open %s for writing.", argv[5]);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing.", argv[5]);
|
||||
|
||||
if (!(infile = fopen(argv[4], "rb")))
|
||||
die("Failed to open %s for reading.", argv[4]);
|
||||
@ -227,15 +239,15 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
while (encode_frame(&codec, NULL, -1, writer)) {
|
||||
}
|
||||
while (encode_frame(&codec, NULL, -1, writer)) {}
|
||||
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
printf("Processed %d frames.\n", frame_count);
|
||||
|
||||
vpx_img_free(&raw);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
// Simple Decoder
|
||||
// ==============
|
||||
//
|
||||
@ -102,10 +103,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 3) die("Invalid number of arguments.");
|
||||
if (argc != 3)
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
@ -113,7 +116,8 @@ int main(int argc, char **argv) {
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
if (!decoder)
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
@ -124,8 +128,8 @@ int main(int argc, char **argv) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame =
|
||||
vpx_video_reader_get_frame(reader, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame.");
|
||||
|
||||
@ -136,7 +140,8 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
@ -109,27 +109,32 @@ static const char *exec_name;
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <codec> <width> <height> <infile> <outfile> "
|
||||
"<keyframe-interval> <error-resilient> <frames to encode>\n"
|
||||
"See comments in simple_encoder.c for more information.\n",
|
||||
"<keyframe-interval> [<error-resilient>]\nSee comments in "
|
||||
"simple_encoder.c for more information.\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
|
||||
int frame_index, int flags, VpxVideoWriter *writer) {
|
||||
static int encode_frame(vpx_codec_ctx_t *codec,
|
||||
vpx_image_t *img,
|
||||
int frame_index,
|
||||
int flags,
|
||||
VpxVideoWriter *writer) {
|
||||
int got_pkts = 0;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(codec, img, frame_index, 1, flags, VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK) die_codec(codec, "Failed to encode frame");
|
||||
const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1,
|
||||
flags, VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK)
|
||||
die_codec(codec, "Failed to encode frame");
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
|
||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||
const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
|
||||
if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
if (!vpx_video_writer_write_frame(writer,
|
||||
pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
@ -142,7 +147,6 @@ static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
|
||||
return got_pkts;
|
||||
}
|
||||
|
||||
// TODO(tomfinegan): Improve command line parsing and add args for bitrate/fps.
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
@ -150,14 +154,15 @@ int main(int argc, char **argv) {
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info = { 0, 0, 0, { 0, 0 } };
|
||||
VpxVideoInfo info = {0};
|
||||
VpxVideoWriter *writer = NULL;
|
||||
const VpxInterface *encoder = NULL;
|
||||
const int fps = 30;
|
||||
const int bitrate = 200;
|
||||
const int fps = 30; // TODO(dkovalev) add command line argument
|
||||
const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument
|
||||
int keyframe_interval = 0;
|
||||
int max_frames = 0;
|
||||
int frames_encoded = 0;
|
||||
|
||||
// TODO(dkovalev): Add some simple command line parsing code to make the
|
||||
// command line more flexible.
|
||||
const char *codec_arg = NULL;
|
||||
const char *width_arg = NULL;
|
||||
const char *height_arg = NULL;
|
||||
@ -167,7 +172,8 @@ int main(int argc, char **argv) {
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 9) die("Invalid number of arguments");
|
||||
if (argc < 7)
|
||||
die("Invalid number of arguments");
|
||||
|
||||
codec_arg = argv[1];
|
||||
width_arg = argv[2];
|
||||
@ -175,44 +181,49 @@ int main(int argc, char **argv) {
|
||||
infile_arg = argv[4];
|
||||
outfile_arg = argv[5];
|
||||
keyframe_interval_arg = argv[6];
|
||||
max_frames = (int)strtol(argv[8], NULL, 0);
|
||||
|
||||
encoder = get_vpx_encoder_by_name(codec_arg);
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
if (!encoder)
|
||||
die("Unsupported codec.");
|
||||
|
||||
info.codec_fourcc = encoder->fourcc;
|
||||
info.frame_width = (int)strtol(width_arg, NULL, 0);
|
||||
info.frame_height = (int)strtol(height_arg, NULL, 0);
|
||||
info.frame_width = strtol(width_arg, NULL, 0);
|
||||
info.frame_height = strtol(height_arg, NULL, 0);
|
||||
info.time_base.numerator = 1;
|
||||
info.time_base.denominator = fps;
|
||||
|
||||
if (info.frame_width <= 0 || info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
|
||||
if (info.frame_width <= 0 ||
|
||||
info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 ||
|
||||
(info.frame_height % 2) != 0) {
|
||||
die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
|
||||
}
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
|
||||
info.frame_height, 1)) {
|
||||
info.frame_height, 1)) {
|
||||
die("Failed to allocate image.");
|
||||
}
|
||||
|
||||
keyframe_interval = (int)strtol(keyframe_interval_arg, NULL, 0);
|
||||
if (keyframe_interval < 0) die("Invalid keyframe interval value.");
|
||||
keyframe_interval = strtol(keyframe_interval_arg, NULL, 0);
|
||||
if (keyframe_interval < 0)
|
||||
die("Invalid keyframe interval value.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&codec, "Failed to get default codec config.");
|
||||
if (res)
|
||||
die_codec(&codec, "Failed to get default codec config.");
|
||||
|
||||
cfg.g_w = info.frame_width;
|
||||
cfg.g_h = info.frame_height;
|
||||
cfg.g_timebase.num = info.time_base.numerator;
|
||||
cfg.g_timebase.den = info.time_base.denominator;
|
||||
cfg.rc_target_bitrate = bitrate;
|
||||
cfg.g_error_resilient = (vpx_codec_er_flags_t)strtoul(argv[7], NULL, 0);
|
||||
cfg.g_error_resilient = argc > 7 ? strtol(argv[7], NULL, 0) : 0;
|
||||
|
||||
writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
|
||||
if (!writer) die("Failed to open %s for writing.", outfile_arg);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing.", outfile_arg);
|
||||
|
||||
if (!(infile = fopen(infile_arg, "rb")))
|
||||
die("Failed to open %s for reading.", infile_arg);
|
||||
@ -226,20 +237,18 @@ int main(int argc, char **argv) {
|
||||
if (keyframe_interval > 0 && frame_count % keyframe_interval == 0)
|
||||
flags |= VPX_EFLAG_FORCE_KF;
|
||||
encode_frame(&codec, &raw, frame_count++, flags, writer);
|
||||
frames_encoded++;
|
||||
if (max_frames > 0 && frames_encoded >= max_frames) break;
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
while (encode_frame(&codec, NULL, -1, 0, writer)) {
|
||||
}
|
||||
while (encode_frame(&codec, NULL, -1, 0, writer)) {};
|
||||
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
printf("Processed %d frames.\n", frame_count);
|
||||
|
||||
vpx_img_free(&raw);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
|
@ -59,23 +59,25 @@
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <codec> <width> <height> <infile> <outfile> "
|
||||
"<frame limit>\n",
|
||||
fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int get_frame_stats(vpx_codec_ctx_t *ctx, const vpx_image_t *img,
|
||||
vpx_codec_pts_t pts, unsigned int duration,
|
||||
vpx_enc_frame_flags_t flags, unsigned int deadline,
|
||||
static int get_frame_stats(vpx_codec_ctx_t *ctx,
|
||||
const vpx_image_t *img,
|
||||
vpx_codec_pts_t pts,
|
||||
unsigned int duration,
|
||||
vpx_enc_frame_flags_t flags,
|
||||
unsigned int deadline,
|
||||
vpx_fixed_buf_t *stats) {
|
||||
int got_pkts = 0;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(ctx, img, pts, duration, flags, deadline);
|
||||
if (res != VPX_CODEC_OK) die_codec(ctx, "Failed to get frame stats.");
|
||||
const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags,
|
||||
deadline);
|
||||
if (res != VPX_CODEC_OK)
|
||||
die_codec(ctx, "Failed to get frame stats.");
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
@ -92,16 +94,20 @@ static int get_frame_stats(vpx_codec_ctx_t *ctx, const vpx_image_t *img,
|
||||
return got_pkts;
|
||||
}
|
||||
|
||||
static int encode_frame(vpx_codec_ctx_t *ctx, const vpx_image_t *img,
|
||||
vpx_codec_pts_t pts, unsigned int duration,
|
||||
vpx_enc_frame_flags_t flags, unsigned int deadline,
|
||||
static int encode_frame(vpx_codec_ctx_t *ctx,
|
||||
const vpx_image_t *img,
|
||||
vpx_codec_pts_t pts,
|
||||
unsigned int duration,
|
||||
vpx_enc_frame_flags_t flags,
|
||||
unsigned int deadline,
|
||||
VpxVideoWriter *writer) {
|
||||
int got_pkts = 0;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(ctx, img, pts, duration, flags, deadline);
|
||||
if (res != VPX_CODEC_OK) die_codec(ctx, "Failed to encode frame.");
|
||||
const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags,
|
||||
deadline);
|
||||
if (res != VPX_CODEC_OK)
|
||||
die_codec(ctx, "Failed to encode frame.");
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
@ -109,8 +115,8 @@ static int encode_frame(vpx_codec_ctx_t *ctx, const vpx_image_t *img,
|
||||
const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
|
||||
|
||||
if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts))
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts))
|
||||
die_codec(ctx, "Failed to write compressed frame.");
|
||||
printf(keyframe ? "K" : ".");
|
||||
fflush(stdout);
|
||||
@ -120,12 +126,13 @@ static int encode_frame(vpx_codec_ctx_t *ctx, const vpx_image_t *img,
|
||||
return got_pkts;
|
||||
}
|
||||
|
||||
static vpx_fixed_buf_t pass0(vpx_image_t *raw, FILE *infile,
|
||||
static vpx_fixed_buf_t pass0(vpx_image_t *raw,
|
||||
FILE *infile,
|
||||
const VpxInterface *encoder,
|
||||
const vpx_codec_enc_cfg_t *cfg, int max_frames) {
|
||||
const vpx_codec_enc_cfg_t *cfg) {
|
||||
vpx_codec_ctx_t codec;
|
||||
int frame_count = 0;
|
||||
vpx_fixed_buf_t stats = { NULL, 0 };
|
||||
vpx_fixed_buf_t stats = {NULL, 0};
|
||||
|
||||
if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
@ -135,33 +142,37 @@ static vpx_fixed_buf_t pass0(vpx_image_t *raw, FILE *infile,
|
||||
++frame_count;
|
||||
get_frame_stats(&codec, raw, frame_count, 1, 0, VPX_DL_GOOD_QUALITY,
|
||||
&stats);
|
||||
if (max_frames > 0 && frame_count >= max_frames) break;
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
while (get_frame_stats(&codec, NULL, frame_count, 1, 0, VPX_DL_GOOD_QUALITY,
|
||||
&stats)) {
|
||||
}
|
||||
while (get_frame_stats(&codec, NULL, frame_count, 1, 0,
|
||||
VPX_DL_GOOD_QUALITY, &stats)) {}
|
||||
|
||||
printf("Pass 0 complete. Processed %d frames.\n", frame_count);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
static void pass1(vpx_image_t *raw, FILE *infile, const char *outfile_name,
|
||||
const VpxInterface *encoder, const vpx_codec_enc_cfg_t *cfg,
|
||||
int max_frames) {
|
||||
VpxVideoInfo info = { encoder->fourcc,
|
||||
cfg->g_w,
|
||||
cfg->g_h,
|
||||
{ cfg->g_timebase.num, cfg->g_timebase.den } };
|
||||
static void pass1(vpx_image_t *raw,
|
||||
FILE *infile,
|
||||
const char *outfile_name,
|
||||
const VpxInterface *encoder,
|
||||
const vpx_codec_enc_cfg_t *cfg) {
|
||||
VpxVideoInfo info = {
|
||||
encoder->fourcc,
|
||||
cfg->g_w,
|
||||
cfg->g_h,
|
||||
{cfg->g_timebase.num, cfg->g_timebase.den}
|
||||
};
|
||||
VpxVideoWriter *writer = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
int frame_count = 0;
|
||||
|
||||
writer = vpx_video_writer_open(outfile_name, kContainerIVF, &info);
|
||||
if (!writer) die("Failed to open %s for writing", outfile_name);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing", outfile_name);
|
||||
|
||||
if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
@ -170,17 +181,15 @@ static void pass1(vpx_image_t *raw, FILE *infile, const char *outfile_name,
|
||||
while (vpx_img_read(raw, infile)) {
|
||||
++frame_count;
|
||||
encode_frame(&codec, raw, frame_count, 1, 0, VPX_DL_GOOD_QUALITY, writer);
|
||||
|
||||
if (max_frames > 0 && frame_count >= max_frames) break;
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
while (encode_frame(&codec, NULL, -1, 1, 0, VPX_DL_GOOD_QUALITY, writer)) {
|
||||
}
|
||||
while (encode_frame(&codec, NULL, -1, 1, 0, VPX_DL_GOOD_QUALITY, writer)) {}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
@ -197,27 +206,26 @@ int main(int argc, char **argv) {
|
||||
vpx_fixed_buf_t stats;
|
||||
|
||||
const VpxInterface *encoder = NULL;
|
||||
const int fps = 30; // TODO(dkovalev) add command line argument
|
||||
const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument
|
||||
const int fps = 30; // TODO(dkovalev) add command line argument
|
||||
const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument
|
||||
const char *const codec_arg = argv[1];
|
||||
const char *const width_arg = argv[2];
|
||||
const char *const height_arg = argv[3];
|
||||
const char *const infile_arg = argv[4];
|
||||
const char *const outfile_arg = argv[5];
|
||||
int max_frames = 0;
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 7) die("Invalid number of arguments.");
|
||||
|
||||
max_frames = (int)strtol(argv[6], NULL, 0);
|
||||
if (argc != 6)
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
encoder = get_vpx_encoder_by_name(codec_arg);
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
if (!encoder)
|
||||
die("Unsupported codec.");
|
||||
|
||||
w = (int)strtol(width_arg, NULL, 0);
|
||||
h = (int)strtol(height_arg, NULL, 0);
|
||||
w = strtol(width_arg, NULL, 0);
|
||||
h = strtol(height_arg, NULL, 0);
|
||||
|
||||
if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0)
|
||||
if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0)
|
||||
die("Invalid frame size: %dx%d", w, h);
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, w, h, 1))
|
||||
@ -227,7 +235,8 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Configuration
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&codec, "Failed to get default codec config.");
|
||||
if (res)
|
||||
die_codec(&codec, "Failed to get default codec config.");
|
||||
|
||||
cfg.g_w = w;
|
||||
cfg.g_h = h;
|
||||
@ -240,13 +249,13 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Pass 0
|
||||
cfg.g_pass = VPX_RC_FIRST_PASS;
|
||||
stats = pass0(&raw, infile, encoder, &cfg, max_frames);
|
||||
stats = pass0(&raw, infile, encoder, &cfg);
|
||||
|
||||
// Pass 1
|
||||
rewind(infile);
|
||||
cfg.g_pass = VPX_RC_LAST_PASS;
|
||||
cfg.rc_twopass_stats_in = stats;
|
||||
pass1(&raw, infile, outfile_arg, encoder, &cfg, max_frames);
|
||||
pass1(&raw, infile, outfile_arg, encoder, &cfg);
|
||||
free(stats.buf);
|
||||
|
||||
vpx_img_free(&raw);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
// VP8 Set Reference Frame
|
||||
// =======================
|
||||
//
|
||||
@ -51,7 +52,6 @@
|
||||
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vp8/common/common.h"
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
@ -64,21 +64,25 @@ void usage_exit(void) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
|
||||
int frame_index, VpxVideoWriter *writer) {
|
||||
static int encode_frame(vpx_codec_ctx_t *codec,
|
||||
vpx_image_t *img,
|
||||
int frame_index,
|
||||
VpxVideoWriter *writer) {
|
||||
int got_pkts = 0;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(codec, img, frame_index, 1, 0, VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK) die_codec(codec, "Failed to encode frame");
|
||||
const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 0,
|
||||
VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK)
|
||||
die_codec(codec, "Failed to encode frame");
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
|
||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||
const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
|
||||
if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
if (!vpx_video_writer_write_frame(writer,
|
||||
pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
@ -94,53 +98,55 @@ static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
vpx_codec_ctx_t codec = {0};
|
||||
vpx_codec_enc_cfg_t cfg = {0};
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info;
|
||||
VpxVideoInfo info = {0};
|
||||
VpxVideoWriter *writer = NULL;
|
||||
const VpxInterface *encoder = NULL;
|
||||
int update_frame_num = 0;
|
||||
const int fps = 30; // TODO(dkovalev) add command line argument
|
||||
const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument
|
||||
|
||||
vp8_zero(codec);
|
||||
vp8_zero(cfg);
|
||||
vp8_zero(info);
|
||||
const int fps = 30; // TODO(dkovalev) add command line argument
|
||||
const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 6) die("Invalid number of arguments");
|
||||
if (argc != 6)
|
||||
die("Invalid number of arguments");
|
||||
|
||||
// TODO(dkovalev): add vp9 support and rename the file accordingly
|
||||
encoder = get_vpx_encoder_by_name("vp8");
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
if (!encoder)
|
||||
die("Unsupported codec.");
|
||||
|
||||
update_frame_num = atoi(argv[5]);
|
||||
if (!update_frame_num) die("Couldn't parse frame number '%s'\n", argv[5]);
|
||||
if (!update_frame_num)
|
||||
die("Couldn't parse frame number '%s'\n", argv[5]);
|
||||
|
||||
info.codec_fourcc = encoder->fourcc;
|
||||
info.frame_width = (int)strtol(argv[1], NULL, 0);
|
||||
info.frame_height = (int)strtol(argv[2], NULL, 0);
|
||||
info.frame_width = strtol(argv[1], NULL, 0);
|
||||
info.frame_height = strtol(argv[2], NULL, 0);
|
||||
info.time_base.numerator = 1;
|
||||
info.time_base.denominator = fps;
|
||||
|
||||
if (info.frame_width <= 0 || info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
|
||||
if (info.frame_width <= 0 ||
|
||||
info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 ||
|
||||
(info.frame_height % 2) != 0) {
|
||||
die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
|
||||
}
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
|
||||
info.frame_height, 1)) {
|
||||
info.frame_height, 1)) {
|
||||
die("Failed to allocate image.");
|
||||
}
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&codec, "Failed to get default codec config.");
|
||||
if (res)
|
||||
die_codec(&codec, "Failed to get default codec config.");
|
||||
|
||||
cfg.g_w = info.frame_width;
|
||||
cfg.g_h = info.frame_height;
|
||||
@ -149,7 +155,8 @@ int main(int argc, char **argv) {
|
||||
cfg.rc_target_bitrate = bitrate;
|
||||
|
||||
writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
|
||||
if (!writer) die("Failed to open %s for writing.", argv[4]);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing.", argv[4]);
|
||||
|
||||
if (!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading.", argv[3]);
|
||||
@ -171,15 +178,15 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
while (encode_frame(&codec, NULL, -1, writer)) {
|
||||
}
|
||||
while (encode_frame(&codec, NULL, -1, writer)) {}
|
||||
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
printf("Processed %d frames.\n", frame_count);
|
||||
|
||||
vpx_img_free(&raw);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vp9/common/vp9_common.h"
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
@ -22,28 +21,32 @@
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr,
|
||||
"vp9_lossless_encoder: Example demonstrating VP9 lossless "
|
||||
"encoding feature. Supports raw input only.\n");
|
||||
fprintf(stderr, "vp9_lossless_encoder: Example demonstrating VP9 lossless "
|
||||
"encoding feature. Supports raw input only.\n");
|
||||
fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
|
||||
int frame_index, int flags, VpxVideoWriter *writer) {
|
||||
static int encode_frame(vpx_codec_ctx_t *codec,
|
||||
vpx_image_t *img,
|
||||
int frame_index,
|
||||
int flags,
|
||||
VpxVideoWriter *writer) {
|
||||
int got_pkts = 0;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(codec, img, frame_index, 1, flags, VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK) die_codec(codec, "Failed to encode frame");
|
||||
const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1,
|
||||
flags, VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK)
|
||||
die_codec(codec, "Failed to encode frame");
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
|
||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||
const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
|
||||
if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
if (!vpx_video_writer_write_frame(writer,
|
||||
pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
@ -63,40 +66,43 @@ int main(int argc, char **argv) {
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info;
|
||||
VpxVideoInfo info = {0};
|
||||
VpxVideoWriter *writer = NULL;
|
||||
const VpxInterface *encoder = NULL;
|
||||
const int fps = 30;
|
||||
|
||||
vp9_zero(info);
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc < 5) die("Invalid number of arguments");
|
||||
if (argc < 5)
|
||||
die("Invalid number of arguments");
|
||||
|
||||
encoder = get_vpx_encoder_by_name("vp9");
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
if (!encoder)
|
||||
die("Unsupported codec.");
|
||||
|
||||
info.codec_fourcc = encoder->fourcc;
|
||||
info.frame_width = (int)strtol(argv[1], NULL, 0);
|
||||
info.frame_height = (int)strtol(argv[2], NULL, 0);
|
||||
info.frame_width = strtol(argv[1], NULL, 0);
|
||||
info.frame_height = strtol(argv[2], NULL, 0);
|
||||
info.time_base.numerator = 1;
|
||||
info.time_base.denominator = fps;
|
||||
|
||||
if (info.frame_width <= 0 || info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
|
||||
if (info.frame_width <= 0 ||
|
||||
info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 ||
|
||||
(info.frame_height % 2) != 0) {
|
||||
die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
|
||||
}
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
|
||||
info.frame_height, 1)) {
|
||||
info.frame_height, 1)) {
|
||||
die("Failed to allocate image.");
|
||||
}
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&codec, "Failed to get default codec config.");
|
||||
if (res)
|
||||
die_codec(&codec, "Failed to get default codec config.");
|
||||
|
||||
cfg.g_w = info.frame_width;
|
||||
cfg.g_h = info.frame_height;
|
||||
@ -104,7 +110,8 @@ int main(int argc, char **argv) {
|
||||
cfg.g_timebase.den = info.time_base.denominator;
|
||||
|
||||
writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
|
||||
if (!writer) die("Failed to open %s for writing.", argv[4]);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing.", argv[4]);
|
||||
|
||||
if (!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading.", argv[3]);
|
||||
@ -121,15 +128,15 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
while (encode_frame(&codec, NULL, -1, 0, writer)) {
|
||||
}
|
||||
while (encode_frame(&codec, NULL, -1, 0, writer)) {}
|
||||
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
printf("Processed %d frames.\n", frame_count);
|
||||
|
||||
vpx_img_free(&raw);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "../args.h"
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
@ -53,9 +54,8 @@ static const arg_def_t spatial_layers_arg =
|
||||
static const arg_def_t temporal_layers_arg =
|
||||
ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers");
|
||||
static const arg_def_t temporal_layering_mode_arg =
|
||||
ARG_DEF("tlm", "temporal-layering-mode", 1,
|
||||
"temporal layering scheme."
|
||||
"VP9E_TEMPORAL_LAYERING_MODE");
|
||||
ARG_DEF("tlm", "temporal-layering-mode", 1, "temporal layering scheme."
|
||||
"VP9E_TEMPORAL_LAYERING_MODE");
|
||||
static const arg_def_t kf_dist_arg =
|
||||
ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
|
||||
static const arg_def_t scale_factors_arg =
|
||||
@ -75,59 +75,46 @@ static const arg_def_t min_bitrate_arg =
|
||||
static const arg_def_t max_bitrate_arg =
|
||||
ARG_DEF(NULL, "max-bitrate", 1, "Maximum bitrate");
|
||||
static const arg_def_t lag_in_frame_arg =
|
||||
ARG_DEF(NULL, "lag-in-frames", 1,
|
||||
"Number of frame to input before "
|
||||
"generating any outputs");
|
||||
ARG_DEF(NULL, "lag-in-frames", 1, "Number of frame to input before "
|
||||
"generating any outputs");
|
||||
static const arg_def_t rc_end_usage_arg =
|
||||
ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
|
||||
static const arg_def_t speed_arg =
|
||||
ARG_DEF("sp", "speed", 1, "speed configuration");
|
||||
static const arg_def_t aqmode_arg =
|
||||
ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
|
||||
static const arg_def_t bitrates_arg =
|
||||
ARG_DEF("bl", "bitrates", 1, "bitrates[sl * num_tl + tl]");
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
static const struct arg_enum_list bitdepth_enum[] = {
|
||||
{ "8", VPX_BITS_8 }, { "10", VPX_BITS_10 }, { "12", VPX_BITS_12 }, { NULL, 0 }
|
||||
{"8", VPX_BITS_8},
|
||||
{"10", VPX_BITS_10},
|
||||
{"12", VPX_BITS_12},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
static const arg_def_t bitdepth_arg = ARG_DEF_ENUM(
|
||||
"d", "bit-depth", 1, "Bit depth for codec 8, 10 or 12. ", bitdepth_enum);
|
||||
static const arg_def_t bitdepth_arg =
|
||||
ARG_DEF_ENUM("d", "bit-depth", 1, "Bit depth for codec 8, 10 or 12. ",
|
||||
bitdepth_enum);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
static const arg_def_t *svc_args[] = { &frames_arg,
|
||||
&width_arg,
|
||||
&height_arg,
|
||||
&timebase_arg,
|
||||
&bitrate_arg,
|
||||
&skip_frames_arg,
|
||||
&spatial_layers_arg,
|
||||
&kf_dist_arg,
|
||||
&scale_factors_arg,
|
||||
&passes_arg,
|
||||
&pass_arg,
|
||||
&fpf_name_arg,
|
||||
&min_q_arg,
|
||||
&max_q_arg,
|
||||
&min_bitrate_arg,
|
||||
&max_bitrate_arg,
|
||||
&temporal_layers_arg,
|
||||
&temporal_layering_mode_arg,
|
||||
&lag_in_frame_arg,
|
||||
&threads_arg,
|
||||
&aqmode_arg,
|
||||
|
||||
static const arg_def_t *svc_args[] = {
|
||||
&frames_arg, &width_arg, &height_arg,
|
||||
&timebase_arg, &bitrate_arg, &skip_frames_arg, &spatial_layers_arg,
|
||||
&kf_dist_arg, &scale_factors_arg, &passes_arg, &pass_arg,
|
||||
&fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg,
|
||||
&max_bitrate_arg, &temporal_layers_arg, &temporal_layering_mode_arg,
|
||||
&lag_in_frame_arg, &threads_arg, &aqmode_arg,
|
||||
#if OUTPUT_RC_STATS
|
||||
&output_rc_stats_arg,
|
||||
&output_rc_stats_arg,
|
||||
#endif
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
&bitdepth_arg,
|
||||
&bitdepth_arg,
|
||||
#endif
|
||||
&speed_arg,
|
||||
&rc_end_usage_arg,
|
||||
&bitrates_arg,
|
||||
NULL };
|
||||
&speed_arg,
|
||||
&rc_end_usage_arg, NULL
|
||||
};
|
||||
|
||||
static const uint32_t default_frames_to_skip = 0;
|
||||
static const uint32_t default_frames_to_code = 60 * 60;
|
||||
@ -141,7 +128,7 @@ static const uint32_t default_temporal_layers = 1;
|
||||
static const uint32_t default_kf_dist = 100;
|
||||
static const uint32_t default_temporal_layering_mode = 0;
|
||||
static const uint32_t default_output_rc_stats = 0;
|
||||
static const int32_t default_speed = -1; // -1 means use library default.
|
||||
static const int32_t default_speed = -1; // -1 means use library default.
|
||||
static const uint32_t default_threads = 0; // zero means use library default.
|
||||
|
||||
typedef struct {
|
||||
@ -168,7 +155,7 @@ void usage_exit(void) {
|
||||
static void parse_command_line(int argc, const char **argv_,
|
||||
AppInput *app_input, SvcContext *svc_ctx,
|
||||
vpx_codec_enc_cfg_t *enc_cfg) {
|
||||
struct arg arg;
|
||||
struct arg arg = {0};
|
||||
char **argv = NULL;
|
||||
char **argi = NULL;
|
||||
char **argj = NULL;
|
||||
@ -178,7 +165,7 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
const char *fpf_file_name = NULL;
|
||||
unsigned int min_bitrate = 0;
|
||||
unsigned int max_bitrate = 0;
|
||||
char string_options[1024] = { 0 };
|
||||
char string_options[1024] = {0};
|
||||
|
||||
// initialize SvcContext with parameters that will be passed to vpx_svc_init
|
||||
svc_ctx->log_level = SVC_LOG_DEBUG;
|
||||
@ -242,8 +229,8 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
} else if (arg_match(&arg, &threads_arg, argi)) {
|
||||
svc_ctx->threads = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
|
||||
svc_ctx->temporal_layering_mode = enc_cfg->temporal_layering_mode =
|
||||
arg_parse_int(&arg);
|
||||
svc_ctx->temporal_layering_mode =
|
||||
enc_cfg->temporal_layering_mode = arg_parse_int(&arg);
|
||||
if (svc_ctx->temporal_layering_mode) {
|
||||
enc_cfg->g_error_resilient = 1;
|
||||
}
|
||||
@ -253,9 +240,6 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
} else if (arg_match(&arg, &scale_factors_arg, argi)) {
|
||||
snprintf(string_options, sizeof(string_options), "%s scale-factors=%s",
|
||||
string_options, arg.val);
|
||||
} else if (arg_match(&arg, &bitrates_arg, argi)) {
|
||||
snprintf(string_options, sizeof(string_options), "%s bitrates=%s",
|
||||
string_options, arg.val);
|
||||
} else if (arg_match(&arg, &passes_arg, argi)) {
|
||||
passes = arg_parse_uint(&arg);
|
||||
if (passes < 1 || passes > 2) {
|
||||
@ -294,7 +278,7 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
enc_cfg->g_input_bit_depth = 10;
|
||||
enc_cfg->g_profile = 2;
|
||||
break;
|
||||
case VPX_BITS_12:
|
||||
case VPX_BITS_12:
|
||||
enc_cfg->g_input_bit_depth = 12;
|
||||
enc_cfg->g_profile = 2;
|
||||
break;
|
||||
@ -376,8 +360,9 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
"num: %d, den: %d, bitrate: %d,\n"
|
||||
"gop size: %d\n",
|
||||
vpx_codec_iface_name(vpx_codec_vp9_cx()), app_input->frames_to_code,
|
||||
app_input->frames_to_skip, svc_ctx->spatial_layers, enc_cfg->g_w,
|
||||
enc_cfg->g_h, enc_cfg->g_timebase.num, enc_cfg->g_timebase.den,
|
||||
app_input->frames_to_skip,
|
||||
svc_ctx->spatial_layers, enc_cfg->g_w, enc_cfg->g_h,
|
||||
enc_cfg->g_timebase.num, enc_cfg->g_timebase.den,
|
||||
enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
|
||||
}
|
||||
|
||||
@ -414,7 +399,7 @@ struct RateControlStats {
|
||||
// Note: these rate control stats assume only 1 key frame in the
|
||||
// sequence (i.e., first frame only).
|
||||
static void set_rate_control_stats(struct RateControlStats *rc,
|
||||
vpx_codec_enc_cfg_t *cfg) {
|
||||
vpx_codec_enc_cfg_t *cfg) {
|
||||
unsigned int sl, tl;
|
||||
// Set the layer (cumulative) framerate and the target layer (non-cumulative)
|
||||
// per-frame-bandwidth, for the rate control encoding stats below.
|
||||
@ -423,19 +408,22 @@ static void set_rate_control_stats(struct RateControlStats *rc,
|
||||
for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
|
||||
for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
|
||||
const int layer = sl * cfg->ts_number_layers + tl;
|
||||
const int tlayer0 = sl * cfg->ts_number_layers;
|
||||
if (cfg->ts_number_layers == 1)
|
||||
rc->layer_framerate[layer] = framerate;
|
||||
else
|
||||
rc->layer_framerate[layer] = framerate / cfg->ts_rate_decimator[tl];
|
||||
rc->layer_framerate[layer] =
|
||||
framerate / cfg->ts_rate_decimator[tl];
|
||||
if (tl > 0) {
|
||||
rc->layer_pfb[layer] =
|
||||
1000.0 *
|
||||
rc->layer_pfb[layer] = 1000.0 *
|
||||
(cfg->layer_target_bitrate[layer] -
|
||||
cfg->layer_target_bitrate[layer - 1]) /
|
||||
(rc->layer_framerate[layer] - rc->layer_framerate[layer - 1]);
|
||||
cfg->layer_target_bitrate[layer - 1]) /
|
||||
(rc->layer_framerate[layer] -
|
||||
rc->layer_framerate[layer - 1]);
|
||||
} else {
|
||||
rc->layer_pfb[layer] = 1000.0 * cfg->layer_target_bitrate[layer] /
|
||||
rc->layer_framerate[layer];
|
||||
rc->layer_pfb[tlayer0] = 1000.0 *
|
||||
cfg->layer_target_bitrate[tlayer0] /
|
||||
rc->layer_framerate[tlayer0];
|
||||
}
|
||||
rc->layer_input_frames[layer] = 0;
|
||||
rc->layer_enc_frames[layer] = 0;
|
||||
@ -455,38 +443,35 @@ static void printout_rate_control_summary(struct RateControlStats *rc,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
unsigned int sl, tl;
|
||||
double perc_fluctuation = 0.0;
|
||||
int tot_num_frames = 0;
|
||||
double perc_fluctuation = 0.0;
|
||||
printf("Total number of processed frames: %d\n\n", frame_cnt - 1);
|
||||
printf("Rate control layer stats for sl%d tl%d layer(s):\n\n",
|
||||
cfg->ss_number_layers, cfg->ts_number_layers);
|
||||
cfg->ss_number_layers, cfg->ts_number_layers);
|
||||
for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
|
||||
tot_num_frames = 0;
|
||||
for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
|
||||
const int layer = sl * cfg->ts_number_layers + tl;
|
||||
const int num_dropped =
|
||||
(tl > 0)
|
||||
? (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer])
|
||||
: (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] -
|
||||
1);
|
||||
tot_num_frames += rc->layer_input_frames[layer];
|
||||
const int num_dropped = (tl > 0) ?
|
||||
(rc->layer_input_frames[layer] - rc->layer_enc_frames[layer]) :
|
||||
(rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] - 1);
|
||||
if (!sl)
|
||||
tot_num_frames += rc->layer_input_frames[layer];
|
||||
rc->layer_encoding_bitrate[layer] = 0.001 * rc->layer_framerate[layer] *
|
||||
rc->layer_encoding_bitrate[layer] /
|
||||
tot_num_frames;
|
||||
rc->layer_avg_frame_size[layer] =
|
||||
rc->layer_avg_frame_size[layer] / rc->layer_enc_frames[layer];
|
||||
rc->layer_avg_rate_mismatch[layer] = 100.0 *
|
||||
rc->layer_avg_rate_mismatch[layer] /
|
||||
rc->layer_enc_frames[layer];
|
||||
rc->layer_encoding_bitrate[layer] / tot_num_frames;
|
||||
rc->layer_avg_frame_size[layer] = rc->layer_avg_frame_size[layer] /
|
||||
rc->layer_enc_frames[layer];
|
||||
rc->layer_avg_rate_mismatch[layer] =
|
||||
100.0 * rc->layer_avg_rate_mismatch[layer] /
|
||||
rc->layer_enc_frames[layer];
|
||||
printf("For layer#: sl%d tl%d \n", sl, tl);
|
||||
printf("Bitrate (target vs actual): %d %f.0 kbps\n",
|
||||
cfg->layer_target_bitrate[layer],
|
||||
rc->layer_encoding_bitrate[layer]);
|
||||
printf("Average frame size (target vs actual): %f %f bits\n",
|
||||
rc->layer_pfb[layer], rc->layer_avg_frame_size[layer]);
|
||||
printf("Average rate_mismatch: %f\n", rc->layer_avg_rate_mismatch[layer]);
|
||||
printf(
|
||||
"Number of input frames, encoded (non-key) frames, "
|
||||
printf("Average rate_mismatch: %f\n",
|
||||
rc->layer_avg_rate_mismatch[layer]);
|
||||
printf("Number of input frames, encoded (non-key) frames, "
|
||||
"and percent dropped frames: %d %d %f.0 \n",
|
||||
rc->layer_input_frames[layer], rc->layer_enc_frames[layer],
|
||||
100.0 * num_dropped / rc->layer_input_frames[layer]);
|
||||
@ -498,17 +483,20 @@ static void printout_rate_control_summary(struct RateControlStats *rc,
|
||||
rc->variance_st_encoding_bitrate / rc->window_count -
|
||||
(rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
|
||||
perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
|
||||
rc->avg_st_encoding_bitrate;
|
||||
rc->avg_st_encoding_bitrate;
|
||||
printf("Short-time stats, for window of %d frames: \n", rc->window_size);
|
||||
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);
|
||||
printf("Num of input, num of encoded (super) frames: %d %d \n", frame_cnt,
|
||||
tot_num_frames);
|
||||
if (frame_cnt != 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,
|
||||
uint64_t sizes[8], int *count) {
|
||||
vpx_codec_err_t parse_superframe_index(const uint8_t *data,
|
||||
size_t data_sz,
|
||||
uint32_t sizes[8], int *count) {
|
||||
// A chunk ending with a byte matching 0xc0 is an invalid chunk unless
|
||||
// it is a super frame index. If the last byte of real video compression
|
||||
// data is 0xc0 the encoder must add a 0 byte. If we have the marker but
|
||||
@ -520,6 +508,7 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
marker = *(data + data_sz - 1);
|
||||
*count = 0;
|
||||
|
||||
|
||||
if ((marker & 0xe0) == 0xc0) {
|
||||
const uint32_t frames = (marker & 0x7) + 1;
|
||||
const uint32_t mag = ((marker >> 3) & 0x3) + 1;
|
||||
@ -527,7 +516,8 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
|
||||
// This chunk is marked as having a superframe index but doesn't have
|
||||
// enough data for it, thus it's an invalid superframe index.
|
||||
if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
|
||||
if (data_sz < index_sz)
|
||||
return VPX_CODEC_CORRUPT_FRAME;
|
||||
|
||||
{
|
||||
const uint8_t marker2 = *(data + data_sz - index_sz);
|
||||
@ -535,7 +525,8 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
// This chunk is marked as having a superframe index but doesn't have
|
||||
// the matching marker byte at the front of the index therefore it's an
|
||||
// invalid chunk.
|
||||
if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
|
||||
if (marker != marker2)
|
||||
return VPX_CODEC_CORRUPT_FRAME;
|
||||
}
|
||||
|
||||
{
|
||||
@ -546,7 +537,8 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
for (i = 0; i < frames; ++i) {
|
||||
uint32_t this_sz = 0;
|
||||
|
||||
for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
|
||||
for (j = 0; j < mag; ++j)
|
||||
this_sz |= (*x++) << (j * 8);
|
||||
sizes[i] = this_sz;
|
||||
}
|
||||
*count = frames;
|
||||
@ -560,52 +552,46 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
// bypass/flexible mode. The pattern corresponds to the pattern
|
||||
// VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
|
||||
// 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,
|
||||
vpx_svc_ref_frame_config_t *ref_frame_config) {
|
||||
int sl;
|
||||
for (sl = 0; sl < num_spatial_layers; ++sl) {
|
||||
if (!tl) {
|
||||
if (!sl) {
|
||||
ref_frame_config->frame_flags[sl] =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
} else {
|
||||
if (is_key_frame) {
|
||||
ref_frame_config->frame_flags[sl] =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_LAST |
|
||||
VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
} else {
|
||||
ref_frame_config->frame_flags[sl] =
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
}
|
||||
}
|
||||
} else if (tl == 1) {
|
||||
if (!sl) {
|
||||
ref_frame_config->frame_flags[sl] =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_GF;
|
||||
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_GF;
|
||||
} else {
|
||||
ref_frame_config->frame_flags[sl] =
|
||||
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;
|
||||
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_GF;
|
||||
}
|
||||
}
|
||||
if (tl == 0) {
|
||||
ref_frame_config->lst_fb_idx[sl] = sl;
|
||||
if (sl) {
|
||||
if (is_key_frame) {
|
||||
ref_frame_config->lst_fb_idx[sl] = sl - 1;
|
||||
ref_frame_config->gld_fb_idx[sl] = sl;
|
||||
} else {
|
||||
ref_frame_config->gld_fb_idx[sl] = sl - 1;
|
||||
}
|
||||
} else {
|
||||
if (sl)
|
||||
ref_frame_config->gld_fb_idx[sl] = sl - 1;
|
||||
else
|
||||
ref_frame_config->gld_fb_idx[sl] = 0;
|
||||
}
|
||||
ref_frame_config->alt_fb_idx[sl] = 0;
|
||||
} else if (tl == 1) {
|
||||
ref_frame_config->lst_fb_idx[sl] = sl;
|
||||
@ -616,9 +602,9 @@ void set_frame_flags_bypass_mode(int tl, int num_spatial_layers,
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
AppInput app_input;
|
||||
AppInput app_input = {0};
|
||||
VpxVideoWriter *writer = NULL;
|
||||
VpxVideoInfo info;
|
||||
VpxVideoInfo info = {0};
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t enc_cfg;
|
||||
SvcContext svc_ctx;
|
||||
@ -632,28 +618,26 @@ int main(int argc, const char **argv) {
|
||||
int end_of_stream = 0;
|
||||
int frames_received = 0;
|
||||
#if OUTPUT_RC_STATS
|
||||
VpxVideoWriter *outfile[VPX_SS_MAX_LAYERS] = { NULL };
|
||||
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
|
||||
struct RateControlStats rc;
|
||||
vpx_svc_layer_id_t layer_id;
|
||||
vpx_svc_ref_frame_config_t ref_frame_config;
|
||||
unsigned int sl, tl;
|
||||
int sl, tl;
|
||||
double sum_bitrate = 0.0;
|
||||
double sum_bitrate2 = 0.0;
|
||||
double framerate = 30.0;
|
||||
double framerate = 30.0;
|
||||
#endif
|
||||
struct vpx_usec_timer timer;
|
||||
int64_t cx_time = 0;
|
||||
memset(&svc_ctx, 0, sizeof(svc_ctx));
|
||||
memset(&app_input, 0, sizeof(AppInput));
|
||||
memset(&info, 0, sizeof(VpxVideoInfo));
|
||||
svc_ctx.log_print = 1;
|
||||
exec_name = argv[0];
|
||||
parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
|
||||
|
||||
// Allocate image buffer
|
||||
// Allocate image buffer
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (!vpx_img_alloc(&raw,
|
||||
enc_cfg.g_input_bit_depth == 8 ? VPX_IMG_FMT_I420
|
||||
: VPX_IMG_FMT_I42016,
|
||||
if (!vpx_img_alloc(&raw, enc_cfg.g_input_bit_depth == 8 ?
|
||||
VPX_IMG_FMT_I420 : VPX_IMG_FMT_I42016,
|
||||
enc_cfg.g_w, enc_cfg.g_h, 32)) {
|
||||
die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
|
||||
}
|
||||
@ -672,10 +656,6 @@ int main(int argc, const char **argv) {
|
||||
die("Failed to initialize encoder\n");
|
||||
|
||||
#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) {
|
||||
set_rate_control_stats(&rc, &enc_cfg);
|
||||
framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num;
|
||||
@ -688,47 +668,38 @@ int main(int argc, const char **argv) {
|
||||
|
||||
if (!(app_input.passes == 2 && app_input.pass == 1)) {
|
||||
// We don't save the bitstream for the 1st pass on two pass rate control
|
||||
writer =
|
||||
vpx_video_writer_open(app_input.output_filename, kContainerIVF, &info);
|
||||
writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF,
|
||||
&info);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing\n", app_input.output_filename);
|
||||
}
|
||||
#if OUTPUT_RC_STATS
|
||||
// Write out spatial layer stream.
|
||||
// TODO(marpan/jianj): allow for writing each spatial and temporal stream.
|
||||
// For now, just write temporal layer streams.
|
||||
// TODO(wonkap): do spatial by re-writing superframe.
|
||||
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];
|
||||
|
||||
snprintf(file_name, sizeof(file_name), "%s_s%d.ivf",
|
||||
app_input.output_filename, sl);
|
||||
outfile[sl] = vpx_video_writer_open(file_name, kContainerIVF, &info);
|
||||
if (!outfile[sl]) die("Failed to open %s for writing", file_name);
|
||||
snprintf(file_name, sizeof(file_name), "%s_t%d.ivf",
|
||||
app_input.output_filename, tl);
|
||||
outfile[tl] = vpx_video_writer_open(file_name, kContainerIVF, &info);
|
||||
if (!outfile[tl])
|
||||
die("Failed to open %s for writing", file_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// skip initial frames
|
||||
for (i = 0; i < app_input.frames_to_skip; ++i) vpx_img_read(&raw, infile);
|
||||
for (i = 0; i < app_input.frames_to_skip; ++i)
|
||||
vpx_img_read(&raw, infile);
|
||||
|
||||
if (svc_ctx.speed != -1)
|
||||
vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
|
||||
if (svc_ctx.threads) {
|
||||
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, get_msb(svc_ctx.threads));
|
||||
if (svc_ctx.threads > 1)
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 1);
|
||||
else
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 0);
|
||||
}
|
||||
if (svc_ctx.threads)
|
||||
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
|
||||
if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
|
||||
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
|
||||
if (svc_ctx.speed >= 5)
|
||||
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
|
||||
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
|
||||
while (!end_of_stream) {
|
||||
@ -757,39 +728,28 @@ int main(int argc, const char **argv) {
|
||||
// the encode for the whole superframe. The encoder will internally loop
|
||||
// over all the spatial layers for the current superframe.
|
||||
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_model() for case of periodic key frames.
|
||||
set_frame_flags_bypass_mode(layer_id.temporal_layer_id,
|
||||
svc_ctx.spatial_layers, frame_cnt == 0,
|
||||
set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id,
|
||||
svc_ctx.spatial_layers,
|
||||
frame_cnt == 0,
|
||||
&ref_frame_config);
|
||||
vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG,
|
||||
&ref_frame_config);
|
||||
// Keep track of input frames, to account for frame drops in rate control
|
||||
// stats/metrics.
|
||||
for (sl = 0; sl < (unsigned int)enc_cfg.ss_number_layers; ++sl) {
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
|
||||
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);
|
||||
res = vpx_svc_encode(
|
||||
&svc_ctx, &codec, (end_of_stream ? NULL : &raw), pts, frame_duration,
|
||||
svc_ctx.speed >= 5 ? VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY);
|
||||
res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw),
|
||||
pts, frame_duration, svc_ctx.speed >= 5 ?
|
||||
VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY);
|
||||
vpx_usec_timer_mark(&timer);
|
||||
cx_time += vpx_usec_timer_elapsed(&timer);
|
||||
|
||||
printf("%s", vpx_svc_get_message(&svc_ctx));
|
||||
fflush(stdout);
|
||||
if (res != VPX_CODEC_OK) {
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
@ -801,64 +761,53 @@ int main(int argc, const char **argv) {
|
||||
SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal;
|
||||
if (cx_pkt->data.frame.sz > 0) {
|
||||
#if OUTPUT_RC_STATS
|
||||
uint64_t sizes[8];
|
||||
uint64_t sizes_parsed[8];
|
||||
uint32_t sizes[8];
|
||||
int count = 0;
|
||||
vp9_zero(sizes);
|
||||
vp9_zero(sizes_parsed);
|
||||
#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.pts);
|
||||
#if OUTPUT_RC_STATS
|
||||
// TODO(marpan): Put this (to line728) in separate function.
|
||||
// TODO(marpan/wonkap): Put this (to line728) in separate function.
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id);
|
||||
parse_superframe_index(cx_pkt->data.frame.buf,
|
||||
cx_pkt->data.frame.sz, sizes_parsed,
|
||||
&count);
|
||||
if (enc_cfg.ss_number_layers == 1)
|
||||
sizes[0] = cx_pkt->data.frame.sz;
|
||||
cx_pkt->data.frame.sz, sizes, &count);
|
||||
// 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 !=
|
||||
VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
|
||||
int num_layers_encoded = 0;
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
sizes[sl] = 0;
|
||||
if (cx_pkt->data.frame.spatial_layer_encoded[sl]) {
|
||||
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);
|
||||
++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
|
||||
layer_id.temporal_layer_id];
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (cx_pkt->data.frame.spatial_layer_encoded[sl]) {
|
||||
for (tl = layer_id.temporal_layer_id;
|
||||
tl < enc_cfg.ts_number_layers; ++tl) {
|
||||
const int layer = sl * enc_cfg.ts_number_layers + tl;
|
||||
++rc.layer_tot_enc_frames[layer];
|
||||
rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
|
||||
// Keep count of rate control stats per layer, for non-key
|
||||
// frames.
|
||||
if (tl == (unsigned int)layer_id.temporal_layer_id &&
|
||||
!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
|
||||
rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl];
|
||||
rc.layer_avg_rate_mismatch[layer] +=
|
||||
fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) /
|
||||
rc.layer_pfb[layer];
|
||||
++rc.layer_enc_frames[layer];
|
||||
}
|
||||
for (tl = layer_id.temporal_layer_id;
|
||||
tl < enc_cfg.ts_number_layers; ++tl) {
|
||||
const int layer = sl * enc_cfg.ts_number_layers + tl;
|
||||
++rc.layer_tot_enc_frames[layer];
|
||||
rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
|
||||
// Keep count of rate control stats per layer, for non-key
|
||||
// frames.
|
||||
if (tl == layer_id.temporal_layer_id &&
|
||||
!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
|
||||
rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl];
|
||||
rc.layer_avg_rate_mismatch[layer] +=
|
||||
fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) /
|
||||
rc.layer_pfb[layer];
|
||||
++rc.layer_enc_frames[layer];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -866,10 +815,10 @@ int main(int argc, const char **argv) {
|
||||
// Update for short-time encoding bitrate states, for moving
|
||||
// window of size rc->window, shifted by rc->window / 2.
|
||||
// Ignore first window segment, due to key frame.
|
||||
if (frame_cnt > (unsigned int)rc.window_size) {
|
||||
if (frame_cnt > rc.window_size) {
|
||||
tl = layer_id.temporal_layer_id;
|
||||
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) {
|
||||
rc.window_count += 1;
|
||||
@ -882,41 +831,43 @@ int main(int argc, const char **argv) {
|
||||
}
|
||||
|
||||
// Second shifted window.
|
||||
if (frame_cnt >
|
||||
(unsigned int)(rc.window_size + rc.window_size / 2)) {
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
|
||||
}
|
||||
if (frame_cnt > rc.window_size + rc.window_size / 2) {
|
||||
tl = layer_id.temporal_layer_id;
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
|
||||
}
|
||||
|
||||
if (frame_cnt > (unsigned int)(2 * rc.window_size) &&
|
||||
frame_cnt % rc.window_size == 0) {
|
||||
rc.window_count += 1;
|
||||
rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
|
||||
rc.variance_st_encoding_bitrate +=
|
||||
(sum_bitrate2 / rc.window_size) *
|
||||
(sum_bitrate2 / rc.window_size);
|
||||
sum_bitrate2 = 0.0;
|
||||
}
|
||||
if (frame_cnt > 2 * rc.window_size &&
|
||||
frame_cnt % rc.window_size == 0) {
|
||||
rc.window_count += 1;
|
||||
rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
|
||||
rc.variance_st_encoding_bitrate +=
|
||||
(sum_bitrate2 / rc.window_size) *
|
||||
(sum_bitrate2 / rc.window_size);
|
||||
sum_bitrate2 = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
|
||||
printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
|
||||
!!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
|
||||
(int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts);
|
||||
*/
|
||||
if (enc_cfg.ss_number_layers == 1 && enc_cfg.ts_number_layers == 1)
|
||||
si->bytes_sum[0] += (int)cx_pkt->data.frame.sz;
|
||||
++frames_received;
|
||||
break;
|
||||
}
|
||||
case VPX_CODEC_STATS_PKT: {
|
||||
stats_write(&app_input.rc_stats, cx_pkt->data.twopass_stats.buf,
|
||||
stats_write(&app_input.rc_stats,
|
||||
cx_pkt->data.twopass_stats.buf,
|
||||
cx_pkt->data.twopass_stats.sz);
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -929,8 +880,8 @@ int main(int argc, const char **argv) {
|
||||
// Compensate for the extra frame count for the bypass mode.
|
||||
if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
const int layer =
|
||||
sl * enc_cfg.ts_number_layers + layer_id.temporal_layer_id;
|
||||
const int layer = sl * enc_cfg.ts_number_layers +
|
||||
layer_id.temporal_layer_id;
|
||||
--rc.layer_input_frames[layer];
|
||||
}
|
||||
}
|
||||
@ -944,23 +895,25 @@ int main(int argc, const char **argv) {
|
||||
}
|
||||
#endif
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
if (app_input.passes == 2) stats_close(&app_input.rc_stats, 1);
|
||||
if (app_input.passes == 2)
|
||||
stats_close(&app_input.rc_stats, 1);
|
||||
if (writer) {
|
||||
vpx_video_writer_close(writer);
|
||||
}
|
||||
#if OUTPUT_RC_STATS
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
vpx_video_writer_close(outfile[sl]);
|
||||
for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
|
||||
vpx_video_writer_close(outfile[tl]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
|
||||
frame_cnt, 1000 * (float)cx_time / (double)(frame_cnt * 1000000),
|
||||
frame_cnt,
|
||||
1000 * (float)cx_time / (double)(frame_cnt * 1000000),
|
||||
1000000 * (double)frame_cnt / (double)cx_time);
|
||||
vpx_img_free(&raw);
|
||||
// display average size, psnr
|
||||
vpx_svc_dump_statistics(&svc_ctx);
|
||||
printf("%s", vpx_svc_dump_statistics(&svc_ctx));
|
||||
vpx_svc_release(&svc_ctx);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -1,442 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
// VP9 Set Reference Frame
|
||||
// ============================
|
||||
//
|
||||
// This is an example demonstrating how to overwrite the VP9 encoder's
|
||||
// internal reference frame. In the sample we set the last frame to the
|
||||
// current frame. This technique could be used to bounce between two cameras.
|
||||
//
|
||||
// The decoder would also have to set the reference frame to the same value
|
||||
// on the same frame, or the video will become corrupt. The 'test_decode'
|
||||
// variable is set to 1 in this example that tests if the encoder and decoder
|
||||
// results are matching.
|
||||
//
|
||||
// Usage
|
||||
// -----
|
||||
// This example encodes a raw video. And the last argument passed in specifies
|
||||
// the frame number to update the reference frame on. For example, run
|
||||
// examples/vp9cx_set_ref 352 288 in.yuv out.ivf 4 30
|
||||
// The parameter is parsed as follows:
|
||||
//
|
||||
//
|
||||
// Extra Variables
|
||||
// ---------------
|
||||
// This example maintains the frame number passed on the command line
|
||||
// in the `update_frame_num` variable.
|
||||
//
|
||||
//
|
||||
// Configuration
|
||||
// -------------
|
||||
//
|
||||
// The reference frame is updated on the frame specified on the command
|
||||
// line.
|
||||
//
|
||||
// Observing The Effects
|
||||
// ---------------------
|
||||
// The encoder and decoder results should be matching when the same reference
|
||||
// frame setting operation is done in both encoder and decoder. Otherwise,
|
||||
// the encoder/decoder mismatch would be seen.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vp9/common/vp9_common.h"
|
||||
|
||||
#include "./tools_common.h"
|
||||
#include "./video_writer.h"
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit() {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <width> <height> <infile> <outfile> "
|
||||
"<frame> <limit(optional)>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int compare_img(const vpx_image_t *const img1,
|
||||
const vpx_image_t *const img2) {
|
||||
uint32_t l_w = img1->d_w;
|
||||
uint32_t c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
|
||||
const uint32_t c_h =
|
||||
(img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
|
||||
uint32_t i;
|
||||
int match = 1;
|
||||
|
||||
match &= (img1->fmt == img2->fmt);
|
||||
match &= (img1->d_w == img2->d_w);
|
||||
match &= (img1->d_h == img2->d_h);
|
||||
|
||||
for (i = 0; i < img1->d_h; ++i)
|
||||
match &= (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
|
||||
img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
|
||||
l_w) == 0);
|
||||
|
||||
for (i = 0; i < c_h; ++i)
|
||||
match &= (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
|
||||
img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U],
|
||||
c_w) == 0);
|
||||
|
||||
for (i = 0; i < c_h; ++i)
|
||||
match &= (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V],
|
||||
img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V],
|
||||
c_w) == 0);
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
#define mmin(a, b) ((a) < (b) ? (a) : (b))
|
||||
static void find_mismatch(const vpx_image_t *const img1,
|
||||
const vpx_image_t *const img2, int yloc[4],
|
||||
int uloc[4], int vloc[4]) {
|
||||
const uint32_t bsize = 64;
|
||||
const uint32_t bsizey = bsize >> img1->y_chroma_shift;
|
||||
const uint32_t bsizex = bsize >> img1->x_chroma_shift;
|
||||
const uint32_t c_w =
|
||||
(img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
|
||||
const uint32_t c_h =
|
||||
(img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
|
||||
int match = 1;
|
||||
uint32_t i, j;
|
||||
yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1;
|
||||
for (i = 0, match = 1; match && i < img1->d_h; i += bsize) {
|
||||
for (j = 0; match && j < img1->d_w; j += bsize) {
|
||||
int k, l;
|
||||
const int si = mmin(i + bsize, img1->d_h) - i;
|
||||
const int sj = mmin(j + bsize, img1->d_w) - j;
|
||||
for (k = 0; match && k < si; ++k) {
|
||||
for (l = 0; match && l < sj; ++l) {
|
||||
if (*(img1->planes[VPX_PLANE_Y] +
|
||||
(i + k) * img1->stride[VPX_PLANE_Y] + j + l) !=
|
||||
*(img2->planes[VPX_PLANE_Y] +
|
||||
(i + k) * img2->stride[VPX_PLANE_Y] + j + l)) {
|
||||
yloc[0] = i + k;
|
||||
yloc[1] = j + l;
|
||||
yloc[2] = *(img1->planes[VPX_PLANE_Y] +
|
||||
(i + k) * img1->stride[VPX_PLANE_Y] + j + l);
|
||||
yloc[3] = *(img2->planes[VPX_PLANE_Y] +
|
||||
(i + k) * img2->stride[VPX_PLANE_Y] + j + l);
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1;
|
||||
for (i = 0, match = 1; match && i < c_h; i += bsizey) {
|
||||
for (j = 0; match && j < c_w; j += bsizex) {
|
||||
int k, l;
|
||||
const int si = mmin(i + bsizey, c_h - i);
|
||||
const int sj = mmin(j + bsizex, c_w - j);
|
||||
for (k = 0; match && k < si; ++k) {
|
||||
for (l = 0; match && l < sj; ++l) {
|
||||
if (*(img1->planes[VPX_PLANE_U] +
|
||||
(i + k) * img1->stride[VPX_PLANE_U] + j + l) !=
|
||||
*(img2->planes[VPX_PLANE_U] +
|
||||
(i + k) * img2->stride[VPX_PLANE_U] + j + l)) {
|
||||
uloc[0] = i + k;
|
||||
uloc[1] = j + l;
|
||||
uloc[2] = *(img1->planes[VPX_PLANE_U] +
|
||||
(i + k) * img1->stride[VPX_PLANE_U] + j + l);
|
||||
uloc[3] = *(img2->planes[VPX_PLANE_U] +
|
||||
(i + k) * img2->stride[VPX_PLANE_U] + j + l);
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1;
|
||||
for (i = 0, match = 1; match && i < c_h; i += bsizey) {
|
||||
for (j = 0; match && j < c_w; j += bsizex) {
|
||||
int k, l;
|
||||
const int si = mmin(i + bsizey, c_h - i);
|
||||
const int sj = mmin(j + bsizex, c_w - j);
|
||||
for (k = 0; match && k < si; ++k) {
|
||||
for (l = 0; match && l < sj; ++l) {
|
||||
if (*(img1->planes[VPX_PLANE_V] +
|
||||
(i + k) * img1->stride[VPX_PLANE_V] + j + l) !=
|
||||
*(img2->planes[VPX_PLANE_V] +
|
||||
(i + k) * img2->stride[VPX_PLANE_V] + j + l)) {
|
||||
vloc[0] = i + k;
|
||||
vloc[1] = j + l;
|
||||
vloc[2] = *(img1->planes[VPX_PLANE_V] +
|
||||
(i + k) * img1->stride[VPX_PLANE_V] + j + l);
|
||||
vloc[3] = *(img2->planes[VPX_PLANE_V] +
|
||||
(i + k) * img2->stride[VPX_PLANE_V] + j + l);
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testing_decode(vpx_codec_ctx_t *encoder, vpx_codec_ctx_t *decoder,
|
||||
unsigned int frame_out, int *mismatch_seen) {
|
||||
vpx_image_t enc_img, dec_img;
|
||||
struct vp9_ref_frame ref_enc, ref_dec;
|
||||
|
||||
if (*mismatch_seen) return;
|
||||
|
||||
ref_enc.idx = 0;
|
||||
ref_dec.idx = 0;
|
||||
if (vpx_codec_control(encoder, VP9_GET_REFERENCE, &ref_enc))
|
||||
die_codec(encoder, "Failed to get encoder reference frame");
|
||||
enc_img = ref_enc.img;
|
||||
if (vpx_codec_control(decoder, VP9_GET_REFERENCE, &ref_dec))
|
||||
die_codec(decoder, "Failed to get decoder reference frame");
|
||||
dec_img = ref_dec.img;
|
||||
|
||||
if (!compare_img(&enc_img, &dec_img)) {
|
||||
int y[4], u[4], v[4];
|
||||
|
||||
*mismatch_seen = 1;
|
||||
|
||||
find_mismatch(&enc_img, &dec_img, y, u, v);
|
||||
printf(
|
||||
"Encode/decode mismatch on frame %d at"
|
||||
" Y[%d, %d] {%d/%d},"
|
||||
" U[%d, %d] {%d/%d},"
|
||||
" V[%d, %d] {%d/%d}",
|
||||
frame_out, y[0], y[1], y[2], y[3], u[0], u[1], u[2], u[3], v[0], v[1],
|
||||
v[2], v[3]);
|
||||
}
|
||||
|
||||
vpx_img_free(&enc_img);
|
||||
vpx_img_free(&dec_img);
|
||||
}
|
||||
|
||||
static int encode_frame(vpx_codec_ctx_t *ecodec, vpx_image_t *img,
|
||||
unsigned int frame_in, VpxVideoWriter *writer,
|
||||
int test_decode, vpx_codec_ctx_t *dcodec,
|
||||
unsigned int *frame_out, int *mismatch_seen) {
|
||||
int got_pkts = 0;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
int got_data;
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(ecodec, img, frame_in, 1, 0, VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK) die_codec(ecodec, "Failed to encode frame");
|
||||
|
||||
got_data = 0;
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(ecodec, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
|
||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||
const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
|
||||
|
||||
if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
|
||||
*frame_out += 1;
|
||||
}
|
||||
|
||||
if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(ecodec, "Failed to write compressed frame");
|
||||
}
|
||||
printf(keyframe ? "K" : ".");
|
||||
fflush(stdout);
|
||||
got_data = 1;
|
||||
|
||||
// Decode 1 frame.
|
||||
if (test_decode) {
|
||||
if (vpx_codec_decode(dcodec, pkt->data.frame.buf,
|
||||
(unsigned int)pkt->data.frame.sz, NULL, 0))
|
||||
die_codec(dcodec, "Failed to decode frame.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mismatch checking
|
||||
if (got_data && test_decode) {
|
||||
testing_decode(ecodec, dcodec, *frame_out, mismatch_seen);
|
||||
}
|
||||
|
||||
return got_pkts;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile = NULL;
|
||||
// Encoder
|
||||
vpx_codec_ctx_t ecodec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
unsigned int frame_in = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info;
|
||||
VpxVideoWriter *writer = NULL;
|
||||
const VpxInterface *encoder = NULL;
|
||||
|
||||
// Test encoder/decoder mismatch.
|
||||
int test_decode = 1;
|
||||
// Decoder
|
||||
vpx_codec_ctx_t dcodec;
|
||||
unsigned int frame_out = 0;
|
||||
|
||||
// The frame number to set reference frame on
|
||||
unsigned int update_frame_num = 0;
|
||||
int mismatch_seen = 0;
|
||||
|
||||
const int fps = 30;
|
||||
const int bitrate = 500;
|
||||
|
||||
const char *width_arg = NULL;
|
||||
const char *height_arg = NULL;
|
||||
const char *infile_arg = NULL;
|
||||
const char *outfile_arg = NULL;
|
||||
const char *update_frame_num_arg = NULL;
|
||||
unsigned int limit = 0;
|
||||
|
||||
vp9_zero(ecodec);
|
||||
vp9_zero(cfg);
|
||||
vp9_zero(info);
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc < 6) die("Invalid number of arguments");
|
||||
|
||||
width_arg = argv[1];
|
||||
height_arg = argv[2];
|
||||
infile_arg = argv[3];
|
||||
outfile_arg = argv[4];
|
||||
update_frame_num_arg = argv[5];
|
||||
|
||||
encoder = get_vpx_encoder_by_name("vp9");
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
|
||||
update_frame_num = (unsigned int)strtoul(update_frame_num_arg, NULL, 0);
|
||||
// In VP9, the reference buffers (cm->buffer_pool->frame_bufs[i].buf) are
|
||||
// allocated while calling vpx_codec_encode(), thus, setting reference for
|
||||
// 1st frame isn't supported.
|
||||
if (update_frame_num <= 1) {
|
||||
die("Couldn't parse frame number '%s'\n", update_frame_num_arg);
|
||||
}
|
||||
|
||||
if (argc > 6) {
|
||||
limit = (unsigned int)strtoul(argv[6], NULL, 0);
|
||||
if (update_frame_num > limit)
|
||||
die("Update frame number couldn't larger than limit\n");
|
||||
}
|
||||
|
||||
info.codec_fourcc = encoder->fourcc;
|
||||
info.frame_width = (int)strtol(width_arg, NULL, 0);
|
||||
info.frame_height = (int)strtol(height_arg, NULL, 0);
|
||||
info.time_base.numerator = 1;
|
||||
info.time_base.denominator = fps;
|
||||
|
||||
if (info.frame_width <= 0 || info.frame_height <= 0 ||
|
||||
(info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
|
||||
die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
|
||||
}
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
|
||||
info.frame_height, 1)) {
|
||||
die("Failed to allocate image.");
|
||||
}
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&ecodec, "Failed to get default codec config.");
|
||||
|
||||
cfg.g_w = info.frame_width;
|
||||
cfg.g_h = info.frame_height;
|
||||
cfg.g_timebase.num = info.time_base.numerator;
|
||||
cfg.g_timebase.den = info.time_base.denominator;
|
||||
cfg.rc_target_bitrate = bitrate;
|
||||
cfg.g_lag_in_frames = 3;
|
||||
|
||||
writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
|
||||
if (!writer) die("Failed to open %s for writing.", outfile_arg);
|
||||
|
||||
if (!(infile = fopen(infile_arg, "rb")))
|
||||
die("Failed to open %s for reading.", infile_arg);
|
||||
|
||||
if (vpx_codec_enc_init(&ecodec, encoder->codec_interface(), &cfg, 0))
|
||||
die_codec(&ecodec, "Failed to initialize encoder");
|
||||
|
||||
// Disable alt_ref.
|
||||
if (vpx_codec_control(&ecodec, VP8E_SET_ENABLEAUTOALTREF, 0))
|
||||
die_codec(&ecodec, "Failed to set enable auto alt ref");
|
||||
|
||||
if (test_decode) {
|
||||
const VpxInterface *decoder = get_vpx_decoder_by_name("vp9");
|
||||
if (vpx_codec_dec_init(&dcodec, decoder->codec_interface(), NULL, 0))
|
||||
die_codec(&dcodec, "Failed to initialize decoder.");
|
||||
}
|
||||
|
||||
// Encode frames.
|
||||
while (vpx_img_read(&raw, infile)) {
|
||||
if (limit && frame_in >= limit) break;
|
||||
if (update_frame_num > 1 && frame_out + 1 == update_frame_num) {
|
||||
vpx_ref_frame_t ref;
|
||||
ref.frame_type = VP8_LAST_FRAME;
|
||||
ref.img = raw;
|
||||
// Set reference frame in encoder.
|
||||
if (vpx_codec_control(&ecodec, VP8_SET_REFERENCE, &ref))
|
||||
die_codec(&ecodec, "Failed to set reference frame");
|
||||
printf(" <SET_REF>");
|
||||
|
||||
// If set_reference in decoder is commented out, the enc/dec mismatch
|
||||
// would be seen.
|
||||
if (test_decode) {
|
||||
if (vpx_codec_control(&dcodec, VP8_SET_REFERENCE, &ref))
|
||||
die_codec(&dcodec, "Failed to set reference frame");
|
||||
}
|
||||
}
|
||||
|
||||
encode_frame(&ecodec, &raw, frame_in, writer, test_decode, &dcodec,
|
||||
&frame_out, &mismatch_seen);
|
||||
frame_in++;
|
||||
if (mismatch_seen) break;
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
if (!mismatch_seen)
|
||||
while (encode_frame(&ecodec, NULL, frame_in, writer, test_decode, &dcodec,
|
||||
&frame_out, &mismatch_seen)) {
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
printf("Processed %d frames.\n", frame_out);
|
||||
|
||||
if (test_decode) {
|
||||
if (!mismatch_seen)
|
||||
printf("Encoder/decoder results are matching.\n");
|
||||
else
|
||||
printf("Encoder/decoder results are NOT matching.\n");
|
||||
}
|
||||
|
||||
if (test_decode)
|
||||
if (vpx_codec_destroy(&dcodec))
|
||||
die_codec(&dcodec, "Failed to destroy decoder");
|
||||
|
||||
vpx_img_free(&raw);
|
||||
if (vpx_codec_destroy(&ecodec))
|
||||
die_codec(&ecodec, "Failed to destroy encoder.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -22,37 +22,26 @@
|
||||
#include "../vpx_ports/vpx_timer.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx_ports/bitops.h"
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
|
||||
#define ROI_MAP 0
|
||||
|
||||
#define zero(Dest) memset(&Dest, 0, sizeof(Dest));
|
||||
|
||||
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.
|
||||
enum denoiserStateVp8 {
|
||||
kVp8DenoiserOff,
|
||||
kVp8DenoiserOnYOnly,
|
||||
kVp8DenoiserOnYUV,
|
||||
kVp8DenoiserOnYUVAggressive,
|
||||
kVp8DenoiserOnAdaptive
|
||||
// Denoiser states, for temporal denoising.
|
||||
enum denoiserState {
|
||||
kDenoiserOff,
|
||||
kDenoiserOnYOnly,
|
||||
kDenoiserOnYUV,
|
||||
kDenoiserOnYUVAggressive,
|
||||
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};
|
||||
|
||||
// For rate control encoding stats.
|
||||
struct RateControlMetrics {
|
||||
@ -97,13 +86,12 @@ static void set_rate_control_metrics(struct RateControlMetrics *rc,
|
||||
// per-frame-bandwidth, for the rate control encoding stats below.
|
||||
const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
|
||||
rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0];
|
||||
rc->layer_pfb[0] =
|
||||
1000.0 * rc->layer_target_bitrate[0] / rc->layer_framerate[0];
|
||||
rc->layer_pfb[0] = 1000.0 * rc->layer_target_bitrate[0] /
|
||||
rc->layer_framerate[0];
|
||||
for (i = 0; i < cfg->ts_number_layers; ++i) {
|
||||
if (i > 0) {
|
||||
rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
|
||||
rc->layer_pfb[i] =
|
||||
1000.0 *
|
||||
rc->layer_pfb[i] = 1000.0 *
|
||||
(rc->layer_target_bitrate[i] - rc->layer_target_bitrate[i - 1]) /
|
||||
(rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
|
||||
}
|
||||
@ -126,31 +114,29 @@ static void printout_rate_control_summary(struct RateControlMetrics *rc,
|
||||
unsigned int i = 0;
|
||||
int tot_num_frames = 0;
|
||||
double perc_fluctuation = 0.0;
|
||||
printf("Total number of processed frames: %d\n\n", frame_cnt - 1);
|
||||
printf("Total number of processed frames: %d\n\n", frame_cnt -1);
|
||||
printf("Rate control layer stats for %d layer(s):\n\n",
|
||||
cfg->ts_number_layers);
|
||||
cfg->ts_number_layers);
|
||||
for (i = 0; i < cfg->ts_number_layers; ++i) {
|
||||
const int num_dropped =
|
||||
(i > 0) ? (rc->layer_input_frames[i] - rc->layer_enc_frames[i])
|
||||
: (rc->layer_input_frames[i] - rc->layer_enc_frames[i] - 1);
|
||||
const int num_dropped = (i > 0) ?
|
||||
(rc->layer_input_frames[i] - rc->layer_enc_frames[i]) :
|
||||
(rc->layer_input_frames[i] - rc->layer_enc_frames[i] - 1);
|
||||
tot_num_frames += rc->layer_input_frames[i];
|
||||
rc->layer_encoding_bitrate[i] = 0.001 * rc->layer_framerate[i] *
|
||||
rc->layer_encoding_bitrate[i] /
|
||||
tot_num_frames;
|
||||
rc->layer_avg_frame_size[i] =
|
||||
rc->layer_avg_frame_size[i] / rc->layer_enc_frames[i];
|
||||
rc->layer_avg_rate_mismatch[i] =
|
||||
100.0 * rc->layer_avg_rate_mismatch[i] / rc->layer_enc_frames[i];
|
||||
rc->layer_encoding_bitrate[i] / tot_num_frames;
|
||||
rc->layer_avg_frame_size[i] = rc->layer_avg_frame_size[i] /
|
||||
rc->layer_enc_frames[i];
|
||||
rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] /
|
||||
rc->layer_enc_frames[i];
|
||||
printf("For layer#: %d \n", i);
|
||||
printf("Bitrate (target vs actual): %d %f \n", rc->layer_target_bitrate[i],
|
||||
rc->layer_encoding_bitrate[i]);
|
||||
printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i],
|
||||
rc->layer_avg_frame_size[i]);
|
||||
printf("Average rate_mismatch: %f \n", rc->layer_avg_rate_mismatch[i]);
|
||||
printf(
|
||||
"Number of input frames, encoded (non-key) frames, "
|
||||
"and perc dropped frames: %d %d %f \n",
|
||||
rc->layer_input_frames[i], rc->layer_enc_frames[i],
|
||||
printf("Number of input frames, encoded (non-key) frames, "
|
||||
"and perc dropped frames: %d %d %f \n", rc->layer_input_frames[i],
|
||||
rc->layer_enc_frames[i],
|
||||
100.0 * num_dropped / rc->layer_input_frames[i]);
|
||||
printf("\n");
|
||||
}
|
||||
@ -159,84 +145,16 @@ static void printout_rate_control_summary(struct RateControlMetrics *rc,
|
||||
rc->variance_st_encoding_bitrate / rc->window_count -
|
||||
(rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
|
||||
perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
|
||||
rc->avg_st_encoding_bitrate;
|
||||
printf("Short-time stats, for window of %d frames: \n", rc->window_size);
|
||||
rc->avg_st_encoding_bitrate;
|
||||
printf("Short-time stats, for window of %d frames: \n",rc->window_size);
|
||||
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);
|
||||
if ((frame_cnt - 1) != tot_num_frames)
|
||||
die("Error: Number of input frames not equal to output! \n");
|
||||
}
|
||||
|
||||
#if ROI_MAP
|
||||
static void set_roi_map(const char *enc_name, vpx_codec_enc_cfg_t *cfg,
|
||||
vpx_roi_map_t *roi) {
|
||||
unsigned int i, j;
|
||||
int block_size = 0;
|
||||
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
|
||||
// segment is 16x16 for vp8, 8x8 for vp9.
|
||||
roi->rows = (cfg->g_h + block_size - 1) / block_size;
|
||||
roi->cols = (cfg->g_w + block_size - 1) / block_size;
|
||||
|
||||
// Applies delta QP on the segment blocks, varies from -63 to 63.
|
||||
// Setting to negative means lower QP (better quality).
|
||||
// Below we set delta_q to the extreme (-63) to show strong effect.
|
||||
// VP8 uses the first 4 segments. VP9 uses all 8 segments.
|
||||
zero(roi->delta_q);
|
||||
roi->delta_q[1] = -63;
|
||||
|
||||
// Applies delta loopfilter strength on the segment blocks, varies from -63 to
|
||||
// 63. Setting to positive means stronger loopfilter. VP8 uses the first 4
|
||||
// segments. VP9 uses all 8 segments.
|
||||
zero(roi->delta_lf);
|
||||
|
||||
if (is_vp8) {
|
||||
// Applies skip encoding threshold on the segment blocks, varies from 0 to
|
||||
// UINT_MAX. Larger value means more skipping of encoding is possible.
|
||||
// This skip threshold only applies on delta frames.
|
||||
zero(roi->static_threshold);
|
||||
}
|
||||
|
||||
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.
|
||||
roi->roi_map =
|
||||
(uint8_t *)calloc(roi->rows * roi->cols, sizeof(*roi->roi_map));
|
||||
for (i = 0; i < roi->rows; ++i) {
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Temporal scaling parameters:
|
||||
// NOTE: The 3 prediction frames cannot be used interchangeably due to
|
||||
// differences in the way they are handled throughout the code. The
|
||||
@ -249,20 +167,20 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
switch (layering_mode) {
|
||||
case 0: {
|
||||
// 1-layer.
|
||||
int ids[1] = { 0 };
|
||||
int ids[1] = {0};
|
||||
cfg->ts_periodicity = 1;
|
||||
*flag_periodicity = 1;
|
||||
cfg->ts_number_layers = 1;
|
||||
cfg->ts_rate_decimator[0] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// Update L only.
|
||||
layer_flags[0] =
|
||||
VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// 2-layers, 2-frame period.
|
||||
int ids[2] = { 0, 1 };
|
||||
int ids[2] = {0, 1};
|
||||
cfg->ts_periodicity = 2;
|
||||
*flag_periodicity = 2;
|
||||
cfg->ts_number_layers = 2;
|
||||
@ -271,24 +189,22 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
#if 1
|
||||
// 0=L, 1=GF, Intra-layer prediction enabled.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF;
|
||||
layer_flags[1] =
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF;
|
||||
#else
|
||||
// 0=L, 1=GF, Intra-layer prediction disabled.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
|
||||
layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
|
||||
VP8_EFLAG_NO_REF_ARF;
|
||||
#else
|
||||
// 0=L, 1=GF, Intra-layer prediction disabled.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
|
||||
layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// 2-layers, 3-frame period.
|
||||
int ids[3] = { 0, 1, 1 };
|
||||
int ids[3] = {0, 1, 1};
|
||||
cfg->ts_periodicity = 3;
|
||||
*flag_periodicity = 3;
|
||||
cfg->ts_number_layers = 2;
|
||||
@ -296,17 +212,16 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
cfg->ts_rate_decimator[1] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, Intra-layer prediction enabled.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] = layer_flags[2] =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] =
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// 3-layers, 6-frame period.
|
||||
int ids[6] = { 0, 2, 2, 1, 2, 2 };
|
||||
int ids[6] = {0, 2, 2, 1, 2, 2};
|
||||
cfg->ts_periodicity = 6;
|
||||
*flag_periodicity = 6;
|
||||
cfg->ts_number_layers = 3;
|
||||
@ -315,18 +230,19 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
cfg->ts_rate_decimator[2] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[3] =
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[1] = layer_flags[2] = layer_flags[4] = layer_flags[5] =
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[1] =
|
||||
layer_flags[2] =
|
||||
layer_flags[4] =
|
||||
layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
int ids[4] = {0, 2, 1, 2};
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
cfg->ts_number_layers = 3;
|
||||
@ -335,41 +251,39 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
cfg->ts_rate_decimator[2] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[1] = layer_flags[3] =
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[1] =
|
||||
layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
int ids[4] = {0, 2, 1, 2};
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
cfg->ts_number_layers = 3;
|
||||
cfg->ts_number_layers = 3;
|
||||
cfg->ts_rate_decimator[0] = 4;
|
||||
cfg->ts_rate_decimator[1] = 2;
|
||||
cfg->ts_rate_decimator[2] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, disabled
|
||||
// in layer 2.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] =
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] = layer_flags[3] =
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] =
|
||||
layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
int ids[4] = {0, 2, 1, 2};
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
cfg->ts_number_layers = 3;
|
||||
@ -378,19 +292,18 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
cfg->ts_rate_decimator[2] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] =
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] = layer_flags[3] =
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] =
|
||||
layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
// NOTE: Probably of academic interest only.
|
||||
// 5-layers, 16-frame period.
|
||||
int ids[16] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4 };
|
||||
int ids[16] = {0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4};
|
||||
cfg->ts_periodicity = 16;
|
||||
*flag_periodicity = 16;
|
||||
cfg->ts_number_layers = 5;
|
||||
@ -400,21 +313,28 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
cfg->ts_rate_decimator[3] = 2;
|
||||
cfg->ts_rate_decimator[4] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF;
|
||||
layer_flags[1] = layer_flags[3] = layer_flags[5] = layer_flags[7] =
|
||||
layer_flags[9] = layer_flags[11] = layer_flags[13] = layer_flags[15] =
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] = layer_flags[6] = layer_flags[10] = layer_flags[14] =
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF;
|
||||
layer_flags[4] = layer_flags[12] =
|
||||
VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF;
|
||||
layer_flags[1] =
|
||||
layer_flags[3] =
|
||||
layer_flags[5] =
|
||||
layer_flags[7] =
|
||||
layer_flags[9] =
|
||||
layer_flags[11] =
|
||||
layer_flags[13] =
|
||||
layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] =
|
||||
layer_flags[6] =
|
||||
layer_flags[10] =
|
||||
layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF;
|
||||
layer_flags[4] =
|
||||
layer_flags[12] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
// 2-layers, with sync point at first frame of layer 1.
|
||||
int ids[2] = { 0, 1 };
|
||||
int ids[2] = {0, 1};
|
||||
cfg->ts_periodicity = 2;
|
||||
*flag_periodicity = 8;
|
||||
cfg->ts_number_layers = 2;
|
||||
@ -426,17 +346,17 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
// key frame. Sync point every 8 frames.
|
||||
|
||||
// Layer 0: predict from L and ARF, update L and G.
|
||||
layer_flags[0] =
|
||||
VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
// Layer 1: sync point: predict from L and ARF, and update G.
|
||||
layer_flags[1] =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
// Layer 0, predict from L and ARF, update L.
|
||||
layer_flags[2] =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
// Layer 1: predict from L, G and ARF, and update G.
|
||||
layer_flags[3] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
// Layer 0.
|
||||
layer_flags[4] = layer_flags[2];
|
||||
// Layer 1.
|
||||
@ -445,11 +365,11 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
layer_flags[6] = layer_flags[4];
|
||||
// Layer 1.
|
||||
layer_flags[7] = layer_flags[5];
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
// 3-layers: Sync points for layer 1 and 2 every 8 frames.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
int ids[4] = {0, 2, 1, 2};
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 8;
|
||||
cfg->ts_number_layers = 3;
|
||||
@ -458,21 +378,20 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
cfg->ts_rate_decimator[2] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF.
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[3] = layer_flags[5] =
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[3] =
|
||||
layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[6] =
|
||||
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;
|
||||
layer_flags[6] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
@ -480,7 +399,7 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
// and is only updated on key frame.
|
||||
// Sync points for layer 1 and 2 every 8 frames.
|
||||
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
int ids[4] = {0, 2, 1, 2};
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 8;
|
||||
cfg->ts_number_layers = 3;
|
||||
@ -490,21 +409,21 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF.
|
||||
// Layer 0: predict from L and ARF; update L and G.
|
||||
layer_flags[0] =
|
||||
VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
|
||||
layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_REF_GF;
|
||||
// Layer 2: sync point: predict from L and ARF; update none.
|
||||
layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
// Layer 1: sync point: predict from L and ARF; update G.
|
||||
layer_flags[2] =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST;
|
||||
// Layer 2: predict from L, G, ARF; update none.
|
||||
layer_flags[3] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
// Layer 0: predict from L and ARF; update L.
|
||||
layer_flags[4] =
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
|
||||
layer_flags[4] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_REF_GF;
|
||||
// Layer 2: predict from L, G, ARF; update none.
|
||||
layer_flags[5] = layer_flags[3];
|
||||
// Layer 1: predict from L, G, ARF; update G.
|
||||
@ -519,7 +438,7 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
// This was added to compare with vp9_spatial_svc_encoder.
|
||||
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
int ids[4] = {0, 2, 1, 2};
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
cfg->ts_number_layers = 3;
|
||||
@ -529,20 +448,20 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled.
|
||||
layer_flags[0] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
layer_flags[3] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
|
||||
break;
|
||||
}
|
||||
case 12:
|
||||
default: {
|
||||
// 3-layers structure as in case 10, but no sync/refresh points for
|
||||
// layer 1 and 2.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
int ids[4] = {0, 2, 1, 2};
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 8;
|
||||
cfg->ts_number_layers = 3;
|
||||
@ -552,15 +471,15 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF, 2=ARF.
|
||||
// Layer 0: predict from L and ARF; update L.
|
||||
layer_flags[0] =
|
||||
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
|
||||
layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_REF_GF;
|
||||
layer_flags[4] = layer_flags[0];
|
||||
// Layer 1: predict from L, G, ARF; update G.
|
||||
layer_flags[2] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
layer_flags[6] = layer_flags[2];
|
||||
// Layer 2: predict from L, G, ARF; update none.
|
||||
layer_flags[1] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
layer_flags[3] = layer_flags[1];
|
||||
layer_flags[5] = layer_flags[1];
|
||||
layer_flags[7] = layer_flags[1];
|
||||
@ -570,7 +489,7 @@ static void set_temporal_layer_pattern(int layering_mode,
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = { NULL };
|
||||
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
@ -578,26 +497,26 @@ int main(int argc, char **argv) {
|
||||
vpx_codec_err_t res;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
uint32_t error_resilient = 0;
|
||||
int speed;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
unsigned int i;
|
||||
int pts = 0; // PTS starts at 0.
|
||||
int pts = 0; // PTS starts at 0.
|
||||
int frame_duration = 1; // 1 timebase tick per frame.
|
||||
int layering_mode = 0;
|
||||
int layer_flags[VPX_TS_MAX_PERIODICITY] = { 0 };
|
||||
int layer_flags[VPX_TS_MAX_PERIODICITY] = {0};
|
||||
int flag_periodicity = 1;
|
||||
#if ROI_MAP
|
||||
vpx_roi_map_t roi;
|
||||
#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
|
||||
vpx_svc_layer_id_t layer_id = {0, 0};
|
||||
#else
|
||||
vpx_svc_layer_id_t layer_id = {0};
|
||||
#endif
|
||||
vpx_svc_layer_id_t layer_id = { 0, 0 };
|
||||
const VpxInterface *encoder = NULL;
|
||||
FILE *infile = NULL;
|
||||
struct RateControlMetrics rc;
|
||||
int64_t cx_time = 0;
|
||||
const int min_args_base = 13;
|
||||
const int min_args_base = 11;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
vpx_bit_depth_t bit_depth = VPX_BITS_8;
|
||||
int input_bit_depth = 8;
|
||||
@ -607,42 +526,37 @@ int main(int argc, char **argv) {
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
double sum_bitrate = 0.0;
|
||||
double sum_bitrate2 = 0.0;
|
||||
double framerate = 30.0;
|
||||
|
||||
zero(rc.layer_target_bitrate);
|
||||
double framerate = 30.0;
|
||||
|
||||
exec_name = argv[0];
|
||||
// Check usage and arguments.
|
||||
if (argc < min_args) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> "
|
||||
"<error_resilient> <threads> <mode> "
|
||||
"<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n",
|
||||
argv[0]);
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
|
||||
"<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n", argv[0]);
|
||||
#else
|
||||
die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> "
|
||||
"<error_resilient> <threads> <mode> "
|
||||
"<Rate_0> ... <Rate_nlayers-1> \n",
|
||||
argv[0]);
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
|
||||
"<Rate_0> ... <Rate_nlayers-1> \n", argv[0]);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
}
|
||||
|
||||
encoder = get_vpx_encoder_by_name(argv[3]);
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
if (!encoder)
|
||||
die("Unsupported codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
|
||||
width = (unsigned int)strtoul(argv[4], NULL, 0);
|
||||
height = (unsigned int)strtoul(argv[5], NULL, 0);
|
||||
width = strtol(argv[4], NULL, 0);
|
||||
height = strtol(argv[5], NULL, 0);
|
||||
if (width < 16 || width % 2 || height < 16 || height % 2) {
|
||||
die("Invalid resolution: %d x %d", width, height);
|
||||
}
|
||||
|
||||
layering_mode = (int)strtol(argv[12], NULL, 0);
|
||||
layering_mode = strtol(argv[10], NULL, 0);
|
||||
if (layering_mode < 0 || layering_mode > 13) {
|
||||
die("Invalid layering mode (0..12) %s", argv[12]);
|
||||
die("Invalid layering mode (0..12) %s", argv[10]);
|
||||
}
|
||||
|
||||
if (argc != min_args + mode_to_num_layers[layering_mode]) {
|
||||
@ -650,7 +564,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
switch (strtol(argv[argc - 1], NULL, 0)) {
|
||||
switch (strtol(argv[argc-1], NULL, 0)) {
|
||||
case 8:
|
||||
bit_depth = VPX_BITS_8;
|
||||
input_bit_depth = 8;
|
||||
@ -663,11 +577,13 @@ int main(int argc, char **argv) {
|
||||
bit_depth = VPX_BITS_12;
|
||||
input_bit_depth = 12;
|
||||
break;
|
||||
default: die("Invalid bit depth (8, 10, 12) %s", argv[argc - 1]);
|
||||
default:
|
||||
die("Invalid bit depth (8, 10, 12) %s", argv[argc-1]);
|
||||
}
|
||||
if (!vpx_img_alloc(
|
||||
&raw, bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_I42016,
|
||||
width, height, 32)) {
|
||||
if (!vpx_img_alloc(&raw,
|
||||
bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 :
|
||||
VPX_IMG_FMT_I42016,
|
||||
width, height, 32)) {
|
||||
die("Failed to allocate image", width, height);
|
||||
}
|
||||
#else
|
||||
@ -696,32 +612,34 @@ int main(int argc, char **argv) {
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
// Timebase format e.g. 30fps: numerator=1, demoninator = 30.
|
||||
cfg.g_timebase.num = (int)strtol(argv[6], NULL, 0);
|
||||
cfg.g_timebase.den = (int)strtol(argv[7], NULL, 0);
|
||||
cfg.g_timebase.num = strtol(argv[6], NULL, 0);
|
||||
cfg.g_timebase.den = strtol(argv[7], NULL, 0);
|
||||
|
||||
speed = (int)strtol(argv[8], NULL, 0);
|
||||
speed = strtol(argv[8], NULL, 0);
|
||||
if (speed < 0) {
|
||||
die("Invalid speed setting: must be positive");
|
||||
}
|
||||
|
||||
for (i = min_args_base;
|
||||
(int)i < min_args_base + mode_to_num_layers[layering_mode]; ++i) {
|
||||
rc.layer_target_bitrate[i - 13] = (int)strtol(argv[i], NULL, 0);
|
||||
(int)i < min_args_base + mode_to_num_layers[layering_mode];
|
||||
++i) {
|
||||
rc.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
|
||||
if (strncmp(encoder->name, "vp8", 3) == 0)
|
||||
cfg.ts_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
|
||||
cfg.ts_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
|
||||
else if (strncmp(encoder->name, "vp9", 3) == 0)
|
||||
cfg.layer_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
|
||||
cfg.layer_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
|
||||
}
|
||||
|
||||
// Real time parameters.
|
||||
cfg.rc_dropframe_thresh = (unsigned int)strtoul(argv[9], NULL, 0);
|
||||
cfg.rc_dropframe_thresh = strtol(argv[9], NULL, 0);
|
||||
cfg.rc_end_usage = VPX_CBR;
|
||||
cfg.rc_min_quantizer = 2;
|
||||
cfg.rc_max_quantizer = 56;
|
||||
if (strncmp(encoder->name, "vp9", 3) == 0) cfg.rc_max_quantizer = 52;
|
||||
if (strncmp(encoder->name, "vp9", 3) == 0)
|
||||
cfg.rc_max_quantizer = 52;
|
||||
cfg.rc_undershoot_pct = 50;
|
||||
cfg.rc_overshoot_pct = 50;
|
||||
cfg.rc_buf_initial_sz = 600;
|
||||
cfg.rc_buf_initial_sz = 500;
|
||||
cfg.rc_buf_optimal_sz = 600;
|
||||
cfg.rc_buf_sz = 1000;
|
||||
|
||||
@ -729,15 +647,11 @@ int main(int argc, char **argv) {
|
||||
cfg.rc_resize_allowed = 0;
|
||||
|
||||
// Use 1 thread as default.
|
||||
cfg.g_threads = (unsigned int)strtoul(argv[11], NULL, 0);
|
||||
cfg.g_threads = 1;
|
||||
|
||||
error_resilient = (uint32_t)strtoul(argv[10], NULL, 0);
|
||||
if (error_resilient != 0 && error_resilient != 1) {
|
||||
die("Invalid value for error resilient (0, 1): %d.", error_resilient);
|
||||
}
|
||||
// Enable error resilient mode.
|
||||
cfg.g_error_resilient = error_resilient;
|
||||
cfg.g_lag_in_frames = 0;
|
||||
cfg.g_error_resilient = 1;
|
||||
cfg.g_lag_in_frames = 0;
|
||||
cfg.kf_mode = VPX_KF_AUTO;
|
||||
|
||||
// Disable automatic keyframe placement.
|
||||
@ -745,7 +659,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
|
||||
|
||||
set_temporal_layer_pattern(layering_mode, &cfg, layer_flags,
|
||||
set_temporal_layer_pattern(layering_mode,
|
||||
&cfg,
|
||||
layer_flags,
|
||||
&flag_periodicity);
|
||||
|
||||
set_rate_control_metrics(&rc, &cfg);
|
||||
@ -772,14 +688,15 @@ int main(int argc, char **argv) {
|
||||
|
||||
snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
|
||||
outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
|
||||
if (!outfile[i]) die("Failed to open %s for writing", file_name);
|
||||
if (!outfile[i])
|
||||
die("Failed to open %s for writing", file_name);
|
||||
|
||||
assert(outfile[i] != NULL);
|
||||
}
|
||||
// No spatial layers in this encoder.
|
||||
cfg.ss_number_layers = 1;
|
||||
|
||||
// Initialize codec.
|
||||
// Initialize codec.
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (vpx_codec_enc_init(
|
||||
&codec, encoder->codec_interface(), &cfg,
|
||||
@ -791,40 +708,18 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (strncmp(encoder->name, "vp8", 3) == 0) {
|
||||
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_GF_CBR_BOOST_PCT, 0);
|
||||
#if ROI_MAP
|
||||
set_roi_map(encoder->name, &cfg, &roi);
|
||||
if (vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))
|
||||
die_codec(&codec, "Failed to set ROI map");
|
||||
#endif
|
||||
|
||||
} else if (strncmp(encoder->name, "vp9", 3) == 0) {
|
||||
vpx_svc_extra_cfg_t svc_params;
|
||||
memset(&svc_params, 0, sizeof(svc_params));
|
||||
vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
|
||||
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
|
||||
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_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, VP9E_SET_TUNE_CONTENT, 0);
|
||||
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, get_msb(cfg.g_threads));
|
||||
#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
|
||||
// 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))
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 1);
|
||||
else
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 0);
|
||||
if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1 : 0))
|
||||
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
|
||||
if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0))
|
||||
die_codec(&codec, "Failed to set SVC");
|
||||
for (i = 0; i < cfg.ts_number_layers; ++i) {
|
||||
svc_params.max_quantizers[i] = cfg.rc_max_quantizer;
|
||||
@ -842,7 +737,7 @@ int main(int argc, char **argv) {
|
||||
// For generating smaller key frames, use a smaller max_intra_size_pct
|
||||
// value, like 100 or 200.
|
||||
{
|
||||
const int max_intra_size_pct = 1000;
|
||||
const int max_intra_size_pct = 900;
|
||||
vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
||||
max_intra_size_pct);
|
||||
}
|
||||
@ -852,8 +747,10 @@ int main(int argc, char **argv) {
|
||||
struct vpx_usec_timer timer;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
|
||||
// Update the temporal layer_id. No spatial layers in this test.
|
||||
layer_id.spatial_layer_id = 0;
|
||||
#endif
|
||||
layer_id.temporal_layer_id =
|
||||
cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
|
||||
if (strncmp(encoder->name, "vp9", 3) == 0) {
|
||||
@ -863,12 +760,14 @@ int main(int argc, char **argv) {
|
||||
layer_id.temporal_layer_id);
|
||||
}
|
||||
flags = layer_flags[frame_cnt % flag_periodicity];
|
||||
if (layering_mode == 0) flags = 0;
|
||||
if (layering_mode == 0)
|
||||
flags = 0;
|
||||
frame_avail = vpx_img_read(&raw, infile);
|
||||
if (frame_avail) ++rc.layer_input_frames[layer_id.temporal_layer_id];
|
||||
if (frame_avail)
|
||||
++rc.layer_input_frames[layer_id.temporal_layer_id];
|
||||
vpx_usec_timer_start(&timer);
|
||||
if (vpx_codec_encode(&codec, frame_avail ? &raw : NULL, pts, 1, flags,
|
||||
VPX_DL_REALTIME)) {
|
||||
if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 1, flags,
|
||||
VPX_DL_REALTIME)) {
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
}
|
||||
vpx_usec_timer_mark(&timer);
|
||||
@ -878,12 +777,12 @@ int main(int argc, char **argv) {
|
||||
layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
|
||||
}
|
||||
got_data = 0;
|
||||
while ((pkt = vpx_codec_get_cx_data(&codec, &iter))) {
|
||||
while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch (pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
|
||||
i < cfg.ts_number_layers; ++i) {
|
||||
i < cfg.ts_number_layers; ++i) {
|
||||
vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
|
||||
pkt->data.frame.sz, pts);
|
||||
++rc.layer_tot_enc_frames[i];
|
||||
@ -926,7 +825,8 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
++frame_cnt;
|
||||
@ -936,17 +836,17 @@ int main(int argc, char **argv) {
|
||||
printout_rate_control_summary(&rc, &cfg, frame_cnt);
|
||||
printf("\n");
|
||||
printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
|
||||
frame_cnt, 1000 * (float)cx_time / (double)(frame_cnt * 1000000),
|
||||
1000000 * (double)frame_cnt / (double)cx_time);
|
||||
frame_cnt,
|
||||
1000 * (float)cx_time / (double)(frame_cnt * 1000000),
|
||||
1000000 * (double)frame_cnt / (double)cx_time);
|
||||
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
// Try to rewrite the output file headers with the actual frame count.
|
||||
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);
|
||||
#if ROI_MAP
|
||||
free(roi.roi_map);
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
14
ivfdec.c
14
ivfdec.c
@ -23,7 +23,7 @@ static void fix_framerate(int *num, int *den) {
|
||||
// we can guess the framerate using only the timebase in this
|
||||
// case. Other files would require reading ahead to guess the
|
||||
// timebase, like we do for webm.
|
||||
if (*den > 0 && *den < 1000000000 && *num > 0 && *num < 1000) {
|
||||
if (*num < 1000) {
|
||||
// Correct for the factor of 2 applied to the timebase in the encoder.
|
||||
if (*num & 1)
|
||||
*den *= 2;
|
||||
@ -46,8 +46,7 @@ int file_is_ivf(struct VpxInputContext *input_ctx) {
|
||||
is_ivf = 1;
|
||||
|
||||
if (mem_get_le16(raw_hdr + 4) != 0) {
|
||||
fprintf(stderr,
|
||||
"Error: Unrecognized IVF version! This file may not"
|
||||
fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
|
||||
" decode properly.");
|
||||
}
|
||||
|
||||
@ -70,13 +69,14 @@ int file_is_ivf(struct VpxInputContext *input_ctx) {
|
||||
return is_ivf;
|
||||
}
|
||||
|
||||
int ivf_read_frame(FILE *infile, uint8_t **buffer, size_t *bytes_read,
|
||||
size_t *buffer_size) {
|
||||
char raw_header[IVF_FRAME_HDR_SZ] = { 0 };
|
||||
int ivf_read_frame(FILE *infile, uint8_t **buffer,
|
||||
size_t *bytes_read, size_t *buffer_size) {
|
||||
char raw_header[IVF_FRAME_HDR_SZ] = {0};
|
||||
size_t frame_size = 0;
|
||||
|
||||
if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) != 1) {
|
||||
if (!feof(infile)) warn("Failed to read frame size\n");
|
||||
if (!feof(infile))
|
||||
warn("Failed to read frame size\n");
|
||||
} else {
|
||||
frame_size = mem_get_le32(raw_header);
|
||||
|
||||
|
6
ivfdec.h
6
ivfdec.h
@ -18,11 +18,11 @@ extern "C" {
|
||||
|
||||
int file_is_ivf(struct VpxInputContext *input);
|
||||
|
||||
int ivf_read_frame(FILE *infile, uint8_t **buffer, size_t *bytes_read,
|
||||
size_t *buffer_size);
|
||||
int ivf_read_frame(FILE *infile, uint8_t **buffer,
|
||||
size_t *bytes_read, size_t *buffer_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // IVFDEC_H_
|
||||
|
6
ivfenc.c
6
ivfenc.c
@ -13,8 +13,10 @@
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx_ports/mem_ops.h"
|
||||
|
||||
void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
|
||||
unsigned int fourcc, int frame_cnt) {
|
||||
void ivf_write_file_header(FILE *outfile,
|
||||
const struct vpx_codec_enc_cfg *cfg,
|
||||
unsigned int fourcc,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
header[0] = 'D';
|
||||
|
8
ivfenc.h
8
ivfenc.h
@ -19,15 +19,17 @@ struct vpx_codec_cx_pkt;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
|
||||
uint32_t fourcc, int frame_cnt);
|
||||
void ivf_write_file_header(FILE *outfile,
|
||||
const struct vpx_codec_enc_cfg *cfg,
|
||||
uint32_t fourcc,
|
||||
int frame_cnt);
|
||||
|
||||
void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size);
|
||||
|
||||
void ivf_write_frame_size(FILE *outfile, size_t frame_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // IVFENC_H_
|
||||
|
@ -943,6 +943,18 @@ GENERATE_XML = NO
|
||||
|
||||
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
|
||||
# dump the program listings (including syntax highlighting
|
||||
# and cross-referencing information) to the XML output. Note that
|
||||
|
103
libs.mk
103
libs.mk
@ -12,7 +12,7 @@
|
||||
# ARM assembly files are written in RVCT-style. We use some make magic to
|
||||
# filter those files to allow GCC compilation
|
||||
ifeq ($(ARCH_ARM),yes)
|
||||
ASM:=$(if $(filter yes,$(CONFIG_GCC)$(CONFIG_MSVS)),.asm.S,.asm)
|
||||
ASM:=$(if $(filter yes,$(CONFIG_GCC)$(CONFIG_MSVS)),.asm.s,.asm)
|
||||
else
|
||||
ASM:=.asm
|
||||
endif
|
||||
@ -88,7 +88,7 @@ ifeq ($(CONFIG_VP9_ENCODER),yes)
|
||||
CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_CX_EXPORTS))
|
||||
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/svc_context.h
|
||||
INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h
|
||||
INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/%
|
||||
CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
|
||||
CODEC_DOC_SECTIONS += vp9 vp9_encoder
|
||||
@ -106,6 +106,43 @@ ifeq ($(CONFIG_VP9_DECODER),yes)
|
||||
CODEC_DOC_SECTIONS += vp9 vp9_decoder
|
||||
endif
|
||||
|
||||
VP9_PREFIX=vp9/
|
||||
$(BUILD_PFX)$(VP9_PREFIX)%.c.o: CFLAGS += -Wextra
|
||||
|
||||
# VP10 make file
|
||||
ifeq ($(CONFIG_VP10),yes)
|
||||
VP10_PREFIX=vp10/
|
||||
include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10_common.mk
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_VP10_ENCODER),yes)
|
||||
VP10_PREFIX=vp10/
|
||||
include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10cx.mk
|
||||
CODEC_SRCS-yes += $(addprefix $(VP10_PREFIX),$(call enabled,VP10_CX_SRCS))
|
||||
CODEC_EXPORTS-yes += $(addprefix $(VP10_PREFIX),$(VP10_CX_EXPORTS))
|
||||
CODEC_SRCS-yes += $(VP10_PREFIX)vp10cx.mk vpx/vp8.h vpx/vp8cx.h
|
||||
INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
|
||||
INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h
|
||||
INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP10_PREFIX)/%
|
||||
CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
|
||||
CODEC_DOC_SECTIONS += vp9 vp9_encoder
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_VP10_DECODER),yes)
|
||||
VP10_PREFIX=vp10/
|
||||
include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10dx.mk
|
||||
CODEC_SRCS-yes += $(addprefix $(VP10_PREFIX),$(call enabled,VP10_DX_SRCS))
|
||||
CODEC_EXPORTS-yes += $(addprefix $(VP10_PREFIX),$(VP10_DX_EXPORTS))
|
||||
CODEC_SRCS-yes += $(VP10_PREFIX)vp10dx.mk vpx/vp8.h vpx/vp8dx.h
|
||||
INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h
|
||||
INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP10_PREFIX)/%
|
||||
CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8dx.h
|
||||
CODEC_DOC_SECTIONS += vp9 vp9_decoder
|
||||
endif
|
||||
|
||||
VP10_PREFIX=vp10/
|
||||
$(BUILD_PFX)$(VP10_PREFIX)%.c.o: CFLAGS += -Wextra
|
||||
|
||||
ifeq ($(CONFIG_ENCODERS),yes)
|
||||
CODEC_DOC_SECTIONS += encoder
|
||||
endif
|
||||
@ -113,12 +150,6 @@ ifeq ($(CONFIG_DECODERS),yes)
|
||||
CODEC_DOC_SECTIONS += decoder
|
||||
endif
|
||||
|
||||
# Suppress -Wextra warnings in third party code.
|
||||
$(BUILD_PFX)third_party/googletest/%.cc.o: CXXFLAGS += -Wno-missing-field-initializers
|
||||
# Suppress -Wextra warnings in first party code pending investigation.
|
||||
# https://bugs.chromium.org/p/webm/issues/detail?id=1069
|
||||
$(BUILD_PFX)vp8/encoder/onyx_if.c.o: CFLAGS += -Wno-unknown-warning-option -Wno-clobbered
|
||||
$(BUILD_PFX)vp8/decoder/onyxd_if.c.o: CFLAGS += -Wno-unknown-warning-option -Wno-clobbered
|
||||
|
||||
ifeq ($(CONFIG_MSVS),yes)
|
||||
CODEC_LIB=$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd)
|
||||
@ -149,11 +180,12 @@ CODEC_SRCS-yes += $(BUILD_PFX)vpx_config.c
|
||||
INSTALL-SRCS-no += $(BUILD_PFX)vpx_config.c
|
||||
ifeq ($(ARCH_X86)$(ARCH_X86_64),yes)
|
||||
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += third_party/x86inc/x86inc.asm
|
||||
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += vpx_dsp/x86/bitdepth_conversion_sse2.asm
|
||||
endif
|
||||
CODEC_EXPORTS-yes += vpx/exports_com
|
||||
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
|
||||
|
||||
INSTALL-LIBS-yes += include/vpx/vpx_codec.h
|
||||
@ -186,13 +218,6 @@ libvpx_srcs.txt:
|
||||
@echo $(CODEC_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@
|
||||
CLEAN-OBJS += libvpx_srcs.txt
|
||||
|
||||
# Assembly files that are included, but don't define symbols themselves.
|
||||
# Filtered out to avoid Windows build warnings.
|
||||
ASM_INCLUDES := \
|
||||
third_party/x86inc/x86inc.asm \
|
||||
vpx_config.asm \
|
||||
vpx_ports/x86_abi_support.asm \
|
||||
vpx_dsp/x86/bitdepth_conversion_sse2.asm \
|
||||
|
||||
ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
|
||||
ifeq ($(CONFIG_MSVS),yes)
|
||||
@ -204,7 +229,12 @@ vpx.def: $(call enabled,CODEC_EXPORTS)
|
||||
--out=$@ $^
|
||||
CLEAN-OBJS += vpx.def
|
||||
|
||||
vpx.$(VCPROJ_SFX): VCPROJ_SRCS=$(filter-out $(addprefix %, $(ASM_INCLUDES)), $^)
|
||||
# Assembly files that are included, but don't define symbols themselves.
|
||||
# Filtered out to avoid Visual Studio build warnings.
|
||||
ASM_INCLUDES := \
|
||||
third_party/x86inc/x86inc.asm \
|
||||
vpx_config.asm \
|
||||
vpx_ports/x86_abi_support.asm \
|
||||
|
||||
vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def
|
||||
@echo " [CREATE] $@"
|
||||
@ -218,15 +248,7 @@ vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def
|
||||
--ver=$(CONFIG_VS_VERSION) \
|
||||
--src-path-bare="$(SRC_PATH_BARE)" \
|
||||
--out=$@ $(CFLAGS) \
|
||||
$(filter $(SRC_PATH_BARE)/vp8/%.c, $(VCPROJ_SRCS)) \
|
||||
$(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)) \
|
||||
$(filter-out $(addprefix %, $(ASM_INCLUDES)), $^) \
|
||||
--src-path-bare="$(SRC_PATH_BARE)" \
|
||||
|
||||
PROJECTS-yes += vpx.$(VCPROJ_SFX)
|
||||
@ -236,12 +258,12 @@ vpx.$(VCPROJ_SFX): $(RTCD)
|
||||
|
||||
endif
|
||||
else
|
||||
LIBVPX_OBJS=$(call objs, $(filter-out $(ASM_INCLUDES), $(CODEC_SRCS)))
|
||||
LIBVPX_OBJS=$(call objs,$(CODEC_SRCS))
|
||||
OBJS-yes += $(LIBVPX_OBJS)
|
||||
LIBS-$(if yes,$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
|
||||
$(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS)
|
||||
|
||||
SO_VERSION_MAJOR := 5
|
||||
SO_VERSION_MAJOR := 3
|
||||
SO_VERSION_MINOR := 0
|
||||
SO_VERSION_PATCH := 0
|
||||
ifeq ($(filter darwin%,$(TGT_OS)),$(TGT_OS))
|
||||
@ -251,12 +273,6 @@ EXPORT_FILE := libvpx.syms
|
||||
LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, \
|
||||
libvpx.dylib )
|
||||
else
|
||||
ifeq ($(filter iphonesimulator%,$(TGT_OS)),$(TGT_OS))
|
||||
LIBVPX_SO := libvpx.$(SO_VERSION_MAJOR).dylib
|
||||
SHARED_LIB_SUF := .dylib
|
||||
EXPORT_FILE := libvpx.syms
|
||||
LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, libvpx.dylib)
|
||||
else
|
||||
ifeq ($(filter os2%,$(TGT_OS)),$(TGT_OS))
|
||||
LIBVPX_SO := libvpx$(SO_VERSION_MAJOR).dll
|
||||
SHARED_LIB_SUF := _dll.a
|
||||
@ -272,7 +288,6 @@ LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, \
|
||||
libvpx.so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
LIBS-$(CONFIG_SHARED) += $(BUILD_PFX)$(LIBVPX_SO)\
|
||||
$(notdir $(LIBVPX_SO_SYMLINKS)) \
|
||||
@ -375,7 +390,7 @@ endif
|
||||
#
|
||||
# Add assembler dependencies for configuration.
|
||||
#
|
||||
$(filter %.S.o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
|
||||
$(filter %.s.o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
|
||||
$(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
|
||||
|
||||
|
||||
@ -400,7 +415,7 @@ LIBVPX_TEST_SRCS=$(addprefix test/,$(call enabled,LIBVPX_TEST_SRCS))
|
||||
LIBVPX_TEST_BIN=./test_libvpx$(EXE_SFX)
|
||||
LIBVPX_TEST_DATA=$(addprefix $(LIBVPX_TEST_DATA_PATH)/,\
|
||||
$(call enabled,LIBVPX_TEST_DATA))
|
||||
libvpx_test_data_url=https://storage.googleapis.com/downloads.webmproject.org/test_data/libvpx/$(1)
|
||||
libvpx_test_data_url=http://downloads.webmproject.org/test_data/libvpx/$(1)
|
||||
|
||||
TEST_INTRA_PRED_SPEED_BIN=./test_intra_pred_speed$(EXE_SFX)
|
||||
TEST_INTRA_PRED_SPEED_SRCS=$(addprefix test/,$(call enabled,TEST_INTRA_PRED_SPEED_SRCS))
|
||||
@ -413,16 +428,8 @@ CLEAN-OBJS += libvpx_test_srcs.txt
|
||||
|
||||
$(LIBVPX_TEST_DATA): $(SRC_PATH_BARE)/test/test-data.sha1
|
||||
@echo " [DOWNLOAD] $@"
|
||||
# Attempt to download the file using curl, retrying once if it fails for a
|
||||
# partial file (18).
|
||||
$(qexec)( \
|
||||
trap 'rm -f $@' INT TERM; \
|
||||
curl="curl --retry 1 -L -o $@ $(call libvpx_test_data_url,$(@F))"; \
|
||||
$$curl; \
|
||||
case "$$?" in \
|
||||
18) $$curl -C -;; \
|
||||
esac \
|
||||
)
|
||||
$(qexec)trap 'rm -f $@' INT TERM &&\
|
||||
curl -L -o $@ $(call libvpx_test_data_url,$(@F))
|
||||
|
||||
testdata:: $(LIBVPX_TEST_DATA)
|
||||
$(qexec)[ -x "$$(which sha1sum)" ] && sha1sum=sha1sum;\
|
||||
|
31
md5_utils.c
31
md5_utils.c
@ -20,17 +20,19 @@
|
||||
* Still in the public domain.
|
||||
*/
|
||||
|
||||
#include <string.h> /* for memcpy() */
|
||||
#include <string.h> /* for memcpy() */
|
||||
|
||||
#include "md5_utils.h"
|
||||
|
||||
static void byteSwap(UWORD32 *buf, unsigned words) {
|
||||
static void
|
||||
byteSwap(UWORD32 *buf, unsigned words) {
|
||||
md5byte *p;
|
||||
|
||||
/* Only swap bytes for big endian machines */
|
||||
int i = 1;
|
||||
|
||||
if (*(char *)&i == 1) return;
|
||||
if (*(char *)&i == 1)
|
||||
return;
|
||||
|
||||
p = (md5byte *)buf;
|
||||
|
||||
@ -45,7 +47,8 @@ static void byteSwap(UWORD32 *buf, unsigned words) {
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(struct MD5Context *ctx) {
|
||||
void
|
||||
MD5Init(struct MD5Context *ctx) {
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
@ -59,7 +62,8 @@ void MD5Init(struct MD5Context *ctx) {
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
|
||||
void
|
||||
MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
|
||||
UWORD32 t;
|
||||
|
||||
/* Update byte count */
|
||||
@ -67,9 +71,9 @@ void MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
|
||||
t = ctx->bytes[0];
|
||||
|
||||
if ((ctx->bytes[0] = t + len) < t)
|
||||
ctx->bytes[1]++; /* Carry from low to high */
|
||||
ctx->bytes[1]++; /* Carry from low to high */
|
||||
|
||||
t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
|
||||
t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
|
||||
|
||||
if (t > len) {
|
||||
memcpy((md5byte *)ctx->in + 64 - t, buf, len);
|
||||
@ -100,7 +104,8 @@ void MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(md5byte digest[16], struct MD5Context *ctx) {
|
||||
void
|
||||
MD5Final(md5byte digest[16], struct MD5Context *ctx) {
|
||||
int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
|
||||
md5byte *p = (md5byte *)ctx->in + count;
|
||||
|
||||
@ -110,7 +115,7 @@ void MD5Final(md5byte digest[16], struct MD5Context *ctx) {
|
||||
/* Bytes of padding needed to make 56 bytes (-8..55) */
|
||||
count = 56 - 1 - count;
|
||||
|
||||
if (count < 0) { /* Padding forces an extra block */
|
||||
if (count < 0) { /* Padding forces an extra block */
|
||||
memset(p, 0, count + 8);
|
||||
byteSwap(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, ctx->in);
|
||||
@ -142,8 +147,8 @@ void MD5Final(md5byte digest[16], struct MD5Context *ctx) {
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, in, s) \
|
||||
(w += f(x, y, z) + in, w = (w << s | w >> (32 - s)) + x)
|
||||
#define MD5STEP(f,w,x,y,z,in,s) \
|
||||
(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||
|
||||
#if defined(__clang__) && defined(__has_attribute)
|
||||
#if __has_attribute(no_sanitize)
|
||||
@ -161,8 +166,8 @@ void MD5Final(md5byte digest[16], struct MD5Context *ctx) {
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
VPX_NO_UNSIGNED_OVERFLOW_CHECK void MD5Transform(UWORD32 buf[4],
|
||||
UWORD32 const in[16]) {
|
||||
VPX_NO_UNSIGNED_OVERFLOW_CHECK void
|
||||
MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) {
|
||||
register UWORD32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
|
86
rate_hist.c
86
rate_hist.c
@ -37,13 +37,7 @@ struct rate_hist {
|
||||
struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
|
||||
const vpx_rational_t *fps) {
|
||||
int i;
|
||||
struct rate_hist *hist = calloc(1, sizeof(*hist));
|
||||
|
||||
if (hist == NULL || cfg == NULL || fps == NULL || fps->num == 0 ||
|
||||
fps->den == 0) {
|
||||
destroy_rate_histogram(hist);
|
||||
return NULL;
|
||||
}
|
||||
struct rate_hist *hist = malloc(sizeof(*hist));
|
||||
|
||||
// Determine the number of samples in the buffer. Use the file's framerate
|
||||
// to determine the number of frames in rc_buf_sz milliseconds, with an
|
||||
@ -51,7 +45,8 @@ struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
|
||||
hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
|
||||
|
||||
// prevent division by zero
|
||||
if (hist->samples == 0) hist->samples = 1;
|
||||
if (hist->samples == 0)
|
||||
hist->samples = 1;
|
||||
|
||||
hist->frames = 0;
|
||||
hist->total = 0;
|
||||
@ -83,20 +78,18 @@ void update_rate_histogram(struct rate_hist *hist,
|
||||
int64_t avg_bitrate = 0;
|
||||
int64_t sum_sz = 0;
|
||||
const int64_t now = pkt->data.frame.pts * 1000 *
|
||||
(uint64_t)cfg->g_timebase.num /
|
||||
(uint64_t)cfg->g_timebase.den;
|
||||
(uint64_t)cfg->g_timebase.num /
|
||||
(uint64_t)cfg->g_timebase.den;
|
||||
|
||||
int idx;
|
||||
|
||||
if (hist == NULL || cfg == NULL || pkt == NULL) return;
|
||||
|
||||
idx = hist->frames++ % hist->samples;
|
||||
int idx = hist->frames++ % hist->samples;
|
||||
hist->pts[idx] = now;
|
||||
hist->sz[idx] = (int)pkt->data.frame.sz;
|
||||
|
||||
if (now < cfg->rc_buf_initial_sz) return;
|
||||
if (now < cfg->rc_buf_initial_sz)
|
||||
return;
|
||||
|
||||
if (!cfg->rc_target_bitrate) return;
|
||||
if (!cfg->rc_target_bitrate)
|
||||
return;
|
||||
|
||||
then = now;
|
||||
|
||||
@ -105,16 +98,20 @@ void update_rate_histogram(struct rate_hist *hist,
|
||||
const int i_idx = (i - 1) % hist->samples;
|
||||
|
||||
then = hist->pts[i_idx];
|
||||
if (now - then > cfg->rc_buf_sz) break;
|
||||
if (now - then > cfg->rc_buf_sz)
|
||||
break;
|
||||
sum_sz += hist->sz[i_idx];
|
||||
}
|
||||
|
||||
if (now == then) return;
|
||||
if (now == then)
|
||||
return;
|
||||
|
||||
avg_bitrate = sum_sz * 8 * 1000 / (now - then);
|
||||
idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000));
|
||||
if (idx < 0) idx = 0;
|
||||
if (idx > RATE_BINS - 1) idx = RATE_BINS - 1;
|
||||
if (idx < 0)
|
||||
idx = 0;
|
||||
if (idx > RATE_BINS - 1)
|
||||
idx = RATE_BINS - 1;
|
||||
if (hist->bucket[idx].low > avg_bitrate)
|
||||
hist->bucket[idx].low = (int)avg_bitrate;
|
||||
if (hist->bucket[idx].high < avg_bitrate)
|
||||
@ -123,22 +120,19 @@ void update_rate_histogram(struct rate_hist *hist,
|
||||
hist->total++;
|
||||
}
|
||||
|
||||
static int merge_hist_buckets(struct hist_bucket *bucket, int max_buckets,
|
||||
int *num_buckets) {
|
||||
static int merge_hist_buckets(struct hist_bucket *bucket,
|
||||
int max_buckets, int *num_buckets) {
|
||||
int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
|
||||
int buckets;
|
||||
int buckets = *num_buckets;
|
||||
int i;
|
||||
|
||||
assert(bucket != NULL);
|
||||
assert(num_buckets != NULL);
|
||||
|
||||
buckets = *num_buckets;
|
||||
|
||||
/* Find the extrema for this list of buckets */
|
||||
big_bucket = small_bucket = 0;
|
||||
for (i = 0; i < buckets; i++) {
|
||||
if (bucket[i].count < bucket[small_bucket].count) small_bucket = i;
|
||||
if (bucket[i].count > bucket[big_bucket].count) big_bucket = i;
|
||||
if (bucket[i].count < bucket[small_bucket].count)
|
||||
small_bucket = i;
|
||||
if (bucket[i].count > bucket[big_bucket].count)
|
||||
big_bucket = i;
|
||||
}
|
||||
|
||||
/* If we have too many buckets, merge the smallest with an adjacent
|
||||
@ -180,10 +174,13 @@ static int merge_hist_buckets(struct hist_bucket *bucket, int max_buckets,
|
||||
*/
|
||||
big_bucket = small_bucket = 0;
|
||||
for (i = 0; i < buckets; i++) {
|
||||
if (i > merge_bucket) bucket[i] = bucket[i + 1];
|
||||
if (i > merge_bucket)
|
||||
bucket[i] = bucket[i + 1];
|
||||
|
||||
if (bucket[i].count < bucket[small_bucket].count) small_bucket = i;
|
||||
if (bucket[i].count > bucket[big_bucket].count) big_bucket = i;
|
||||
if (bucket[i].count < bucket[small_bucket].count)
|
||||
small_bucket = i;
|
||||
if (bucket[i].count > bucket[big_bucket].count)
|
||||
big_bucket = i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,13 +188,11 @@ static int merge_hist_buckets(struct hist_bucket *bucket, int max_buckets,
|
||||
return bucket[big_bucket].count;
|
||||
}
|
||||
|
||||
static void show_histogram(const struct hist_bucket *bucket, int buckets,
|
||||
int total, int scale) {
|
||||
static void show_histogram(const struct hist_bucket *bucket,
|
||||
int buckets, int total, int scale) {
|
||||
const char *pat1, *pat2;
|
||||
int i;
|
||||
|
||||
assert(bucket != NULL);
|
||||
|
||||
switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) {
|
||||
case 1:
|
||||
case 2:
|
||||
@ -237,7 +232,8 @@ static void show_histogram(const struct hist_bucket *bucket, int buckets,
|
||||
|
||||
pct = (float)(100.0 * bucket[i].count / total);
|
||||
len = HIST_BAR_MAX * bucket[i].count / scale;
|
||||
if (len < 1) len = 1;
|
||||
if (len < 1)
|
||||
len = 1;
|
||||
assert(len <= HIST_BAR_MAX);
|
||||
|
||||
if (bucket[i].low == bucket[i].high)
|
||||
@ -245,7 +241,8 @@ static void show_histogram(const struct hist_bucket *bucket, int buckets,
|
||||
else
|
||||
fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
|
||||
|
||||
for (j = 0; j < HIST_BAR_MAX; j++) fprintf(stderr, j < len ? "=" : " ");
|
||||
for (j = 0; j < HIST_BAR_MAX; j++)
|
||||
fprintf(stderr, j < len ? "=" : " ");
|
||||
fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
|
||||
}
|
||||
}
|
||||
@ -271,15 +268,14 @@ void show_q_histogram(const int counts[64], int max_buckets) {
|
||||
show_histogram(bucket, buckets, total, scale);
|
||||
}
|
||||
|
||||
void show_rate_histogram(struct rate_hist *hist, const vpx_codec_enc_cfg_t *cfg,
|
||||
int max_buckets) {
|
||||
void show_rate_histogram(struct rate_hist *hist,
|
||||
const vpx_codec_enc_cfg_t *cfg, int max_buckets) {
|
||||
int i, scale;
|
||||
int buckets = 0;
|
||||
|
||||
if (hist == NULL || cfg == NULL) return;
|
||||
|
||||
for (i = 0; i < RATE_BINS; i++) {
|
||||
if (hist->bucket[i].low == INT_MAX) continue;
|
||||
if (hist->bucket[i].low == INT_MAX)
|
||||
continue;
|
||||
hist->bucket[buckets++] = hist->bucket[i];
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,6 @@
|
||||
#ifndef TEST_ACM_RANDOM_H_
|
||||
#define TEST_ACM_RANDOM_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "vpx/vpx_integer.h"
|
||||
@ -27,7 +23,9 @@ class ACMRandom {
|
||||
|
||||
explicit ACMRandom(int seed) : random_(seed) {}
|
||||
|
||||
void Reset(int seed) { random_.Reseed(seed); }
|
||||
void Reset(int seed) {
|
||||
random_.Reseed(seed);
|
||||
}
|
||||
uint16_t Rand16(void) {
|
||||
const uint32_t value =
|
||||
random_.Generate(testing::internal::Random::kMaxRange);
|
||||
@ -37,7 +35,7 @@ class ACMRandom {
|
||||
int16_t Rand9Signed(void) {
|
||||
// Use 9 bits: values between 255 (0x0FF) and -256 (0x100).
|
||||
const uint32_t value = random_.Generate(512);
|
||||
return static_cast<int16_t>(value) - 256;
|
||||
return static_cast<int16_t>(value - 256);
|
||||
}
|
||||
|
||||
uint8_t Rand8(void) {
|
||||
@ -54,18 +52,17 @@ class ACMRandom {
|
||||
return r < 128 ? r << 4 : r >> 4;
|
||||
}
|
||||
|
||||
uint32_t RandRange(const uint32_t range) {
|
||||
// testing::internal::Random::Generate provides values in the range
|
||||
// testing::internal::Random::kMaxRange.
|
||||
assert(range <= testing::internal::Random::kMaxRange);
|
||||
int PseudoUniform(int range) {
|
||||
return random_.Generate(range);
|
||||
}
|
||||
|
||||
int PseudoUniform(int range) { return random_.Generate(range); }
|
||||
int operator()(int n) {
|
||||
return PseudoUniform(n);
|
||||
}
|
||||
|
||||
int operator()(int n) { return PseudoUniform(n); }
|
||||
|
||||
static int DeterministicSeed(void) { return 0xbaba; }
|
||||
static int DeterministicSeed(void) {
|
||||
return 0xbaba;
|
||||
}
|
||||
|
||||
private:
|
||||
testing::internal::Random random_;
|
||||
|
@ -17,8 +17,8 @@
|
||||
namespace {
|
||||
|
||||
// Check if any pixel in a 16x16 macroblock varies between frames.
|
||||
int CheckMb(const vpx_image_t ¤t, const vpx_image_t &previous, int mb_r,
|
||||
int mb_c) {
|
||||
int CheckMb(const vpx_image_t ¤t, const vpx_image_t &previous,
|
||||
int mb_r, int mb_c) {
|
||||
for (int plane = 0; plane < 3; plane++) {
|
||||
int r = 16 * mb_r;
|
||||
int c0 = 16 * mb_c;
|
||||
@ -37,9 +37,8 @@ int CheckMb(const vpx_image_t ¤t, const vpx_image_t &previous, int mb_r,
|
||||
for (; r < r_top; ++r) {
|
||||
for (int c = c0; c < c_top; ++c) {
|
||||
if (current.planes[plane][current.stride[plane] * r + c] !=
|
||||
previous.planes[plane][previous.stride[plane] * r + c]) {
|
||||
previous.planes[plane][previous.stride[plane] * r + c])
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,6 @@ class ActiveMapTest
|
||||
encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
|
||||
} else if (video->frame() == 3) {
|
||||
vpx_active_map_t map = vpx_active_map_t();
|
||||
/* clang-format off */
|
||||
uint8_t active_map[9 * 13] = {
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
@ -51,7 +50,6 @@ class ActiveMapTest
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1,
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0,
|
||||
};
|
||||
/* clang-format on */
|
||||
map.cols = (kWidth + 15) / 16;
|
||||
map.rows = (kHeight + 15) / 16;
|
||||
ASSERT_EQ(map.cols, 13u);
|
||||
@ -79,8 +77,8 @@ TEST_P(ActiveMapTest, Test) {
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.kf_max_dist = 90000;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", kWidth, kHeight, 30, 1,
|
||||
0, 20);
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", kWidth, kHeight, 30,
|
||||
1, 0, 20);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
@ -13,21 +13,22 @@
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_dsp/postproc.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static const int kNoiseSize = 3072;
|
||||
|
||||
// TODO(jimbankoski): make width and height integers not unsigned.
|
||||
typedef void (*AddNoiseFunc)(uint8_t *start, const int8_t *noise,
|
||||
int blackclamp, int whiteclamp, int width,
|
||||
int height, int pitch);
|
||||
typedef void (*AddNoiseFunc)(unsigned char *start, char *noise,
|
||||
char blackclamp[16], char whiteclamp[16],
|
||||
char bothclamp[16], unsigned int width,
|
||||
unsigned int height, int pitch);
|
||||
|
||||
class AddNoiseTest : public ::testing::TestWithParam<AddNoiseFunc> {
|
||||
class AddNoiseTest
|
||||
: public ::testing::TestWithParam<AddNoiseFunc> {
|
||||
public:
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
virtual void TearDown() {
|
||||
libvpx_test::ClearSystemState();
|
||||
}
|
||||
virtual ~AddNoiseTest() {}
|
||||
};
|
||||
|
||||
@ -39,19 +40,71 @@ double stddev6(char a, char b, char c, char d, char e, char f) {
|
||||
return sqrt(v);
|
||||
}
|
||||
|
||||
// TODO(jimbankoski): The following 2 functions are duplicated in each codec.
|
||||
// For now the vp9 one has been copied into the test as is. We should normalize
|
||||
// these in vpx_dsp and not have 3 copies of these unless there is different
|
||||
// noise we add for each codec.
|
||||
|
||||
double gaussian(double sigma, double mu, double x) {
|
||||
return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
|
||||
(exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
|
||||
}
|
||||
|
||||
int setup_noise(int size_noise, char *noise) {
|
||||
char char_dist[300];
|
||||
const int ai = 4;
|
||||
const int qi = 24;
|
||||
const double sigma = ai + .5 + .6 * (63 - qi) / 63.0;
|
||||
|
||||
/* set up a lookup table of 256 entries that matches
|
||||
* a gaussian distribution with sigma determined by q.
|
||||
*/
|
||||
int next = 0;
|
||||
|
||||
for (int i = -32; i < 32; i++) {
|
||||
int a_i = (int) (0.5 + 256 * gaussian(sigma, 0, i));
|
||||
|
||||
if (a_i) {
|
||||
for (int j = 0; j < a_i; j++) {
|
||||
char_dist[next + j] = (char)(i);
|
||||
}
|
||||
|
||||
next = next + a_i;
|
||||
}
|
||||
}
|
||||
|
||||
for (; next < 256; next++)
|
||||
char_dist[next] = 0;
|
||||
|
||||
for (int i = 0; i < size_noise; i++) {
|
||||
noise[i] = char_dist[rand() & 0xff]; // NOLINT
|
||||
}
|
||||
|
||||
// Returns the most negative value in distribution.
|
||||
return char_dist[0];
|
||||
}
|
||||
|
||||
TEST_P(AddNoiseTest, CheckNoiseAdded) {
|
||||
const int width = 64;
|
||||
DECLARE_ALIGNED(16, char, blackclamp[16]);
|
||||
DECLARE_ALIGNED(16, char, whiteclamp[16]);
|
||||
DECLARE_ALIGNED(16, char, bothclamp[16]);
|
||||
const int width = 64;
|
||||
const int height = 64;
|
||||
const int image_size = width * height;
|
||||
int8_t noise[kNoiseSize];
|
||||
const int clamp = vpx_setup_noise(4.4, noise, kNoiseSize);
|
||||
uint8_t *const s =
|
||||
reinterpret_cast<uint8_t *>(vpx_calloc(image_size, sizeof(*s)));
|
||||
ASSERT_TRUE(s != NULL);
|
||||
memset(s, 99, image_size * sizeof(*s));
|
||||
char noise[3072];
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
GetParam()(s, noise, clamp, clamp, width, height, width));
|
||||
const int clamp = setup_noise(3072, noise);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
blackclamp[i] = -clamp;
|
||||
whiteclamp[i] = -clamp;
|
||||
bothclamp[i] = -2 * clamp;
|
||||
}
|
||||
|
||||
uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
|
||||
memset(s, 99, image_size);
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
|
||||
bothclamp, width, height, width));
|
||||
|
||||
// Check to make sure we don't end up having either the same or no added
|
||||
// noise either vertically or horizontally.
|
||||
@ -69,52 +122,60 @@ TEST_P(AddNoiseTest, CheckNoiseAdded) {
|
||||
// Initialize pixels in the image to 255 and check for roll over.
|
||||
memset(s, 255, image_size);
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
GetParam()(s, noise, clamp, clamp, width, height, width));
|
||||
ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
|
||||
bothclamp, width, height, width));
|
||||
|
||||
// Check to make sure don't roll over.
|
||||
for (int i = 0; i < image_size; ++i) {
|
||||
EXPECT_GT(static_cast<int>(s[i]), clamp) << "i = " << i;
|
||||
EXPECT_GT((int)s[i], 10) << "i = " << i;
|
||||
}
|
||||
|
||||
// Initialize pixels in the image to 0 and check for roll under.
|
||||
memset(s, 0, image_size);
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
GetParam()(s, noise, clamp, clamp, width, height, width));
|
||||
ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
|
||||
bothclamp, width, height, width));
|
||||
|
||||
// Check to make sure don't roll under.
|
||||
for (int i = 0; i < image_size; ++i) {
|
||||
EXPECT_LT(static_cast<int>(s[i]), 255 - clamp) << "i = " << i;
|
||||
EXPECT_LT((int)s[i], 245) << "i = " << i;
|
||||
}
|
||||
|
||||
vpx_free(s);
|
||||
}
|
||||
|
||||
TEST_P(AddNoiseTest, CheckCvsAssembly) {
|
||||
const int width = 64;
|
||||
DECLARE_ALIGNED(16, char, blackclamp[16]);
|
||||
DECLARE_ALIGNED(16, char, whiteclamp[16]);
|
||||
DECLARE_ALIGNED(16, char, bothclamp[16]);
|
||||
const int width = 64;
|
||||
const int height = 64;
|
||||
const int image_size = width * height;
|
||||
int8_t noise[kNoiseSize];
|
||||
const int clamp = vpx_setup_noise(4.4, noise, kNoiseSize);
|
||||
char noise[3072];
|
||||
|
||||
const int clamp = setup_noise(3072, noise);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
blackclamp[i] = -clamp;
|
||||
whiteclamp[i] = -clamp;
|
||||
bothclamp[i] = -2 * clamp;
|
||||
}
|
||||
|
||||
uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
|
||||
uint8_t *const d = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
|
||||
ASSERT_TRUE(s != NULL);
|
||||
ASSERT_TRUE(d != NULL);
|
||||
|
||||
memset(s, 99, image_size);
|
||||
memset(d, 99, image_size);
|
||||
|
||||
srand(0);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
GetParam()(s, noise, clamp, clamp, width, height, width));
|
||||
ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
|
||||
bothclamp, width, height, width));
|
||||
srand(0);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
vpx_plane_add_noise_c(d, noise, clamp, clamp, width, height, width));
|
||||
ASM_REGISTER_STATE_CHECK(vpx_plane_add_noise_c(d, noise, blackclamp,
|
||||
whiteclamp, bothclamp,
|
||||
width, height, width));
|
||||
|
||||
for (int i = 0; i < image_size; ++i) {
|
||||
EXPECT_EQ(static_cast<int>(s[i]), static_cast<int>(d[i])) << "i = " << i;
|
||||
EXPECT_EQ((int)s[i], (int)d[i]) << "i = " << i;
|
||||
}
|
||||
|
||||
vpx_free(d);
|
||||
@ -124,6 +185,11 @@ TEST_P(AddNoiseTest, CheckCvsAssembly) {
|
||||
INSTANTIATE_TEST_CASE_P(C, AddNoiseTest,
|
||||
::testing::Values(vpx_plane_add_noise_c));
|
||||
|
||||
#if HAVE_MMX
|
||||
INSTANTIATE_TEST_CASE_P(MMX, AddNoiseTest,
|
||||
::testing::Values(vpx_plane_add_noise_mmx));
|
||||
#endif
|
||||
|
||||
#if HAVE_SSE2
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, AddNoiseTest,
|
||||
::testing::Values(vpx_plane_add_noise_sse2));
|
||||
|
@ -1,157 +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 "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"
|
||||
|
||||
namespace {
|
||||
|
||||
class AltRefAqSegmentTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
AltRefAqSegmentTest() : EncoderTest(GET_PARAM(0)) {}
|
||||
virtual ~AltRefAqSegmentTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
InitializeConfig();
|
||||
SetMode(GET_PARAM(1));
|
||||
set_cpu_used_ = GET_PARAM(2);
|
||||
aq_mode_ = 0;
|
||||
alt_ref_aq_mode_ = 0;
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
if (video->frame() == 1) {
|
||||
encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
|
||||
encoder->Control(VP9E_SET_ALT_REF_AQ, alt_ref_aq_mode_);
|
||||
encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
|
||||
encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 100);
|
||||
}
|
||||
}
|
||||
|
||||
int set_cpu_used_;
|
||||
int aq_mode_;
|
||||
int alt_ref_aq_mode_;
|
||||
};
|
||||
|
||||
// Validate that this ALT_REF_AQ/AQ segmentation mode
|
||||
// (ALT_REF_AQ=0, AQ=0/no_aq)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ0) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
cfg_.rc_buf_optimal_sz = 500;
|
||||
cfg_.rc_buf_sz = 1000;
|
||||
cfg_.rc_target_bitrate = 300;
|
||||
|
||||
aq_mode_ = 0;
|
||||
alt_ref_aq_mode_ = 1;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
// Validate that this ALT_REF_AQ/AQ segmentation mode
|
||||
// (ALT_REF_AQ=0, AQ=1/variance_aq)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ1) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
cfg_.rc_buf_optimal_sz = 500;
|
||||
cfg_.rc_buf_sz = 1000;
|
||||
cfg_.rc_target_bitrate = 300;
|
||||
|
||||
aq_mode_ = 1;
|
||||
alt_ref_aq_mode_ = 1;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
// Validate that this ALT_REF_AQ/AQ segmentation mode
|
||||
// (ALT_REF_AQ=0, AQ=2/complexity_aq)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ2) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
cfg_.rc_buf_optimal_sz = 500;
|
||||
cfg_.rc_buf_sz = 1000;
|
||||
cfg_.rc_target_bitrate = 300;
|
||||
|
||||
aq_mode_ = 2;
|
||||
alt_ref_aq_mode_ = 1;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
// Validate that this ALT_REF_AQ/AQ segmentation mode
|
||||
// (ALT_REF_AQ=0, AQ=3/cyclicrefresh_aq)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ3) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
cfg_.rc_buf_optimal_sz = 500;
|
||||
cfg_.rc_buf_sz = 1000;
|
||||
cfg_.rc_target_bitrate = 300;
|
||||
|
||||
aq_mode_ = 3;
|
||||
alt_ref_aq_mode_ = 1;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
// Validate that this ALT_REF_AQ/AQ segmentation mode
|
||||
// (ALT_REF_AQ=0, AQ=4/equator360_aq)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ4) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
cfg_.rc_buf_initial_sz = 500;
|
||||
cfg_.rc_buf_optimal_sz = 500;
|
||||
cfg_.rc_buf_sz = 1000;
|
||||
cfg_.rc_target_bitrate = 300;
|
||||
|
||||
aq_mode_ = 4;
|
||||
alt_ref_aq_mode_ = 1;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(AltRefAqSegmentTest,
|
||||
::testing::Values(::libvpx_test::kOnePassGood,
|
||||
::libvpx_test::kTwoPassGood),
|
||||
::testing::Range(2, 5));
|
||||
} // namespace
|
@ -21,7 +21,7 @@ const int kLookAheadMin = 5;
|
||||
const int kLookAheadMax = 26;
|
||||
|
||||
class AltRefTest : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<int> {
|
||||
public ::libvpx_test::CodecTestWithParam<int> {
|
||||
protected:
|
||||
AltRefTest() : EncoderTest(GET_PARAM(0)), altref_count_(0) {}
|
||||
virtual ~AltRefTest() {}
|
||||
@ -31,7 +31,9 @@ class AltRefTest : public ::libvpx_test::EncoderTest,
|
||||
SetMode(libvpx_test::kTwoPassGood);
|
||||
}
|
||||
|
||||
virtual void BeginPassHook(unsigned int /*pass*/) { altref_count_ = 0; }
|
||||
virtual void BeginPassHook(unsigned int pass) {
|
||||
altref_count_ = 0;
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
|
||||
libvpx_test::Encoder *encoder) {
|
||||
@ -73,8 +75,11 @@ class AltRefForcedKeyTestLarge
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
AltRefForcedKeyTestLarge()
|
||||
: EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
|
||||
cpu_used_(GET_PARAM(2)), forced_kf_frame_num_(1), frame_num_(0) {}
|
||||
: EncoderTest(GET_PARAM(0)),
|
||||
encoding_mode_(GET_PARAM(1)),
|
||||
cpu_used_(GET_PARAM(2)),
|
||||
forced_kf_frame_num_(1),
|
||||
frame_num_(0) {}
|
||||
virtual ~AltRefForcedKeyTestLarge() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
@ -89,11 +94,16 @@ class AltRefForcedKeyTestLarge
|
||||
if (video->frame() == 0) {
|
||||
encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
|
||||
encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
|
||||
#if CONFIG_VP9_ENCODER
|
||||
// override test default for tile columns if necessary.
|
||||
#if CONFIG_VP9_ENCODER
|
||||
if (GET_PARAM(0) == &libvpx_test::kVP9) {
|
||||
encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_VP10_ENCODER
|
||||
if (GET_PARAM(0) == &libvpx_test::kVP10) {
|
||||
encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
frame_flags_ =
|
||||
@ -142,11 +152,19 @@ TEST_P(AltRefForcedKeyTestLarge, ForcedFrameIsKey) {
|
||||
}
|
||||
}
|
||||
|
||||
VP8_INSTANTIATE_TEST_CASE(AltRefForcedKeyTestLarge,
|
||||
::testing::Values(::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 9));
|
||||
VP8_INSTANTIATE_TEST_CASE(
|
||||
AltRefForcedKeyTestLarge,
|
||||
::testing::Values(::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 9));
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(
|
||||
AltRefForcedKeyTestLarge,
|
||||
::testing::Values(::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 9));
|
||||
|
||||
VP10_INSTANTIATE_TEST_CASE(
|
||||
AltRefForcedKeyTestLarge,
|
||||
::testing::Values(::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 9));
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(AltRefForcedKeyTestLarge,
|
||||
::testing::Values(::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 9));
|
||||
} // namespace
|
||||
|
@ -32,7 +32,6 @@ LOCAL_CPP_EXTENSION := .cc
|
||||
LOCAL_MODULE := gtest
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/third_party/googletest/src/
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/third_party/googletest/src/include/
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/third_party/googletest/src/include/
|
||||
LOCAL_SRC_FILES := ./third_party/googletest/src/src/gtest-all.cc
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
@ -57,7 +57,7 @@ TEST_P(AqSegmentTest, TestNoMisMatchAQ1) {
|
||||
aq_mode_ = 1;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
@ -77,7 +77,7 @@ TEST_P(AqSegmentTest, TestNoMisMatchAQ2) {
|
||||
aq_mode_ = 2;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
@ -97,7 +97,7 @@ TEST_P(AqSegmentTest, TestNoMisMatchAQ3) {
|
||||
aq_mode_ = 3;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
400
test/avg_test.cc
400
test/avg_test.cc
@ -14,7 +14,6 @@
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vp9_rtcd.h"
|
||||
#include "./vpx_config.h"
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
|
||||
@ -23,7 +22,6 @@
|
||||
#include "test/register_state_check.h"
|
||||
#include "test/util.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#include "vpx_ports/vpx_timer.h"
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
@ -33,7 +31,7 @@ class AverageTestBase : public ::testing::Test {
|
||||
AverageTestBase(int width, int height) : width_(width), height_(height) {}
|
||||
|
||||
static void SetUpTestCase() {
|
||||
source_data_ = reinterpret_cast<uint8_t *>(
|
||||
source_data_ = reinterpret_cast<uint8_t*>(
|
||||
vpx_memalign(kDataAlignment, kDataBlockSize));
|
||||
}
|
||||
|
||||
@ -42,7 +40,9 @@ class AverageTestBase : public ::testing::Test {
|
||||
source_data_ = NULL;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
virtual void TearDown() {
|
||||
libvpx_test::ClearSystemState();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Handle blocks up to 4 blocks 64x64 with stride up to 128
|
||||
@ -55,65 +55,65 @@ class AverageTestBase : public ::testing::Test {
|
||||
}
|
||||
|
||||
// Sum Pixels
|
||||
static unsigned int ReferenceAverage8x8(const uint8_t *source, int pitch) {
|
||||
unsigned int ReferenceAverage8x8(const uint8_t* source, int pitch) {
|
||||
unsigned int average = 0;
|
||||
for (int h = 0; h < 8; ++h) {
|
||||
for (int w = 0; w < 8; ++w) average += source[h * pitch + w];
|
||||
}
|
||||
for (int h = 0; h < 8; ++h)
|
||||
for (int w = 0; w < 8; ++w)
|
||||
average += source[h * pitch + w];
|
||||
return ((average + 32) >> 6);
|
||||
}
|
||||
|
||||
static unsigned int ReferenceAverage4x4(const uint8_t *source, int pitch) {
|
||||
unsigned int ReferenceAverage4x4(const uint8_t* source, int pitch) {
|
||||
unsigned int average = 0;
|
||||
for (int h = 0; h < 4; ++h) {
|
||||
for (int w = 0; w < 4; ++w) average += source[h * pitch + w];
|
||||
}
|
||||
for (int h = 0; h < 4; ++h)
|
||||
for (int w = 0; w < 4; ++w)
|
||||
average += source[h * pitch + w];
|
||||
return ((average + 8) >> 4);
|
||||
}
|
||||
|
||||
void FillConstant(uint8_t fill_constant) {
|
||||
for (int i = 0; i < width_ * height_; ++i) {
|
||||
source_data_[i] = fill_constant;
|
||||
source_data_[i] = fill_constant;
|
||||
}
|
||||
}
|
||||
|
||||
void FillRandom() {
|
||||
for (int i = 0; i < width_ * height_; ++i) {
|
||||
source_data_[i] = rnd_.Rand8();
|
||||
source_data_[i] = rnd_.Rand8();
|
||||
}
|
||||
}
|
||||
|
||||
int width_, height_;
|
||||
static uint8_t *source_data_;
|
||||
static uint8_t* source_data_;
|
||||
int source_stride_;
|
||||
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
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,
|
||||
public ::testing::WithParamInterface<AvgFunc> {
|
||||
class AverageTest
|
||||
: public AverageTestBase,
|
||||
public ::testing::WithParamInterface<AvgFunc>{
|
||||
public:
|
||||
AverageTest() : AverageTestBase(GET_PARAM(0), GET_PARAM(1)) {}
|
||||
|
||||
protected:
|
||||
void CheckAverages() {
|
||||
const int block_size = GET_PARAM(3);
|
||||
unsigned int expected = 0;
|
||||
if (block_size == 8) {
|
||||
expected =
|
||||
ReferenceAverage8x8(source_data_ + GET_PARAM(2), source_stride_);
|
||||
} else if (block_size == 4) {
|
||||
expected =
|
||||
ReferenceAverage4x4(source_data_ + GET_PARAM(2), source_stride_);
|
||||
if (GET_PARAM(3) == 8) {
|
||||
expected = ReferenceAverage8x8(source_data_+ GET_PARAM(2),
|
||||
source_stride_);
|
||||
} else if (GET_PARAM(3) == 4) {
|
||||
expected = ReferenceAverage4x4(source_data_+ GET_PARAM(2),
|
||||
source_stride_);
|
||||
}
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
GET_PARAM(4)(source_data_ + GET_PARAM(2), source_stride_));
|
||||
unsigned int actual =
|
||||
GET_PARAM(4)(source_data_ + GET_PARAM(2), source_stride_);
|
||||
ASM_REGISTER_STATE_CHECK(GET_PARAM(4)(source_data_+ GET_PARAM(2),
|
||||
source_stride_));
|
||||
unsigned int actual = GET_PARAM(4)(source_data_+ GET_PARAM(2),
|
||||
source_stride_);
|
||||
|
||||
EXPECT_EQ(expected, actual);
|
||||
}
|
||||
@ -122,22 +122,25 @@ class AverageTest : public AverageTestBase,
|
||||
typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref,
|
||||
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,
|
||||
public ::testing::WithParamInterface<IntProRowParam> {
|
||||
class IntProRowTest
|
||||
: public AverageTestBase,
|
||||
public ::testing::WithParamInterface<IntProRowParam> {
|
||||
public:
|
||||
IntProRowTest()
|
||||
: AverageTestBase(16, GET_PARAM(0)), hbuf_asm_(NULL), hbuf_c_(NULL) {
|
||||
: AverageTestBase(16, GET_PARAM(0)),
|
||||
hbuf_asm_(NULL),
|
||||
hbuf_c_(NULL) {
|
||||
asm_func_ = GET_PARAM(1);
|
||||
c_func_ = GET_PARAM(2);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
hbuf_asm_ = reinterpret_cast<int16_t *>(
|
||||
hbuf_asm_ = reinterpret_cast<int16_t*>(
|
||||
vpx_memalign(kDataAlignment, sizeof(*hbuf_asm_) * 16));
|
||||
hbuf_c_ = reinterpret_cast<int16_t *>(
|
||||
hbuf_c_ = reinterpret_cast<int16_t*>(
|
||||
vpx_memalign(kDataAlignment, sizeof(*hbuf_c_) * 16));
|
||||
}
|
||||
|
||||
@ -164,10 +167,11 @@ class IntProRowTest : public AverageTestBase,
|
||||
|
||||
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,
|
||||
public ::testing::WithParamInterface<IntProColParam> {
|
||||
class IntProColTest
|
||||
: public AverageTestBase,
|
||||
public ::testing::WithParamInterface<IntProColParam> {
|
||||
public:
|
||||
IntProColTest() : AverageTestBase(GET_PARAM(0), 1), sum_asm_(0), sum_c_(0) {
|
||||
asm_func_ = GET_PARAM(1);
|
||||
@ -188,17 +192,18 @@ class IntProColTest : public AverageTestBase,
|
||||
int16_t sum_c_;
|
||||
};
|
||||
|
||||
typedef int (*SatdFunc)(const tran_low_t *coeffs, int length);
|
||||
typedef ::testing::tuple<int, SatdFunc> SatdTestParam;
|
||||
typedef int (*SatdFunc)(const int16_t *coeffs, int length);
|
||||
typedef std::tr1::tuple<int, SatdFunc> SatdTestParam;
|
||||
|
||||
class SatdTest : public ::testing::Test,
|
||||
public ::testing::WithParamInterface<SatdTestParam> {
|
||||
class SatdTest
|
||||
: public ::testing::Test,
|
||||
public ::testing::WithParamInterface<SatdTestParam> {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
satd_size_ = GET_PARAM(0);
|
||||
satd_func_ = GET_PARAM(1);
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
src_ = reinterpret_cast<tran_low_t *>(
|
||||
src_ = reinterpret_cast<int16_t*>(
|
||||
vpx_memalign(16, sizeof(*src_) * satd_size_));
|
||||
ASSERT_TRUE(src_ != NULL);
|
||||
}
|
||||
@ -208,15 +213,12 @@ class SatdTest : public ::testing::Test,
|
||||
vpx_free(src_);
|
||||
}
|
||||
|
||||
void FillConstant(const tran_low_t val) {
|
||||
void FillConstant(const int16_t val) {
|
||||
for (int i = 0; i < satd_size_; ++i) src_[i] = val;
|
||||
}
|
||||
|
||||
void FillRandom() {
|
||||
for (int i = 0; i < satd_size_; ++i) {
|
||||
const int16_t tmp = rnd_.Rand16();
|
||||
src_[i] = (tran_low_t)tmp;
|
||||
}
|
||||
for (int i = 0; i < satd_size_; ++i) src_[i] = rnd_.Rand16();
|
||||
}
|
||||
|
||||
void Check(const int expected) {
|
||||
@ -228,67 +230,12 @@ class SatdTest : public ::testing::Test,
|
||||
int satd_size_;
|
||||
|
||||
private:
|
||||
tran_low_t *src_;
|
||||
int16_t *src_;
|
||||
SatdFunc satd_func_;
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
|
||||
typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff,
|
||||
const tran_low_t *dqcoeff, int block_size);
|
||||
typedef ::testing::tuple<int, BlockErrorFunc> BlockErrorTestFPParam;
|
||||
|
||||
class BlockErrorTestFP
|
||||
: public ::testing::Test,
|
||||
public ::testing::WithParamInterface<BlockErrorTestFPParam> {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
txfm_size_ = GET_PARAM(0);
|
||||
block_error_func_ = GET_PARAM(1);
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
coeff_ = reinterpret_cast<tran_low_t *>(
|
||||
vpx_memalign(16, sizeof(*coeff_) * txfm_size_));
|
||||
dqcoeff_ = reinterpret_cast<tran_low_t *>(
|
||||
vpx_memalign(16, sizeof(*dqcoeff_) * txfm_size_));
|
||||
ASSERT_TRUE(coeff_ != NULL);
|
||||
ASSERT_TRUE(dqcoeff_ != NULL);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
libvpx_test::ClearSystemState();
|
||||
vpx_free(coeff_);
|
||||
vpx_free(dqcoeff_);
|
||||
}
|
||||
|
||||
void FillConstant(const tran_low_t coeff_val, const tran_low_t dqcoeff_val) {
|
||||
for (int i = 0; i < txfm_size_; ++i) coeff_[i] = coeff_val;
|
||||
for (int i = 0; i < txfm_size_; ++i) dqcoeff_[i] = dqcoeff_val;
|
||||
}
|
||||
|
||||
void FillRandom() {
|
||||
// Just two fixed seeds
|
||||
rnd_.Reset(0xb0b9);
|
||||
for (int i = 0; i < txfm_size_; ++i) coeff_[i] = rnd_.Rand16() >> 1;
|
||||
rnd_.Reset(0xb0c8);
|
||||
for (int i = 0; i < txfm_size_; ++i) dqcoeff_[i] = rnd_.Rand16() >> 1;
|
||||
}
|
||||
|
||||
void Check(const int64_t expected) {
|
||||
int64_t total;
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
total = block_error_func_(coeff_, dqcoeff_, txfm_size_));
|
||||
EXPECT_EQ(expected, total);
|
||||
}
|
||||
|
||||
int txfm_size_;
|
||||
|
||||
private:
|
||||
tran_low_t *coeff_;
|
||||
tran_low_t *dqcoeff_;
|
||||
BlockErrorFunc block_error_func_;
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
|
||||
uint8_t *AverageTestBase::source_data_ = NULL;
|
||||
uint8_t* AverageTestBase::source_data_ = NULL;
|
||||
|
||||
TEST_P(AverageTest, MinValue) {
|
||||
FillConstant(0);
|
||||
@ -339,6 +286,7 @@ TEST_P(IntProColTest, Random) {
|
||||
RunComparison();
|
||||
}
|
||||
|
||||
|
||||
TEST_P(SatdTest, MinValue) {
|
||||
const int kMin = -32640;
|
||||
const int expected = -kMin * satd_size_;
|
||||
@ -368,214 +316,96 @@ TEST_P(SatdTest, Random) {
|
||||
Check(expected);
|
||||
}
|
||||
|
||||
TEST_P(SatdTest, DISABLED_Speed) {
|
||||
const int kCountSpeedTestBlock = 20000;
|
||||
vpx_usec_timer timer;
|
||||
DECLARE_ALIGNED(16, tran_low_t, coeff[1024]);
|
||||
const int blocksize = GET_PARAM(0);
|
||||
|
||||
vpx_usec_timer_start(&timer);
|
||||
for (int i = 0; i < kCountSpeedTestBlock; ++i) {
|
||||
GET_PARAM(1)(coeff, blocksize);
|
||||
}
|
||||
vpx_usec_timer_mark(&timer);
|
||||
const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
|
||||
printf("blocksize: %4d time: %4d us\n", blocksize, elapsed_time);
|
||||
}
|
||||
|
||||
TEST_P(BlockErrorTestFP, MinValue) {
|
||||
const int64_t kMin = -32640;
|
||||
const int64_t expected = kMin * kMin * txfm_size_;
|
||||
FillConstant(kMin, 0);
|
||||
Check(expected);
|
||||
}
|
||||
|
||||
TEST_P(BlockErrorTestFP, MaxValue) {
|
||||
const int64_t kMax = 32640;
|
||||
const int64_t expected = kMax * kMax * txfm_size_;
|
||||
FillConstant(kMax, 0);
|
||||
Check(expected);
|
||||
}
|
||||
|
||||
TEST_P(BlockErrorTestFP, Random) {
|
||||
int64_t expected;
|
||||
switch (txfm_size_) {
|
||||
case 16: expected = 2051681432; break;
|
||||
case 64: expected = 11075114379; break;
|
||||
case 256: expected = 44386271116; break;
|
||||
case 1024: expected = 184774996089; break;
|
||||
default:
|
||||
FAIL() << "Invalid satd size (" << txfm_size_
|
||||
<< ") valid: 16/64/256/1024";
|
||||
}
|
||||
FillRandom();
|
||||
Check(expected);
|
||||
}
|
||||
|
||||
TEST_P(BlockErrorTestFP, DISABLED_Speed) {
|
||||
const int kCountSpeedTestBlock = 20000;
|
||||
vpx_usec_timer timer;
|
||||
DECLARE_ALIGNED(16, tran_low_t, coeff[1024]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, dqcoeff[1024]);
|
||||
const int blocksize = GET_PARAM(0);
|
||||
|
||||
vpx_usec_timer_start(&timer);
|
||||
for (int i = 0; i < kCountSpeedTestBlock; ++i) {
|
||||
GET_PARAM(1)(coeff, dqcoeff, blocksize);
|
||||
}
|
||||
vpx_usec_timer_mark(&timer);
|
||||
const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
|
||||
printf("blocksize: %4d time: %4d us\n", blocksize, elapsed_time);
|
||||
}
|
||||
|
||||
using ::testing::make_tuple;
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, AverageTest,
|
||||
::testing::Values(make_tuple(16, 16, 1, 8, &vpx_avg_8x8_c),
|
||||
make_tuple(16, 16, 1, 4, &vpx_avg_4x4_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, SatdTest,
|
||||
::testing::Values(make_tuple(16, &vpx_satd_c),
|
||||
make_tuple(64, &vpx_satd_c),
|
||||
make_tuple(256, &vpx_satd_c),
|
||||
make_tuple(1024, &vpx_satd_c)));
|
||||
::testing::Values(
|
||||
make_tuple(16, 16, 1, 8, &vpx_avg_8x8_c),
|
||||
make_tuple(16, 16, 1, 4, &vpx_avg_4x4_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, BlockErrorTestFP,
|
||||
::testing::Values(make_tuple(16, &vp9_block_error_fp_c),
|
||||
make_tuple(64, &vp9_block_error_fp_c),
|
||||
make_tuple(256, &vp9_block_error_fp_c),
|
||||
make_tuple(1024, &vp9_block_error_fp_c)));
|
||||
C, SatdTest,
|
||||
::testing::Values(
|
||||
make_tuple(16, &vpx_satd_c),
|
||||
make_tuple(64, &vpx_satd_c),
|
||||
make_tuple(256, &vpx_satd_c),
|
||||
make_tuple(1024, &vpx_satd_c)));
|
||||
|
||||
#if HAVE_SSE2
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, AverageTest,
|
||||
::testing::Values(make_tuple(16, 16, 0, 8, &vpx_avg_8x8_sse2),
|
||||
make_tuple(16, 16, 5, 8, &vpx_avg_8x8_sse2),
|
||||
make_tuple(32, 32, 15, 8, &vpx_avg_8x8_sse2),
|
||||
make_tuple(16, 16, 0, 4, &vpx_avg_4x4_sse2),
|
||||
make_tuple(16, 16, 5, 4, &vpx_avg_4x4_sse2),
|
||||
make_tuple(32, 32, 15, 4, &vpx_avg_4x4_sse2)));
|
||||
::testing::Values(
|
||||
make_tuple(16, 16, 0, 8, &vpx_avg_8x8_sse2),
|
||||
make_tuple(16, 16, 5, 8, &vpx_avg_8x8_sse2),
|
||||
make_tuple(32, 32, 15, 8, &vpx_avg_8x8_sse2),
|
||||
make_tuple(16, 16, 0, 4, &vpx_avg_4x4_sse2),
|
||||
make_tuple(16, 16, 5, 4, &vpx_avg_4x4_sse2),
|
||||
make_tuple(32, 32, 15, 4, &vpx_avg_4x4_sse2)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, IntProRowTest,
|
||||
::testing::Values(make_tuple(16, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
|
||||
make_tuple(32, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
|
||||
make_tuple(64, &vpx_int_pro_row_sse2,
|
||||
&vpx_int_pro_row_c)));
|
||||
SSE2, IntProRowTest, ::testing::Values(
|
||||
make_tuple(16, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
|
||||
make_tuple(32, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
|
||||
make_tuple(64, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, IntProColTest,
|
||||
::testing::Values(make_tuple(16, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
|
||||
make_tuple(32, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
|
||||
make_tuple(64, &vpx_int_pro_col_sse2,
|
||||
&vpx_int_pro_col_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, SatdTest,
|
||||
::testing::Values(make_tuple(16, &vpx_satd_sse2),
|
||||
make_tuple(64, &vpx_satd_sse2),
|
||||
make_tuple(256, &vpx_satd_sse2),
|
||||
make_tuple(1024, &vpx_satd_sse2)));
|
||||
SSE2, IntProColTest, ::testing::Values(
|
||||
make_tuple(16, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
|
||||
make_tuple(32, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
|
||||
make_tuple(64, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, BlockErrorTestFP,
|
||||
::testing::Values(make_tuple(16, &vp9_block_error_fp_sse2),
|
||||
make_tuple(64, &vp9_block_error_fp_sse2),
|
||||
make_tuple(256, &vp9_block_error_fp_sse2),
|
||||
make_tuple(1024, &vp9_block_error_fp_sse2)));
|
||||
#endif // HAVE_SSE2
|
||||
|
||||
#if HAVE_AVX2
|
||||
INSTANTIATE_TEST_CASE_P(AVX2, SatdTest,
|
||||
::testing::Values(make_tuple(16, &vpx_satd_avx2),
|
||||
make_tuple(64, &vpx_satd_avx2),
|
||||
make_tuple(256, &vpx_satd_avx2),
|
||||
make_tuple(1024, &vpx_satd_avx2)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
AVX2, BlockErrorTestFP,
|
||||
::testing::Values(make_tuple(16, &vp9_block_error_fp_avx2),
|
||||
make_tuple(64, &vp9_block_error_fp_avx2),
|
||||
make_tuple(256, &vp9_block_error_fp_avx2),
|
||||
make_tuple(1024, &vp9_block_error_fp_avx2)));
|
||||
SSE2, SatdTest,
|
||||
::testing::Values(
|
||||
make_tuple(16, &vpx_satd_sse2),
|
||||
make_tuple(64, &vpx_satd_sse2),
|
||||
make_tuple(256, &vpx_satd_sse2),
|
||||
make_tuple(1024, &vpx_satd_sse2)));
|
||||
#endif
|
||||
|
||||
#if HAVE_NEON
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, AverageTest,
|
||||
::testing::Values(make_tuple(16, 16, 0, 8, &vpx_avg_8x8_neon),
|
||||
make_tuple(16, 16, 5, 8, &vpx_avg_8x8_neon),
|
||||
make_tuple(32, 32, 15, 8, &vpx_avg_8x8_neon),
|
||||
make_tuple(16, 16, 0, 4, &vpx_avg_4x4_neon),
|
||||
make_tuple(16, 16, 5, 4, &vpx_avg_4x4_neon),
|
||||
make_tuple(32, 32, 15, 4, &vpx_avg_4x4_neon)));
|
||||
::testing::Values(
|
||||
make_tuple(16, 16, 0, 8, &vpx_avg_8x8_neon),
|
||||
make_tuple(16, 16, 5, 8, &vpx_avg_8x8_neon),
|
||||
make_tuple(32, 32, 15, 8, &vpx_avg_8x8_neon),
|
||||
make_tuple(16, 16, 0, 4, &vpx_avg_4x4_neon),
|
||||
make_tuple(16, 16, 5, 4, &vpx_avg_4x4_neon),
|
||||
make_tuple(32, 32, 15, 4, &vpx_avg_4x4_neon)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, IntProRowTest,
|
||||
::testing::Values(make_tuple(16, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
|
||||
make_tuple(32, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
|
||||
make_tuple(64, &vpx_int_pro_row_neon,
|
||||
&vpx_int_pro_row_c)));
|
||||
NEON, IntProRowTest, ::testing::Values(
|
||||
make_tuple(16, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
|
||||
make_tuple(32, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
|
||||
make_tuple(64, &vpx_int_pro_row_neon, &vpx_int_pro_row_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, IntProColTest,
|
||||
::testing::Values(make_tuple(16, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
|
||||
make_tuple(32, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
|
||||
make_tuple(64, &vpx_int_pro_col_neon,
|
||||
&vpx_int_pro_col_c)));
|
||||
NEON, IntProColTest, ::testing::Values(
|
||||
make_tuple(16, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
|
||||
make_tuple(32, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
|
||||
make_tuple(64, &vpx_int_pro_col_neon, &vpx_int_pro_col_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(NEON, SatdTest,
|
||||
::testing::Values(make_tuple(16, &vpx_satd_neon),
|
||||
make_tuple(64, &vpx_satd_neon),
|
||||
make_tuple(256, &vpx_satd_neon),
|
||||
make_tuple(1024, &vpx_satd_neon)));
|
||||
|
||||
// TODO(jianj): Remove the highbitdepth flag once the SIMD functions are
|
||||
// in place.
|
||||
#if !CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, BlockErrorTestFP,
|
||||
::testing::Values(make_tuple(16, &vp9_block_error_fp_neon),
|
||||
make_tuple(64, &vp9_block_error_fp_neon),
|
||||
make_tuple(256, &vp9_block_error_fp_neon),
|
||||
make_tuple(1024, &vp9_block_error_fp_neon)));
|
||||
#endif // !CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_NEON
|
||||
NEON, SatdTest,
|
||||
::testing::Values(
|
||||
make_tuple(16, &vpx_satd_neon),
|
||||
make_tuple(64, &vpx_satd_neon),
|
||||
make_tuple(256, &vpx_satd_neon),
|
||||
make_tuple(1024, &vpx_satd_neon)));
|
||||
#endif
|
||||
|
||||
#if HAVE_MSA
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, AverageTest,
|
||||
::testing::Values(make_tuple(16, 16, 0, 8, &vpx_avg_8x8_msa),
|
||||
make_tuple(16, 16, 5, 8, &vpx_avg_8x8_msa),
|
||||
make_tuple(32, 32, 15, 8, &vpx_avg_8x8_msa),
|
||||
make_tuple(16, 16, 0, 4, &vpx_avg_4x4_msa),
|
||||
make_tuple(16, 16, 5, 4, &vpx_avg_4x4_msa),
|
||||
make_tuple(32, 32, 15, 4, &vpx_avg_4x4_msa)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, IntProRowTest,
|
||||
::testing::Values(make_tuple(16, &vpx_int_pro_row_msa, &vpx_int_pro_row_c),
|
||||
make_tuple(32, &vpx_int_pro_row_msa, &vpx_int_pro_row_c),
|
||||
make_tuple(64, &vpx_int_pro_row_msa,
|
||||
&vpx_int_pro_row_c)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, IntProColTest,
|
||||
::testing::Values(make_tuple(16, &vpx_int_pro_col_msa, &vpx_int_pro_col_c),
|
||||
make_tuple(32, &vpx_int_pro_col_msa, &vpx_int_pro_col_c),
|
||||
make_tuple(64, &vpx_int_pro_col_msa,
|
||||
&vpx_int_pro_col_c)));
|
||||
|
||||
// TODO(jingning): Remove the highbitdepth flag once the SIMD functions are
|
||||
// in place.
|
||||
#if !CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(MSA, SatdTest,
|
||||
::testing::Values(make_tuple(16, &vpx_satd_msa),
|
||||
make_tuple(64, &vpx_satd_msa),
|
||||
make_tuple(256, &vpx_satd_msa),
|
||||
make_tuple(1024, &vpx_satd_msa)));
|
||||
#endif // !CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_MSA
|
||||
::testing::Values(
|
||||
make_tuple(16, 16, 0, 8, &vpx_avg_8x8_msa),
|
||||
make_tuple(16, 16, 5, 8, &vpx_avg_8x8_msa),
|
||||
make_tuple(32, 32, 15, 8, &vpx_avg_8x8_msa),
|
||||
make_tuple(16, 16, 0, 4, &vpx_avg_4x4_msa),
|
||||
make_tuple(16, 16, 5, 4, &vpx_avg_4x4_msa),
|
||||
make_tuple(32, 32, 15, 4, &vpx_avg_4x4_msa)));
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
@ -26,9 +26,11 @@
|
||||
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
|
||||
extern "C" double vp9_get_blockiness(const unsigned char *img1, int img1_pitch,
|
||||
const unsigned char *img2, int img2_pitch,
|
||||
int width, int height);
|
||||
|
||||
extern "C"
|
||||
double vp9_get_blockiness(const unsigned char *img1, int img1_pitch,
|
||||
const unsigned char *img2, int img2_pitch,
|
||||
int width, int height);
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
@ -38,9 +40,9 @@ class BlockinessTestBase : public ::testing::Test {
|
||||
BlockinessTestBase(int width, int height) : width_(width), height_(height) {}
|
||||
|
||||
static void SetUpTestCase() {
|
||||
source_data_ = reinterpret_cast<uint8_t *>(
|
||||
source_data_ = reinterpret_cast<uint8_t*>(
|
||||
vpx_memalign(kDataAlignment, kDataBufferSize));
|
||||
reference_data_ = reinterpret_cast<uint8_t *>(
|
||||
reference_data_ = reinterpret_cast<uint8_t*>(
|
||||
vpx_memalign(kDataAlignment, kDataBufferSize));
|
||||
}
|
||||
|
||||
@ -51,12 +53,14 @@ class BlockinessTestBase : public ::testing::Test {
|
||||
reference_data_ = NULL;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
virtual void TearDown() {
|
||||
libvpx_test::ClearSystemState();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Handle frames up to 640x480
|
||||
static const int kDataAlignment = 16;
|
||||
static const int kDataBufferSize = 640 * 480;
|
||||
static const int kDataBufferSize = 640*480;
|
||||
|
||||
virtual void SetUp() {
|
||||
source_stride_ = (width_ + 31) & ~31;
|
||||
@ -64,8 +68,8 @@ class BlockinessTestBase : public ::testing::Test {
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
}
|
||||
|
||||
void FillConstant(uint8_t *data, int stride, uint8_t fill_constant, int width,
|
||||
int height) {
|
||||
void FillConstant(uint8_t *data, int stride, uint8_t fill_constant,
|
||||
int width, int height) {
|
||||
for (int h = 0; h < height; ++h) {
|
||||
for (int w = 0; w < width; ++w) {
|
||||
data[h * stride + w] = fill_constant;
|
||||
@ -100,11 +104,10 @@ class BlockinessTestBase : public ::testing::Test {
|
||||
void FillCheckerboard(uint8_t *data, int stride) {
|
||||
for (int h = 0; h < height_; h += 4) {
|
||||
for (int w = 0; w < width_; w += 4) {
|
||||
if (((h / 4) ^ (w / 4)) & 1) {
|
||||
if (((h/4) ^ (w/4)) & 1)
|
||||
FillConstant(data + h * stride + w, stride, 255, 4, 4);
|
||||
} else {
|
||||
else
|
||||
FillConstant(data + h * stride + w, stride, 0, 4, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,16 +135,16 @@ class BlockinessTestBase : public ::testing::Test {
|
||||
}
|
||||
}
|
||||
int width_, height_;
|
||||
static uint8_t *source_data_;
|
||||
static uint8_t* source_data_;
|
||||
int source_stride_;
|
||||
static uint8_t *reference_data_;
|
||||
static uint8_t* reference_data_;
|
||||
int reference_stride_;
|
||||
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
typedef ::testing::tuple<int, int> BlockinessParam;
|
||||
typedef std::tr1::tuple<int, int> BlockinessParam;
|
||||
class BlockinessVP9Test
|
||||
: public BlockinessTestBase,
|
||||
public ::testing::WithParamInterface<BlockinessParam> {
|
||||
@ -149,32 +152,32 @@ class BlockinessVP9Test
|
||||
BlockinessVP9Test() : BlockinessTestBase(GET_PARAM(0), GET_PARAM(1)) {}
|
||||
|
||||
protected:
|
||||
double GetBlockiness() const {
|
||||
return vp9_get_blockiness(source_data_, source_stride_, reference_data_,
|
||||
reference_stride_, width_, height_);
|
||||
int CheckBlockiness() {
|
||||
return vp9_get_blockiness(source_data_, source_stride_,
|
||||
reference_data_, reference_stride_,
|
||||
width_, height_);
|
||||
}
|
||||
};
|
||||
#endif // CONFIG_VP9_ENCODER
|
||||
|
||||
uint8_t *BlockinessTestBase::source_data_ = NULL;
|
||||
uint8_t *BlockinessTestBase::reference_data_ = NULL;
|
||||
uint8_t* BlockinessTestBase::source_data_ = NULL;
|
||||
uint8_t* BlockinessTestBase::reference_data_ = NULL;
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
TEST_P(BlockinessVP9Test, SourceBlockierThanReference) {
|
||||
// Source is blockier than reference.
|
||||
FillRandomBlocky(source_data_, source_stride_);
|
||||
FillConstant(reference_data_, reference_stride_, 128);
|
||||
const double super_blocky = GetBlockiness();
|
||||
int super_blocky = CheckBlockiness();
|
||||
|
||||
EXPECT_DOUBLE_EQ(0.0, super_blocky)
|
||||
<< "Blocky source should produce 0 blockiness.";
|
||||
EXPECT_EQ(0, super_blocky) << "Blocky source should produce 0 blockiness.";
|
||||
}
|
||||
|
||||
TEST_P(BlockinessVP9Test, ReferenceBlockierThanSource) {
|
||||
// Source is blockier than reference.
|
||||
FillConstant(source_data_, source_stride_, 128);
|
||||
FillRandomBlocky(reference_data_, reference_stride_);
|
||||
const double super_blocky = GetBlockiness();
|
||||
int super_blocky = CheckBlockiness();
|
||||
|
||||
EXPECT_GT(super_blocky, 0.0)
|
||||
<< "Blocky reference should score high for blockiness.";
|
||||
@ -184,10 +187,10 @@ TEST_P(BlockinessVP9Test, BlurringDecreasesBlockiness) {
|
||||
// Source is blockier than reference.
|
||||
FillConstant(source_data_, source_stride_, 128);
|
||||
FillRandomBlocky(reference_data_, reference_stride_);
|
||||
const double super_blocky = GetBlockiness();
|
||||
int super_blocky = CheckBlockiness();
|
||||
|
||||
Blur(reference_data_, reference_stride_, 4);
|
||||
const double less_blocky = GetBlockiness();
|
||||
int less_blocky = CheckBlockiness();
|
||||
|
||||
EXPECT_GT(super_blocky, less_blocky)
|
||||
<< "A straight blur should decrease blockiness.";
|
||||
@ -198,24 +201,27 @@ TEST_P(BlockinessVP9Test, WorstCaseBlockiness) {
|
||||
FillConstant(source_data_, source_stride_, 128);
|
||||
FillCheckerboard(reference_data_, reference_stride_);
|
||||
|
||||
const double super_blocky = GetBlockiness();
|
||||
int super_blocky = CheckBlockiness();
|
||||
|
||||
Blur(reference_data_, reference_stride_, 4);
|
||||
const double less_blocky = GetBlockiness();
|
||||
int less_blocky = CheckBlockiness();
|
||||
|
||||
EXPECT_GT(super_blocky, less_blocky)
|
||||
<< "A straight blur should decrease blockiness.";
|
||||
}
|
||||
#endif // CONFIG_VP9_ENCODER
|
||||
|
||||
using ::testing::make_tuple;
|
||||
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// C functions
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
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));
|
||||
#endif
|
||||
|
@ -17,9 +17,8 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class BordersTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
class BordersTest : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
protected:
|
||||
BordersTest() : EncoderTest(GET_PARAM(0)) {}
|
||||
virtual ~BordersTest() {}
|
||||
@ -79,6 +78,9 @@ TEST_P(BordersTest, TestLowBitrate) {
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(BordersTest,
|
||||
::testing::Values(::libvpx_test::kTwoPassGood));
|
||||
VP9_INSTANTIATE_TEST_CASE(BordersTest, ::testing::Values(
|
||||
::libvpx_test::kTwoPassGood));
|
||||
|
||||
VP10_INSTANTIATE_TEST_CASE(BordersTest, ::testing::Values(
|
||||
::libvpx_test::kTwoPassGood));
|
||||
} // namespace
|
||||
|
382
test/buffer.h
382
test/buffer.h
@ -1,382 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef TEST_BUFFER_H_
|
||||
#define TEST_BUFFER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "test/acm_random.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
|
||||
namespace libvpx_test {
|
||||
|
||||
template <typename T>
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer(int width, int height, int top_padding, int left_padding,
|
||||
int right_padding, int bottom_padding)
|
||||
: width_(width), height_(height), top_padding_(top_padding),
|
||||
left_padding_(left_padding), right_padding_(right_padding),
|
||||
bottom_padding_(bottom_padding), alignment_(0), padding_value_(0),
|
||||
stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(NULL) {}
|
||||
|
||||
Buffer(int width, int height, int top_padding, int left_padding,
|
||||
int right_padding, int bottom_padding, unsigned int alignment)
|
||||
: width_(width), height_(height), top_padding_(top_padding),
|
||||
left_padding_(left_padding), right_padding_(right_padding),
|
||||
bottom_padding_(bottom_padding), alignment_(alignment),
|
||||
padding_value_(0), stride_(0), raw_size_(0), num_elements_(0),
|
||||
raw_buffer_(NULL) {}
|
||||
|
||||
Buffer(int width, int height, int padding)
|
||||
: width_(width), height_(height), top_padding_(padding),
|
||||
left_padding_(padding), right_padding_(padding),
|
||||
bottom_padding_(padding), alignment_(0), padding_value_(0), stride_(0),
|
||||
raw_size_(0), num_elements_(0), raw_buffer_(NULL) {}
|
||||
|
||||
Buffer(int width, int height, int padding, unsigned int alignment)
|
||||
: width_(width), height_(height), top_padding_(padding),
|
||||
left_padding_(padding), right_padding_(padding),
|
||||
bottom_padding_(padding), alignment_(alignment), padding_value_(0),
|
||||
stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(NULL) {}
|
||||
|
||||
~Buffer() {
|
||||
if (alignment_) {
|
||||
vpx_free(raw_buffer_);
|
||||
} else {
|
||||
delete[] raw_buffer_;
|
||||
}
|
||||
}
|
||||
|
||||
T *TopLeftPixel() const;
|
||||
|
||||
int stride() const { return stride_; }
|
||||
|
||||
// Set the buffer (excluding padding) to 'value'.
|
||||
void Set(const T value);
|
||||
|
||||
// Set the buffer (excluding padding) to the output of ACMRandom function
|
||||
// 'rand_func'.
|
||||
void Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)());
|
||||
|
||||
// Set the buffer (excluding padding) to the output of ACMRandom function
|
||||
// 'RandRange' with range 'low' to 'high' which typically must be within
|
||||
// testing::internal::Random::kMaxRange (1u << 31). However, because we want
|
||||
// to allow negative low (and high) values, it is restricted to INT32_MAX
|
||||
// here.
|
||||
void Set(ACMRandom *rand_class, const T low, const T high);
|
||||
|
||||
// Copy the contents of Buffer 'a' (excluding padding).
|
||||
void CopyFrom(const Buffer<T> &a);
|
||||
|
||||
void DumpBuffer() const;
|
||||
|
||||
// Highlight the differences between two buffers if they are the same size.
|
||||
void PrintDifference(const Buffer<T> &a) const;
|
||||
|
||||
bool HasPadding() const;
|
||||
|
||||
// Sets all the values in the buffer to 'padding_value'.
|
||||
void SetPadding(const T padding_value);
|
||||
|
||||
// Checks if all the values (excluding padding) are equal to 'value' if the
|
||||
// Buffers are the same size.
|
||||
bool CheckValues(const T value) const;
|
||||
|
||||
// Check that padding matches the expected value or there is no padding.
|
||||
bool CheckPadding() const;
|
||||
|
||||
// Compare the non-padding portion of two buffers if they are the same size.
|
||||
bool CheckValues(const Buffer<T> &a) const;
|
||||
|
||||
bool Init() {
|
||||
if (raw_buffer_ != NULL) return false;
|
||||
EXPECT_GT(width_, 0);
|
||||
EXPECT_GT(height_, 0);
|
||||
EXPECT_GE(top_padding_, 0);
|
||||
EXPECT_GE(left_padding_, 0);
|
||||
EXPECT_GE(right_padding_, 0);
|
||||
EXPECT_GE(bottom_padding_, 0);
|
||||
stride_ = left_padding_ + width_ + right_padding_;
|
||||
num_elements_ = stride_ * (top_padding_ + height_ + bottom_padding_);
|
||||
raw_size_ = num_elements_ * sizeof(T);
|
||||
if (alignment_) {
|
||||
EXPECT_GE(alignment_, sizeof(T));
|
||||
// Ensure alignment of the first value will be preserved.
|
||||
EXPECT_EQ((left_padding_ * sizeof(T)) % alignment_, 0u);
|
||||
// Ensure alignment of the subsequent rows will be preserved when there is
|
||||
// a stride.
|
||||
if (stride_ != width_) {
|
||||
EXPECT_EQ((stride_ * sizeof(T)) % alignment_, 0u);
|
||||
}
|
||||
raw_buffer_ = reinterpret_cast<T *>(vpx_memalign(alignment_, raw_size_));
|
||||
} else {
|
||||
raw_buffer_ = new (std::nothrow) T[num_elements_];
|
||||
}
|
||||
EXPECT_TRUE(raw_buffer_ != NULL);
|
||||
SetPadding(std::numeric_limits<T>::max());
|
||||
return !::testing::Test::HasFailure();
|
||||
}
|
||||
|
||||
private:
|
||||
bool BufferSizesMatch(const Buffer<T> &a) const;
|
||||
|
||||
const int width_;
|
||||
const int height_;
|
||||
const int top_padding_;
|
||||
const int left_padding_;
|
||||
const int right_padding_;
|
||||
const int bottom_padding_;
|
||||
const unsigned int alignment_;
|
||||
T padding_value_;
|
||||
int stride_;
|
||||
int raw_size_;
|
||||
int num_elements_;
|
||||
T *raw_buffer_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T *Buffer<T>::TopLeftPixel() const {
|
||||
if (!raw_buffer_) return NULL;
|
||||
return raw_buffer_ + (top_padding_ * stride_) + left_padding_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::Set(const T value) {
|
||||
if (!raw_buffer_) return;
|
||||
T *src = TopLeftPixel();
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
src[width] = value;
|
||||
}
|
||||
src += stride_;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)()) {
|
||||
if (!raw_buffer_) return;
|
||||
T *src = TopLeftPixel();
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
src[width] = (*rand_class.*rand_func)();
|
||||
}
|
||||
src += stride_;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::Set(ACMRandom *rand_class, const T low, const T high) {
|
||||
if (!raw_buffer_) return;
|
||||
|
||||
EXPECT_LE(low, high);
|
||||
EXPECT_LE(static_cast<int64_t>(high) - low,
|
||||
std::numeric_limits<int32_t>::max());
|
||||
|
||||
T *src = TopLeftPixel();
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
// 'low' will be promoted to unsigned given the return type of RandRange.
|
||||
// Store the value as an int to avoid unsigned overflow warnings when
|
||||
// 'low' is negative.
|
||||
const int32_t value =
|
||||
static_cast<int32_t>((*rand_class).RandRange(high - low));
|
||||
src[width] = static_cast<T>(value + low);
|
||||
}
|
||||
src += stride_;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::CopyFrom(const Buffer<T> &a) {
|
||||
if (!raw_buffer_) return;
|
||||
if (!BufferSizesMatch(a)) return;
|
||||
|
||||
T *a_src = a.TopLeftPixel();
|
||||
T *b_src = this->TopLeftPixel();
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
b_src[width] = a_src[width];
|
||||
}
|
||||
a_src += a.stride();
|
||||
b_src += this->stride();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::DumpBuffer() const {
|
||||
if (!raw_buffer_) return;
|
||||
for (int height = 0; height < height_ + top_padding_ + bottom_padding_;
|
||||
++height) {
|
||||
for (int width = 0; width < stride_; ++width) {
|
||||
printf("%4d", raw_buffer_[height + width * stride_]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Buffer<T>::HasPadding() const {
|
||||
if (!raw_buffer_) return false;
|
||||
return top_padding_ || left_padding_ || right_padding_ || bottom_padding_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::PrintDifference(const Buffer<T> &a) const {
|
||||
if (!raw_buffer_) return;
|
||||
if (!BufferSizesMatch(a)) return;
|
||||
|
||||
T *a_src = a.TopLeftPixel();
|
||||
T *b_src = TopLeftPixel();
|
||||
|
||||
printf("This buffer:\n");
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
if (a_src[width] != b_src[width]) {
|
||||
printf("*%3d", b_src[width]);
|
||||
} else {
|
||||
printf("%4d", b_src[width]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
a_src += a.stride();
|
||||
b_src += this->stride();
|
||||
}
|
||||
|
||||
a_src = a.TopLeftPixel();
|
||||
b_src = TopLeftPixel();
|
||||
|
||||
printf("Reference buffer:\n");
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
if (a_src[width] != b_src[width]) {
|
||||
printf("*%3d", a_src[width]);
|
||||
} else {
|
||||
printf("%4d", a_src[width]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
a_src += a.stride();
|
||||
b_src += this->stride();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::SetPadding(const T padding_value) {
|
||||
if (!raw_buffer_) return;
|
||||
padding_value_ = padding_value;
|
||||
|
||||
T *src = raw_buffer_;
|
||||
for (int i = 0; i < num_elements_; ++i) {
|
||||
src[i] = padding_value;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Buffer<T>::CheckValues(const T value) const {
|
||||
if (!raw_buffer_) return false;
|
||||
T *src = TopLeftPixel();
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
if (value != src[width]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
src += stride_;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Buffer<T>::CheckPadding() const {
|
||||
if (!raw_buffer_) return false;
|
||||
if (!HasPadding()) return true;
|
||||
|
||||
// Top padding.
|
||||
T const *top = raw_buffer_;
|
||||
for (int i = 0; i < stride_ * top_padding_; ++i) {
|
||||
if (padding_value_ != top[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Left padding.
|
||||
T const *left = TopLeftPixel() - left_padding_;
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < left_padding_; ++width) {
|
||||
if (padding_value_ != left[width]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
left += stride_;
|
||||
}
|
||||
|
||||
// Right padding.
|
||||
T const *right = TopLeftPixel() + width_;
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < right_padding_; ++width) {
|
||||
if (padding_value_ != right[width]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
right += stride_;
|
||||
}
|
||||
|
||||
// Bottom padding
|
||||
T const *bottom = raw_buffer_ + (top_padding_ + height_) * stride_;
|
||||
for (int i = 0; i < stride_ * bottom_padding_; ++i) {
|
||||
if (padding_value_ != bottom[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Buffer<T>::CheckValues(const Buffer<T> &a) const {
|
||||
if (!raw_buffer_) return false;
|
||||
if (!BufferSizesMatch(a)) return false;
|
||||
|
||||
T *a_src = a.TopLeftPixel();
|
||||
T *b_src = this->TopLeftPixel();
|
||||
for (int height = 0; height < height_; ++height) {
|
||||
for (int width = 0; width < width_; ++width) {
|
||||
if (a_src[width] != b_src[width]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
a_src += a.stride();
|
||||
b_src += this->stride();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Buffer<T>::BufferSizesMatch(const Buffer<T> &a) const {
|
||||
if (!raw_buffer_) return false;
|
||||
if (a.width_ != this->width_ || a.height_ != this->height_) {
|
||||
printf(
|
||||
"Reference buffer of size %dx%d does not match this buffer which is "
|
||||
"size %dx%d\n",
|
||||
a.width_, a.height_, this->width_, this->height_);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace libvpx_test
|
||||
#endif // TEST_BUFFER_H_
|
@ -36,26 +36,29 @@ struct ByteAlignmentTestParam {
|
||||
};
|
||||
|
||||
const ByteAlignmentTestParam kBaTestParams[] = {
|
||||
{ kLegacyByteAlignment, VPX_CODEC_OK, true },
|
||||
{ 32, VPX_CODEC_OK, true },
|
||||
{ 64, VPX_CODEC_OK, true },
|
||||
{ 128, VPX_CODEC_OK, true },
|
||||
{ 256, VPX_CODEC_OK, true },
|
||||
{ 512, VPX_CODEC_OK, true },
|
||||
{ 1024, VPX_CODEC_OK, true },
|
||||
{ 1, VPX_CODEC_INVALID_PARAM, false },
|
||||
{ -2, VPX_CODEC_INVALID_PARAM, false },
|
||||
{ 4, VPX_CODEC_INVALID_PARAM, false },
|
||||
{ 16, VPX_CODEC_INVALID_PARAM, false },
|
||||
{ 255, VPX_CODEC_INVALID_PARAM, false },
|
||||
{ 2048, VPX_CODEC_INVALID_PARAM, false },
|
||||
{kLegacyByteAlignment, VPX_CODEC_OK, true},
|
||||
{32, VPX_CODEC_OK, true},
|
||||
{64, VPX_CODEC_OK, true},
|
||||
{128, VPX_CODEC_OK, true},
|
||||
{256, VPX_CODEC_OK, true},
|
||||
{512, VPX_CODEC_OK, true},
|
||||
{1024, VPX_CODEC_OK, true},
|
||||
{1, VPX_CODEC_INVALID_PARAM, false},
|
||||
{-2, VPX_CODEC_INVALID_PARAM, false},
|
||||
{4, VPX_CODEC_INVALID_PARAM, false},
|
||||
{16, VPX_CODEC_INVALID_PARAM, false},
|
||||
{255, VPX_CODEC_INVALID_PARAM, false},
|
||||
{2048, VPX_CODEC_INVALID_PARAM, false},
|
||||
};
|
||||
|
||||
// Class for testing byte alignment of reference buffers.
|
||||
class ByteAlignmentTest
|
||||
: public ::testing::TestWithParam<ByteAlignmentTestParam> {
|
||||
protected:
|
||||
ByteAlignmentTest() : video_(NULL), decoder_(NULL), md5_file_(NULL) {}
|
||||
ByteAlignmentTest()
|
||||
: video_(NULL),
|
||||
decoder_(NULL),
|
||||
md5_file_(NULL) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
|
||||
@ -71,7 +74,8 @@ class ByteAlignmentTest
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
if (md5_file_ != NULL) fclose(md5_file_);
|
||||
if (md5_file_ != NULL)
|
||||
fclose(md5_file_);
|
||||
|
||||
delete decoder_;
|
||||
delete video_;
|
||||
@ -85,7 +89,8 @@ class ByteAlignmentTest
|
||||
const vpx_codec_err_t res =
|
||||
decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
|
||||
CheckDecodedFrames(byte_alignment_to_check);
|
||||
if (res == VPX_CODEC_OK) video_->Next();
|
||||
if (res == VPX_CODEC_OK)
|
||||
video_->Next();
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -93,7 +98,8 @@ class ByteAlignmentTest
|
||||
for (; video_->cxdata() != NULL; video_->Next()) {
|
||||
const vpx_codec_err_t res =
|
||||
decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
|
||||
if (res != VPX_CODEC_OK) return res;
|
||||
if (res != VPX_CODEC_OK)
|
||||
return res;
|
||||
CheckDecodedFrames(byte_alignment_to_check);
|
||||
}
|
||||
return VPX_CODEC_OK;
|
||||
@ -128,8 +134,8 @@ class ByteAlignmentTest
|
||||
// TODO(fgalligan): Move the MD5 testing code into another class.
|
||||
void OpenMd5File(const std::string &md5_file_name_) {
|
||||
md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
|
||||
ASSERT_TRUE(md5_file_ != NULL)
|
||||
<< "MD5 file open failed. Filename: " << md5_file_name_;
|
||||
ASSERT_TRUE(md5_file_ != NULL) << "MD5 file open failed. Filename: "
|
||||
<< md5_file_name_;
|
||||
}
|
||||
|
||||
void CheckMd5(const vpx_image_t &img) {
|
||||
@ -157,8 +163,8 @@ class ByteAlignmentTest
|
||||
|
||||
TEST_F(ByteAlignmentTest, SwitchByteAlignment) {
|
||||
const int num_elements = 14;
|
||||
const int byte_alignments[] = { 0, 32, 64, 128, 256, 512, 1024,
|
||||
0, 1024, 32, 512, 64, 256, 128 };
|
||||
const int byte_alignments[] = { 0, 32, 64, 128, 256, 512, 1024,
|
||||
0, 1024, 32, 512, 64, 256, 128 };
|
||||
|
||||
for (int i = 0; i < num_elements; ++i) {
|
||||
SetByteAlignment(byte_alignments[i], VPX_CODEC_OK);
|
||||
@ -171,9 +177,8 @@ TEST_F(ByteAlignmentTest, SwitchByteAlignment) {
|
||||
TEST_P(ByteAlignmentTest, TestAlignment) {
|
||||
const ByteAlignmentTestParam t = GetParam();
|
||||
SetByteAlignment(t.byte_alignment, t.expected_value);
|
||||
if (t.decode_remaining) {
|
||||
if (t.decode_remaining)
|
||||
ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(t.byte_alignment));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Alignments, ByteAlignmentTest,
|
||||
|
@ -11,13 +11,19 @@
|
||||
#define TEST_CLEAR_SYSTEM_STATE_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 {
|
||||
|
||||
// Reset system to a known state. This function should be used for all non-API
|
||||
// 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
|
||||
#endif // TEST_CLEAR_SYSTEM_STATE_H_
|
||||
|
@ -13,10 +13,10 @@
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
|
||||
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
|
||||
#include "vpx/vp8cx.h"
|
||||
#endif
|
||||
#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
|
||||
#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER || CONFIG_VP10_DECODER
|
||||
#include "vpx/vp8dx.h"
|
||||
#endif
|
||||
|
||||
@ -32,12 +32,15 @@ class CodecFactory {
|
||||
|
||||
virtual ~CodecFactory() {}
|
||||
|
||||
virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg) const = 0;
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
unsigned long deadline) const = 0;
|
||||
|
||||
virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
const vpx_codec_flags_t flags) const = 0;
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
const vpx_codec_flags_t flags,
|
||||
unsigned long deadline) // NOLINT(runtime/int)
|
||||
const = 0;
|
||||
|
||||
virtual Encoder *CreateEncoder(vpx_codec_enc_cfg_t cfg,
|
||||
virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
|
||||
unsigned long deadline,
|
||||
const unsigned long init_flags,
|
||||
TwopassStatsStore *stats) const = 0;
|
||||
@ -50,25 +53,20 @@ class CodecFactory {
|
||||
* to avoid having to include a pointer to the CodecFactory in every test
|
||||
* definition.
|
||||
*/
|
||||
template <class T1>
|
||||
class CodecTestWithParam
|
||||
: public ::testing::TestWithParam<
|
||||
::testing::tuple<const libvpx_test::CodecFactory *, T1> > {};
|
||||
template<class T1>
|
||||
class CodecTestWithParam : public ::testing::TestWithParam<
|
||||
std::tr1::tuple< const libvpx_test::CodecFactory*, T1 > > {
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
class CodecTestWith2Params
|
||||
: public ::testing::TestWithParam<
|
||||
::testing::tuple<const libvpx_test::CodecFactory *, T1, T2> > {};
|
||||
template<class T1, class T2>
|
||||
class CodecTestWith2Params : public ::testing::TestWithParam<
|
||||
std::tr1::tuple< const libvpx_test::CodecFactory*, T1, T2 > > {
|
||||
};
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
class CodecTestWith3Params
|
||||
: public ::testing::TestWithParam<
|
||||
::testing::tuple<const libvpx_test::CodecFactory *, T1, T2, T3> > {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
class CodecTestWith4Params
|
||||
: public ::testing::TestWithParam< ::testing::tuple<
|
||||
const libvpx_test::CodecFactory *, T1, T2, T3, T4> > {};
|
||||
template<class T1, class T2, class T3>
|
||||
class CodecTestWith3Params : public ::testing::TestWithParam<
|
||||
std::tr1::tuple< const libvpx_test::CodecFactory*, T1, T2, T3 > > {
|
||||
};
|
||||
|
||||
/*
|
||||
* VP8 Codec Definitions
|
||||
@ -76,13 +74,15 @@ class CodecTestWith4Params
|
||||
#if CONFIG_VP8
|
||||
class VP8Decoder : public Decoder {
|
||||
public:
|
||||
explicit VP8Decoder(vpx_codec_dec_cfg_t cfg) : Decoder(cfg) {}
|
||||
VP8Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
|
||||
: Decoder(cfg, deadline) {}
|
||||
|
||||
VP8Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag)
|
||||
: Decoder(cfg, flag) {}
|
||||
VP8Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
|
||||
unsigned long deadline) // NOLINT
|
||||
: Decoder(cfg, flag, deadline) {}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t *CodecInterface() const {
|
||||
virtual vpx_codec_iface_t* CodecInterface() const {
|
||||
#if CONFIG_VP8_DECODER
|
||||
return &vpx_codec_vp8_dx_algo;
|
||||
#else
|
||||
@ -98,7 +98,7 @@ class VP8Encoder : public Encoder {
|
||||
: Encoder(cfg, deadline, init_flags, stats) {}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t *CodecInterface() const {
|
||||
virtual vpx_codec_iface_t* CodecInterface() const {
|
||||
#if CONFIG_VP8_ENCODER
|
||||
return &vpx_codec_vp8_cx_algo;
|
||||
#else
|
||||
@ -111,32 +111,28 @@ class VP8CodecFactory : public CodecFactory {
|
||||
public:
|
||||
VP8CodecFactory() : CodecFactory() {}
|
||||
|
||||
virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg) const {
|
||||
return CreateDecoder(cfg, 0);
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
unsigned long deadline) const {
|
||||
return CreateDecoder(cfg, 0, deadline);
|
||||
}
|
||||
|
||||
virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
const vpx_codec_flags_t flags) const {
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
const vpx_codec_flags_t flags,
|
||||
unsigned long deadline) const { // NOLINT
|
||||
#if CONFIG_VP8_DECODER
|
||||
return new VP8Decoder(cfg, flags);
|
||||
return new VP8Decoder(cfg, flags, deadline);
|
||||
#else
|
||||
(void)cfg;
|
||||
(void)flags;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual Encoder *CreateEncoder(vpx_codec_enc_cfg_t cfg,
|
||||
virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
|
||||
unsigned long deadline,
|
||||
const unsigned long init_flags,
|
||||
TwopassStatsStore *stats) const {
|
||||
#if CONFIG_VP8_ENCODER
|
||||
return new VP8Encoder(cfg, deadline, init_flags, stats);
|
||||
#else
|
||||
(void)cfg;
|
||||
(void)deadline;
|
||||
(void)init_flags;
|
||||
(void)stats;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
@ -146,8 +142,6 @@ class VP8CodecFactory : public CodecFactory {
|
||||
#if CONFIG_VP8_ENCODER
|
||||
return vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, cfg, usage);
|
||||
#else
|
||||
(void)cfg;
|
||||
(void)usage;
|
||||
return VPX_CODEC_INCAPABLE;
|
||||
#endif
|
||||
}
|
||||
@ -155,30 +149,32 @@ class VP8CodecFactory : public CodecFactory {
|
||||
|
||||
const libvpx_test::VP8CodecFactory kVP8;
|
||||
|
||||
#define VP8_INSTANTIATE_TEST_CASE(test, ...) \
|
||||
INSTANTIATE_TEST_CASE_P( \
|
||||
VP8, test, \
|
||||
::testing::Combine( \
|
||||
::testing::Values(static_cast<const libvpx_test::CodecFactory *>( \
|
||||
&libvpx_test::kVP8)), \
|
||||
#define VP8_INSTANTIATE_TEST_CASE(test, ...)\
|
||||
INSTANTIATE_TEST_CASE_P(VP8, test, \
|
||||
::testing::Combine( \
|
||||
::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \
|
||||
&libvpx_test::kVP8)), \
|
||||
__VA_ARGS__))
|
||||
#else
|
||||
#define VP8_INSTANTIATE_TEST_CASE(test, ...)
|
||||
#endif // CONFIG_VP8
|
||||
|
||||
|
||||
/*
|
||||
* VP9 Codec Definitions
|
||||
*/
|
||||
#if CONFIG_VP9
|
||||
class VP9Decoder : public Decoder {
|
||||
public:
|
||||
explicit VP9Decoder(vpx_codec_dec_cfg_t cfg) : Decoder(cfg) {}
|
||||
VP9Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
|
||||
: Decoder(cfg, deadline) {}
|
||||
|
||||
VP9Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag)
|
||||
: Decoder(cfg, flag) {}
|
||||
VP9Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
|
||||
unsigned long deadline) // NOLINT
|
||||
: Decoder(cfg, flag, deadline) {}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t *CodecInterface() const {
|
||||
virtual vpx_codec_iface_t* CodecInterface() const {
|
||||
#if CONFIG_VP9_DECODER
|
||||
return &vpx_codec_vp9_dx_algo;
|
||||
#else
|
||||
@ -194,7 +190,7 @@ class VP9Encoder : public Encoder {
|
||||
: Encoder(cfg, deadline, init_flags, stats) {}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t *CodecInterface() const {
|
||||
virtual vpx_codec_iface_t* CodecInterface() const {
|
||||
#if CONFIG_VP9_ENCODER
|
||||
return &vpx_codec_vp9_cx_algo;
|
||||
#else
|
||||
@ -207,32 +203,28 @@ class VP9CodecFactory : public CodecFactory {
|
||||
public:
|
||||
VP9CodecFactory() : CodecFactory() {}
|
||||
|
||||
virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg) const {
|
||||
return CreateDecoder(cfg, 0);
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
unsigned long deadline) const {
|
||||
return CreateDecoder(cfg, 0, deadline);
|
||||
}
|
||||
|
||||
virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
const vpx_codec_flags_t flags) const {
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
const vpx_codec_flags_t flags,
|
||||
unsigned long deadline) const { // NOLINT
|
||||
#if CONFIG_VP9_DECODER
|
||||
return new VP9Decoder(cfg, flags);
|
||||
return new VP9Decoder(cfg, flags, deadline);
|
||||
#else
|
||||
(void)cfg;
|
||||
(void)flags;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual Encoder *CreateEncoder(vpx_codec_enc_cfg_t cfg,
|
||||
virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
|
||||
unsigned long deadline,
|
||||
const unsigned long init_flags,
|
||||
TwopassStatsStore *stats) const {
|
||||
#if CONFIG_VP9_ENCODER
|
||||
return new VP9Encoder(cfg, deadline, init_flags, stats);
|
||||
#else
|
||||
(void)cfg;
|
||||
(void)deadline;
|
||||
(void)init_flags;
|
||||
(void)stats;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
@ -241,9 +233,9 @@ class VP9CodecFactory : public CodecFactory {
|
||||
int usage) const {
|
||||
#if CONFIG_VP9_ENCODER
|
||||
return vpx_codec_enc_config_default(&vpx_codec_vp9_cx_algo, cfg, usage);
|
||||
#elif CONFIG_VP10_ENCODER
|
||||
return vpx_codec_enc_config_default(&vpx_codec_vp10_cx_algo, cfg, usage);
|
||||
#else
|
||||
(void)cfg;
|
||||
(void)usage;
|
||||
return VPX_CODEC_INCAPABLE;
|
||||
#endif
|
||||
}
|
||||
@ -251,16 +243,106 @@ class VP9CodecFactory : public CodecFactory {
|
||||
|
||||
const libvpx_test::VP9CodecFactory kVP9;
|
||||
|
||||
#define VP9_INSTANTIATE_TEST_CASE(test, ...) \
|
||||
INSTANTIATE_TEST_CASE_P( \
|
||||
VP9, test, \
|
||||
::testing::Combine( \
|
||||
::testing::Values(static_cast<const libvpx_test::CodecFactory *>( \
|
||||
&libvpx_test::kVP9)), \
|
||||
#define VP9_INSTANTIATE_TEST_CASE(test, ...)\
|
||||
INSTANTIATE_TEST_CASE_P(VP9, test, \
|
||||
::testing::Combine( \
|
||||
::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \
|
||||
&libvpx_test::kVP9)), \
|
||||
__VA_ARGS__))
|
||||
#else
|
||||
#define VP9_INSTANTIATE_TEST_CASE(test, ...)
|
||||
#endif // CONFIG_VP9
|
||||
|
||||
/*
|
||||
* VP10 Codec Definitions
|
||||
*/
|
||||
#if CONFIG_VP10
|
||||
class VP10Decoder : public Decoder {
|
||||
public:
|
||||
VP10Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
|
||||
: Decoder(cfg, deadline) {}
|
||||
|
||||
VP10Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
|
||||
unsigned long deadline) // NOLINT
|
||||
: Decoder(cfg, flag, deadline) {}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t* CodecInterface() const {
|
||||
#if CONFIG_VP10_DECODER
|
||||
return &vpx_codec_vp10_dx_algo;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
class VP10Encoder : public Encoder {
|
||||
public:
|
||||
VP10Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
|
||||
const unsigned long init_flags, TwopassStatsStore *stats)
|
||||
: Encoder(cfg, deadline, init_flags, stats) {}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t* CodecInterface() const {
|
||||
#if CONFIG_VP10_ENCODER
|
||||
return &vpx_codec_vp10_cx_algo;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
class VP10CodecFactory : public CodecFactory {
|
||||
public:
|
||||
VP10CodecFactory() : CodecFactory() {}
|
||||
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
unsigned long deadline) const {
|
||||
return CreateDecoder(cfg, 0, deadline);
|
||||
}
|
||||
|
||||
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
|
||||
const vpx_codec_flags_t flags,
|
||||
unsigned long deadline) const { // NOLINT
|
||||
#if CONFIG_VP10_DECODER
|
||||
return new VP10Decoder(cfg, flags, deadline);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
|
||||
unsigned long deadline,
|
||||
const unsigned long init_flags,
|
||||
TwopassStatsStore *stats) const {
|
||||
#if CONFIG_VP10_ENCODER
|
||||
return new VP10Encoder(cfg, deadline, init_flags, stats);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
|
||||
int usage) const {
|
||||
#if CONFIG_VP10_ENCODER
|
||||
return vpx_codec_enc_config_default(&vpx_codec_vp10_cx_algo, cfg, usage);
|
||||
#else
|
||||
return VPX_CODEC_INCAPABLE;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
const libvpx_test::VP10CodecFactory kVP10;
|
||||
|
||||
#define VP10_INSTANTIATE_TEST_CASE(test, ...)\
|
||||
INSTANTIATE_TEST_CASE_P(VP10, test, \
|
||||
::testing::Combine( \
|
||||
::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \
|
||||
&libvpx_test::kVP10)), \
|
||||
__VA_ARGS__))
|
||||
#else
|
||||
#define VP10_INSTANTIATE_TEST_CASE(test, ...)
|
||||
#endif // CONFIG_VP10
|
||||
|
||||
} // namespace libvpx_test
|
||||
#endif // TEST_CODEC_FACTORY_H_
|
||||
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
|
||||
#include "test/acm_random.h"
|
||||
#include "test/buffer.h"
|
||||
#include "test/register_state_check.h"
|
||||
#include "vpx_ports/vpx_timer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using ::libvpx_test::ACMRandom;
|
||||
using ::libvpx_test::Buffer;
|
||||
|
||||
typedef void (*AvgPredFunc)(uint8_t *a, const uint8_t *b, int w, int h,
|
||||
const uint8_t *c, int c_stride);
|
||||
|
||||
uint8_t avg_with_rounding(uint8_t a, uint8_t b) { return (a + b + 1) >> 1; }
|
||||
|
||||
void reference_pred(const Buffer<uint8_t> &pred, const Buffer<uint8_t> &ref,
|
||||
int width, int height, Buffer<uint8_t> *avg) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
avg->TopLeftPixel()[y * avg->stride() + x] =
|
||||
avg_with_rounding(pred.TopLeftPixel()[y * pred.stride() + x],
|
||||
ref.TopLeftPixel()[y * ref.stride() + x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvgPredTest : public ::testing::TestWithParam<AvgPredFunc> {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
avg_pred_func_ = GetParam();
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
}
|
||||
|
||||
protected:
|
||||
AvgPredFunc avg_pred_func_;
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
|
||||
TEST_P(AvgPredTest, SizeCombinations) {
|
||||
// This is called as part of the sub pixel variance. As such it must be one of
|
||||
// the variance block sizes.
|
||||
|
||||
for (int width_pow = 2; width_pow <= 6; ++width_pow) {
|
||||
for (int height_pow = width_pow - 1; height_pow <= width_pow + 1;
|
||||
++height_pow) {
|
||||
// Don't test 4x2 or 64x128
|
||||
if (height_pow == 1 || height_pow == 7) continue;
|
||||
|
||||
// The sse2 special-cases when ref width == stride, so make sure to test
|
||||
// it.
|
||||
for (int ref_padding = 0; ref_padding < 2; ref_padding++) {
|
||||
const int width = 1 << width_pow;
|
||||
const int height = 1 << height_pow;
|
||||
// Only the reference buffer may have a stride not equal to width.
|
||||
Buffer<uint8_t> ref =
|
||||
Buffer<uint8_t>(width, height, ref_padding ? 8 : 0);
|
||||
ASSERT_TRUE(ref.Init());
|
||||
Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(pred.Init());
|
||||
Buffer<uint8_t> avg_ref = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(avg_ref.Init());
|
||||
Buffer<uint8_t> avg_chk = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(avg_chk.Init());
|
||||
|
||||
ref.Set(&rnd_, &ACMRandom::Rand8);
|
||||
pred.Set(&rnd_, &ACMRandom::Rand8);
|
||||
|
||||
reference_pred(pred, ref, width, height, &avg_ref);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
avg_pred_func_(avg_chk.TopLeftPixel(), pred.TopLeftPixel(), width,
|
||||
height, ref.TopLeftPixel(), ref.stride()));
|
||||
|
||||
EXPECT_TRUE(avg_chk.CheckValues(avg_ref));
|
||||
if (HasFailure()) {
|
||||
printf("Width: %d Height: %d\n", width, height);
|
||||
avg_chk.PrintDifference(avg_ref);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(AvgPredTest, CompareReferenceRandom) {
|
||||
const int width = 64;
|
||||
const int height = 32;
|
||||
Buffer<uint8_t> ref = Buffer<uint8_t>(width, height, 8);
|
||||
ASSERT_TRUE(ref.Init());
|
||||
Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(pred.Init());
|
||||
Buffer<uint8_t> avg_ref = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(avg_ref.Init());
|
||||
Buffer<uint8_t> avg_chk = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(avg_chk.Init());
|
||||
|
||||
for (int i = 0; i < 500; ++i) {
|
||||
ref.Set(&rnd_, &ACMRandom::Rand8);
|
||||
pred.Set(&rnd_, &ACMRandom::Rand8);
|
||||
|
||||
reference_pred(pred, ref, width, height, &avg_ref);
|
||||
ASM_REGISTER_STATE_CHECK(avg_pred_func_(avg_chk.TopLeftPixel(),
|
||||
pred.TopLeftPixel(), width, height,
|
||||
ref.TopLeftPixel(), ref.stride()));
|
||||
EXPECT_TRUE(avg_chk.CheckValues(avg_ref));
|
||||
if (HasFailure()) {
|
||||
printf("Width: %d Height: %d\n", width, height);
|
||||
avg_chk.PrintDifference(avg_ref);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(AvgPredTest, DISABLED_Speed) {
|
||||
for (int width_pow = 2; width_pow <= 6; ++width_pow) {
|
||||
for (int height_pow = width_pow - 1; height_pow <= width_pow + 1;
|
||||
++height_pow) {
|
||||
// Don't test 4x2 or 64x128
|
||||
if (height_pow == 1 || height_pow == 7) continue;
|
||||
|
||||
for (int ref_padding = 0; ref_padding < 2; ref_padding++) {
|
||||
const int width = 1 << width_pow;
|
||||
const int height = 1 << height_pow;
|
||||
Buffer<uint8_t> ref =
|
||||
Buffer<uint8_t>(width, height, ref_padding ? 8 : 0);
|
||||
ASSERT_TRUE(ref.Init());
|
||||
Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(pred.Init());
|
||||
Buffer<uint8_t> avg = Buffer<uint8_t>(width, height, 0, 16);
|
||||
ASSERT_TRUE(avg.Init());
|
||||
|
||||
ref.Set(&rnd_, &ACMRandom::Rand8);
|
||||
pred.Set(&rnd_, &ACMRandom::Rand8);
|
||||
|
||||
vpx_usec_timer timer;
|
||||
vpx_usec_timer_start(&timer);
|
||||
for (int i = 0; i < 10000000 / (width * height); ++i) {
|
||||
avg_pred_func_(avg.TopLeftPixel(), pred.TopLeftPixel(), width, height,
|
||||
ref.TopLeftPixel(), ref.stride());
|
||||
}
|
||||
vpx_usec_timer_mark(&timer);
|
||||
|
||||
const int elapsed_time =
|
||||
static_cast<int>(vpx_usec_timer_elapsed(&timer));
|
||||
printf("Average Test (ref_padding: %d) %dx%d time: %5d us\n",
|
||||
ref_padding, width, height, elapsed_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, AvgPredTest,
|
||||
::testing::Values(&vpx_comp_avg_pred_c));
|
||||
|
||||
#if HAVE_SSE2
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, AvgPredTest,
|
||||
::testing::Values(&vpx_comp_avg_pred_sse2));
|
||||
#endif // HAVE_SSE2
|
||||
|
||||
#if HAVE_NEON
|
||||
INSTANTIATE_TEST_CASE_P(NEON, AvgPredTest,
|
||||
::testing::Values(&vpx_comp_avg_pred_neon));
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if HAVE_VSX
|
||||
INSTANTIATE_TEST_CASE_P(VSX, AvgPredTest,
|
||||
::testing::Values(&vpx_comp_avg_pred_vsx));
|
||||
#endif // HAVE_VSX
|
||||
} // namespace
|
@ -15,13 +15,11 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class ConfigTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
class ConfigTest : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
protected:
|
||||
ConfigTest()
|
||||
: EncoderTest(GET_PARAM(0)), frame_count_in_(0), frame_count_out_(0),
|
||||
frame_count_max_(0) {}
|
||||
ConfigTest() : EncoderTest(GET_PARAM(0)),
|
||||
frame_count_in_(0), frame_count_out_(0), frame_count_max_(0) {}
|
||||
virtual ~ConfigTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
@ -34,12 +32,12 @@ class ConfigTest
|
||||
frame_count_out_ = 0;
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(libvpx_test::VideoSource * /*video*/) {
|
||||
virtual void PreEncodeFrameHook(libvpx_test::VideoSource* /*video*/) {
|
||||
++frame_count_in_;
|
||||
abort_ |= (frame_count_in_ >= frame_count_max_);
|
||||
}
|
||||
|
||||
virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {
|
||||
virtual void FramePktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {
|
||||
++frame_count_out_;
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,12 @@
|
||||
#include "vpx_dsp/ssim.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
|
||||
extern "C" double vpx_get_ssim_metrics(uint8_t *img1, int img1_pitch,
|
||||
uint8_t *img2, int img2_pitch, int width,
|
||||
int height, Ssimv *sv2, Metrics *m,
|
||||
int do_inconsistency);
|
||||
extern "C"
|
||||
double vpx_get_ssim_metrics(uint8_t *img1, int img1_pitch,
|
||||
uint8_t *img2, int img2_pitch,
|
||||
int width, int height,
|
||||
Ssimv *sv2, Metrics *m,
|
||||
int do_inconsistency);
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
@ -39,18 +41,20 @@ class ConsistencyTestBase : public ::testing::Test {
|
||||
ConsistencyTestBase(int width, int height) : width_(width), height_(height) {}
|
||||
|
||||
static void SetUpTestCase() {
|
||||
source_data_[0] = reinterpret_cast<uint8_t *>(
|
||||
source_data_[0] = reinterpret_cast<uint8_t*>(
|
||||
vpx_memalign(kDataAlignment, kDataBufferSize));
|
||||
reference_data_[0] = reinterpret_cast<uint8_t *>(
|
||||
reference_data_[0] = reinterpret_cast<uint8_t*>(
|
||||
vpx_memalign(kDataAlignment, kDataBufferSize));
|
||||
source_data_[1] = reinterpret_cast<uint8_t *>(
|
||||
source_data_[1] = reinterpret_cast<uint8_t*>(
|
||||
vpx_memalign(kDataAlignment, kDataBufferSize));
|
||||
reference_data_[1] = reinterpret_cast<uint8_t *>(
|
||||
reference_data_[1] = reinterpret_cast<uint8_t*>(
|
||||
vpx_memalign(kDataAlignment, kDataBufferSize));
|
||||
ssim_array_ = new Ssimv[kDataBufferSize / 16];
|
||||
}
|
||||
|
||||
static void ClearSsim() { memset(ssim_array_, 0, kDataBufferSize / 16); }
|
||||
static void ClearSsim() {
|
||||
memset(ssim_array_, 0, kDataBufferSize / 16);
|
||||
}
|
||||
static void TearDownTestCase() {
|
||||
vpx_free(source_data_[0]);
|
||||
source_data_[0] = NULL;
|
||||
@ -64,12 +68,14 @@ class ConsistencyTestBase : public ::testing::Test {
|
||||
delete[] ssim_array_;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
virtual void TearDown() {
|
||||
libvpx_test::ClearSystemState();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Handle frames up to 640x480
|
||||
static const int kDataAlignment = 16;
|
||||
static const int kDataBufferSize = 640 * 480;
|
||||
static const int kDataBufferSize = 640*480;
|
||||
|
||||
virtual void SetUp() {
|
||||
source_stride_ = (width_ + 31) & ~31;
|
||||
@ -116,9 +122,9 @@ class ConsistencyTestBase : public ::testing::Test {
|
||||
}
|
||||
}
|
||||
int width_, height_;
|
||||
static uint8_t *source_data_[2];
|
||||
static uint8_t* source_data_[2];
|
||||
int source_stride_;
|
||||
static uint8_t *reference_data_[2];
|
||||
static uint8_t* reference_data_[2];
|
||||
int reference_stride_;
|
||||
static Ssimv *ssim_array_;
|
||||
Metrics metrics_;
|
||||
@ -127,7 +133,7 @@ class ConsistencyTestBase : public ::testing::Test {
|
||||
};
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
typedef ::testing::tuple<int, int> ConsistencyParam;
|
||||
typedef std::tr1::tuple<int, int> ConsistencyParam;
|
||||
class ConsistencyVP9Test
|
||||
: public ConsistencyTestBase,
|
||||
public ::testing::WithParamInterface<ConsistencyParam> {
|
||||
@ -136,17 +142,18 @@ class ConsistencyVP9Test
|
||||
|
||||
protected:
|
||||
double CheckConsistency(int frame) {
|
||||
EXPECT_LT(frame, 2) << "Frame to check has to be less than 2.";
|
||||
return vpx_get_ssim_metrics(source_data_[frame], source_stride_,
|
||||
reference_data_[frame], reference_stride_,
|
||||
width_, height_, ssim_array_, &metrics_, 1);
|
||||
EXPECT_LT(frame, 2)<< "Frame to check has to be less than 2.";
|
||||
return
|
||||
vpx_get_ssim_metrics(source_data_[frame], source_stride_,
|
||||
reference_data_[frame], reference_stride_,
|
||||
width_, height_, ssim_array_, &metrics_, 1);
|
||||
}
|
||||
};
|
||||
#endif // CONFIG_VP9_ENCODER
|
||||
|
||||
uint8_t *ConsistencyTestBase::source_data_[2] = { NULL, NULL };
|
||||
uint8_t *ConsistencyTestBase::reference_data_[2] = { NULL, NULL };
|
||||
Ssimv *ConsistencyTestBase::ssim_array_ = NULL;
|
||||
uint8_t* ConsistencyTestBase::source_data_[2] = {NULL, NULL};
|
||||
uint8_t* ConsistencyTestBase::reference_data_[2] = {NULL, NULL};
|
||||
Ssimv* ConsistencyTestBase::ssim_array_ = NULL;
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
TEST_P(ConsistencyVP9Test, ConsistencyIsZero) {
|
||||
@ -198,14 +205,17 @@ TEST_P(ConsistencyVP9Test, ConsistencyIsZero) {
|
||||
}
|
||||
#endif // CONFIG_VP9_ENCODER
|
||||
|
||||
using ::testing::make_tuple;
|
||||
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// C functions
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
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,
|
||||
::testing::ValuesIn(c_vp9_tests));
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,8 +23,10 @@ class CpuSpeedTest
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
CpuSpeedTest()
|
||||
: EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
|
||||
set_cpu_used_(GET_PARAM(2)), min_psnr_(kMaxPSNR),
|
||||
: EncoderTest(GET_PARAM(0)),
|
||||
encoding_mode_(GET_PARAM(1)),
|
||||
set_cpu_used_(GET_PARAM(2)),
|
||||
min_psnr_(kMaxPSNR),
|
||||
tune_content_(VP9E_CONTENT_DEFAULT) {}
|
||||
virtual ~CpuSpeedTest() {}
|
||||
|
||||
@ -40,7 +42,9 @@ class CpuSpeedTest
|
||||
}
|
||||
}
|
||||
|
||||
virtual void BeginPassHook(unsigned int /*pass*/) { min_psnr_ = kMaxPSNR; }
|
||||
virtual void BeginPassHook(unsigned int /*pass*/) {
|
||||
min_psnr_ = kMaxPSNR;
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
@ -57,7 +61,8 @@ class CpuSpeedTest
|
||||
}
|
||||
|
||||
virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
if (pkt->data.psnr.psnr[0] < min_psnr_) min_psnr_ = pkt->data.psnr.psnr[0];
|
||||
if (pkt->data.psnr.psnr[0] < min_psnr_)
|
||||
min_psnr_ = pkt->data.psnr.psnr[0];
|
||||
}
|
||||
|
||||
::libvpx_test::TestMode encoding_mode_;
|
||||
@ -148,9 +153,14 @@ TEST_P(CpuSpeedTest, TestLowBitrate) {
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(CpuSpeedTest,
|
||||
::testing::Values(::libvpx_test::kTwoPassGood,
|
||||
::libvpx_test::kOnePassGood,
|
||||
::libvpx_test::kRealTime),
|
||||
::testing::Range(0, 9));
|
||||
VP9_INSTANTIATE_TEST_CASE(
|
||||
CpuSpeedTest,
|
||||
::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
|
||||
::libvpx_test::kRealTime),
|
||||
::testing::Range(0, 9));
|
||||
|
||||
VP10_INSTANTIATE_TEST_CASE(
|
||||
CpuSpeedTest,
|
||||
::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 3));
|
||||
} // namespace
|
||||
|
@ -24,12 +24,14 @@ const int kCQLevelStep = 8;
|
||||
const unsigned int kCQTargetBitrate = 2000;
|
||||
|
||||
class CQTest : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<int> {
|
||||
public ::libvpx_test::CodecTestWithParam<int> {
|
||||
public:
|
||||
// maps the cqlevel to the bitrate produced.
|
||||
typedef std::map<int, uint32_t> BitrateMap;
|
||||
|
||||
static void SetUpTestCase() { bitrates_.clear(); }
|
||||
static void SetUpTestCase() {
|
||||
bitrates_.clear();
|
||||
}
|
||||
|
||||
static void TearDownTestCase() {
|
||||
ASSERT_TRUE(!HasFailure())
|
||||
@ -126,6 +128,7 @@ TEST_P(CQTest, LinearPSNRIsHigherForCQLevel) {
|
||||
EXPECT_GE(cq_psnr_lin, vbr_psnr_lin);
|
||||
}
|
||||
|
||||
VP8_INSTANTIATE_TEST_CASE(CQTest, ::testing::Range(kCQLevelMin, kCQLevelMax,
|
||||
kCQLevelStep));
|
||||
VP8_INSTANTIATE_TEST_CASE(CQTest,
|
||||
::testing::Range(kCQLevelMin, kCQLevelMax,
|
||||
kCQLevelStep));
|
||||
} // namespace
|
||||
|
1135
test/datarate_test.cc
Normal file
1135
test/datarate_test.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,12 +25,20 @@
|
||||
#include "vpx/vpx_codec.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_ports/mem.h"
|
||||
#include "vpx_ports/msvc.h" // for round()
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
static int round(double x) {
|
||||
if (x < 0)
|
||||
return static_cast<int>(ceil(x - 0.5));
|
||||
else
|
||||
return static_cast<int>(floor(x + 0.5));
|
||||
}
|
||||
#endif
|
||||
|
||||
const int kNumCoeffs = 256;
|
||||
const double C1 = 0.995184726672197;
|
||||
const double C2 = 0.98078528040323;
|
||||
@ -54,16 +62,16 @@ void butterfly_16x16_dct_1d(double input[16], double output[16]) {
|
||||
double temp1, temp2;
|
||||
|
||||
// step 1
|
||||
step[0] = input[0] + input[15];
|
||||
step[1] = input[1] + input[14];
|
||||
step[2] = input[2] + input[13];
|
||||
step[3] = input[3] + input[12];
|
||||
step[4] = input[4] + input[11];
|
||||
step[5] = input[5] + input[10];
|
||||
step[6] = input[6] + input[9];
|
||||
step[7] = input[7] + input[8];
|
||||
step[8] = input[7] - input[8];
|
||||
step[9] = input[6] - input[9];
|
||||
step[ 0] = input[0] + input[15];
|
||||
step[ 1] = input[1] + input[14];
|
||||
step[ 2] = input[2] + input[13];
|
||||
step[ 3] = input[3] + input[12];
|
||||
step[ 4] = input[4] + input[11];
|
||||
step[ 5] = input[5] + input[10];
|
||||
step[ 6] = input[6] + input[ 9];
|
||||
step[ 7] = input[7] + input[ 8];
|
||||
step[ 8] = input[7] - input[ 8];
|
||||
step[ 9] = input[6] - input[ 9];
|
||||
step[10] = input[5] - input[10];
|
||||
step[11] = input[4] - input[11];
|
||||
step[12] = input[3] - input[12];
|
||||
@ -81,13 +89,13 @@ void butterfly_16x16_dct_1d(double input[16], double output[16]) {
|
||||
output[6] = step[1] - step[6];
|
||||
output[7] = step[0] - step[7];
|
||||
|
||||
temp1 = step[8] * C7;
|
||||
temp1 = step[ 8] * C7;
|
||||
temp2 = step[15] * C9;
|
||||
output[8] = temp1 + temp2;
|
||||
output[ 8] = temp1 + temp2;
|
||||
|
||||
temp1 = step[9] * C11;
|
||||
temp1 = step[ 9] * C11;
|
||||
temp2 = step[14] * C5;
|
||||
output[9] = temp1 - temp2;
|
||||
output[ 9] = temp1 - temp2;
|
||||
|
||||
temp1 = step[10] * C3;
|
||||
temp2 = step[13] * C13;
|
||||
@ -105,40 +113,40 @@ void butterfly_16x16_dct_1d(double input[16], double output[16]) {
|
||||
temp2 = step[13] * C3;
|
||||
output[13] = temp2 - temp1;
|
||||
|
||||
temp1 = step[9] * C5;
|
||||
temp1 = step[ 9] * C5;
|
||||
temp2 = step[14] * C11;
|
||||
output[14] = temp2 + temp1;
|
||||
|
||||
temp1 = step[8] * C9;
|
||||
temp1 = step[ 8] * C9;
|
||||
temp2 = step[15] * C7;
|
||||
output[15] = temp2 - temp1;
|
||||
|
||||
// step 3
|
||||
step[0] = output[0] + output[3];
|
||||
step[1] = output[1] + output[2];
|
||||
step[2] = output[1] - output[2];
|
||||
step[3] = output[0] - output[3];
|
||||
step[ 0] = output[0] + output[3];
|
||||
step[ 1] = output[1] + output[2];
|
||||
step[ 2] = output[1] - output[2];
|
||||
step[ 3] = output[0] - output[3];
|
||||
|
||||
temp1 = output[4] * C14;
|
||||
temp2 = output[7] * C2;
|
||||
step[4] = temp1 + temp2;
|
||||
step[ 4] = temp1 + temp2;
|
||||
|
||||
temp1 = output[5] * C10;
|
||||
temp2 = output[6] * C6;
|
||||
step[5] = temp1 + temp2;
|
||||
step[ 5] = temp1 + temp2;
|
||||
|
||||
temp1 = output[5] * C6;
|
||||
temp2 = output[6] * C10;
|
||||
step[6] = temp2 - temp1;
|
||||
step[ 6] = temp2 - temp1;
|
||||
|
||||
temp1 = output[4] * C2;
|
||||
temp2 = output[7] * C14;
|
||||
step[7] = temp2 - temp1;
|
||||
step[ 7] = temp2 - temp1;
|
||||
|
||||
step[8] = output[8] + output[11];
|
||||
step[9] = output[9] + output[10];
|
||||
step[10] = output[9] - output[10];
|
||||
step[11] = output[8] - output[11];
|
||||
step[ 8] = output[ 8] + output[11];
|
||||
step[ 9] = output[ 9] + output[10];
|
||||
step[10] = output[ 9] - output[10];
|
||||
step[11] = output[ 8] - output[11];
|
||||
|
||||
step[12] = output[12] + output[15];
|
||||
step[13] = output[13] + output[14];
|
||||
@ -146,25 +154,25 @@ void butterfly_16x16_dct_1d(double input[16], double output[16]) {
|
||||
step[15] = output[12] - output[15];
|
||||
|
||||
// step 4
|
||||
output[0] = (step[0] + step[1]);
|
||||
output[8] = (step[0] - step[1]);
|
||||
output[ 0] = (step[ 0] + step[ 1]);
|
||||
output[ 8] = (step[ 0] - step[ 1]);
|
||||
|
||||
temp1 = step[2] * C12;
|
||||
temp2 = step[3] * C4;
|
||||
temp1 = temp1 + temp2;
|
||||
output[4] = 2 * (temp1 * C8);
|
||||
output[ 4] = 2*(temp1 * C8);
|
||||
|
||||
temp1 = step[2] * C4;
|
||||
temp2 = step[3] * C12;
|
||||
temp1 = temp2 - temp1;
|
||||
output[12] = 2 * (temp1 * C8);
|
||||
|
||||
output[2] = 2 * ((step[4] + step[5]) * C8);
|
||||
output[14] = 2 * ((step[7] - step[6]) * C8);
|
||||
output[ 2] = 2 * ((step[4] + step[ 5]) * C8);
|
||||
output[14] = 2 * ((step[7] - step[ 6]) * C8);
|
||||
|
||||
temp1 = step[4] - step[5];
|
||||
temp2 = step[6] + step[7];
|
||||
output[6] = (temp1 + temp2);
|
||||
output[ 6] = (temp1 + temp2);
|
||||
output[10] = (temp1 - temp2);
|
||||
|
||||
intermediate[8] = step[8] + step[14];
|
||||
@ -180,18 +188,18 @@ void butterfly_16x16_dct_1d(double input[16], double output[16]) {
|
||||
temp1 = temp2 + temp1;
|
||||
output[13] = 2 * (temp1 * C8);
|
||||
|
||||
output[9] = 2 * ((step[10] + step[11]) * C8);
|
||||
output[ 9] = 2 * ((step[10] + step[11]) * C8);
|
||||
|
||||
intermediate[11] = step[10] - step[11];
|
||||
intermediate[12] = step[12] + step[13];
|
||||
intermediate[13] = step[12] - step[13];
|
||||
intermediate[14] = step[8] - step[14];
|
||||
intermediate[15] = step[9] - step[15];
|
||||
intermediate[14] = step[ 8] - step[14];
|
||||
intermediate[15] = step[ 9] - step[15];
|
||||
|
||||
output[15] = (intermediate[11] + intermediate[12]);
|
||||
output[1] = -(intermediate[11] - intermediate[12]);
|
||||
output[ 1] = -(intermediate[11] - intermediate[12]);
|
||||
|
||||
output[7] = 2 * (intermediate[13] * C8);
|
||||
output[ 7] = 2 * (intermediate[13] * C8);
|
||||
|
||||
temp1 = intermediate[14] * C12;
|
||||
temp2 = intermediate[15] * C4;
|
||||
@ -201,24 +209,28 @@ void butterfly_16x16_dct_1d(double input[16], double output[16]) {
|
||||
temp1 = intermediate[14] * C4;
|
||||
temp2 = intermediate[15] * C12;
|
||||
temp1 = temp2 + temp1;
|
||||
output[5] = 2 * (temp1 * C8);
|
||||
output[ 5] = 2 * (temp1 * C8);
|
||||
}
|
||||
|
||||
void reference_16x16_dct_2d(int16_t input[256], double output[256]) {
|
||||
// First transform columns
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
double temp_in[16], temp_out[16];
|
||||
for (int j = 0; j < 16; ++j) temp_in[j] = input[j * 16 + i];
|
||||
for (int j = 0; j < 16; ++j)
|
||||
temp_in[j] = input[j * 16 + i];
|
||||
butterfly_16x16_dct_1d(temp_in, temp_out);
|
||||
for (int j = 0; j < 16; ++j) output[j * 16 + i] = temp_out[j];
|
||||
for (int j = 0; j < 16; ++j)
|
||||
output[j * 16 + i] = temp_out[j];
|
||||
}
|
||||
// Then transform rows
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
double temp_in[16], temp_out[16];
|
||||
for (int j = 0; j < 16; ++j) temp_in[j] = output[j + i * 16];
|
||||
for (int j = 0; j < 16; ++j)
|
||||
temp_in[j] = output[j + i * 16];
|
||||
butterfly_16x16_dct_1d(temp_in, temp_out);
|
||||
// Scale by some magic number
|
||||
for (int j = 0; j < 16; ++j) output[j + i * 16] = temp_out[j] / 2;
|
||||
for (int j = 0; j < 16; ++j)
|
||||
output[j + i * 16] = temp_out[j]/2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,10 +241,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,
|
||||
int tx_type);
|
||||
|
||||
typedef ::testing::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t>
|
||||
Dct16x16Param;
|
||||
typedef ::testing::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param;
|
||||
typedef ::testing::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t>
|
||||
typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct16x16Param;
|
||||
typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param;
|
||||
typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t>
|
||||
Idct16x16Param;
|
||||
|
||||
void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride,
|
||||
@ -245,7 +256,8 @@ void idct16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
|
||||
vpx_idct16x16_256_add_c(in, dest, stride);
|
||||
}
|
||||
|
||||
void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
|
||||
void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride,
|
||||
int tx_type) {
|
||||
vp9_fht16x16_c(in, out, stride, tx_type);
|
||||
}
|
||||
|
||||
@ -256,11 +268,11 @@ void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
void idct16x16_10(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
vpx_highbd_idct16x16_256_add_c(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct16x16_12(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
vpx_highbd_idct16x16_256_add_c(in, out, stride, 12);
|
||||
}
|
||||
|
||||
void idct16x16_10_ref(const tran_low_t *in, uint8_t *out, int stride,
|
||||
@ -274,36 +286,36 @@ void idct16x16_12_ref(const tran_low_t *in, uint8_t *out, int stride,
|
||||
}
|
||||
|
||||
void iht16x16_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
|
||||
vp9_highbd_iht16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 10);
|
||||
vp9_highbd_iht16x16_256_add_c(in, out, stride, tx_type, 10);
|
||||
}
|
||||
|
||||
void iht16x16_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
|
||||
vp9_highbd_iht16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 12);
|
||||
vp9_highbd_iht16x16_256_add_c(in, out, stride, tx_type, 12);
|
||||
}
|
||||
|
||||
#if HAVE_SSE2
|
||||
void idct16x16_10_add_10_c(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_10_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
vpx_highbd_idct16x16_10_add_c(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct16x16_10_add_12_c(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_10_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
vpx_highbd_idct16x16_10_add_c(in, out, stride, 12);
|
||||
}
|
||||
|
||||
void idct16x16_256_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_256_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
vpx_highbd_idct16x16_256_add_sse2(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct16x16_256_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_256_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
vpx_highbd_idct16x16_256_add_sse2(in, out, stride, 12);
|
||||
}
|
||||
|
||||
void idct16x16_10_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_10_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
vpx_highbd_idct16x16_10_add_sse2(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct16x16_10_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct16x16_10_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
vpx_highbd_idct16x16_10_add_sse2(in, out, stride, 12);
|
||||
}
|
||||
#endif // HAVE_SSE2
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
@ -347,31 +359,33 @@ class Trans16x16TestBase {
|
||||
}
|
||||
}
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunFwdTxfm(test_input_block, test_temp_block, pitch_));
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
|
||||
test_temp_block, pitch_));
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(test_temp_block, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(test_temp_block, CAST_TO_BYTEPTR(dst16), pitch_));
|
||||
RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int32_t diff =
|
||||
bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
|
||||
const uint32_t diff =
|
||||
bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
|
||||
#else
|
||||
const int32_t diff = dst[j] - src[j];
|
||||
const uint32_t diff = dst[j] - src[j];
|
||||
#endif
|
||||
const uint32_t error = diff * diff;
|
||||
if (max_error < error) max_error = error;
|
||||
if (max_error < error)
|
||||
max_error = error;
|
||||
total_error += error;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error)
|
||||
EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error)
|
||||
<< "Error: 16x16 FHT/IHT has an individual round trip error > 1";
|
||||
|
||||
EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error)
|
||||
@ -387,9 +401,8 @@ class Trans16x16TestBase {
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with input range [-mask_, mask_].
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
|
||||
}
|
||||
|
||||
fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
|
||||
@ -413,14 +426,16 @@ class Trans16x16TestBase {
|
||||
input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
|
||||
}
|
||||
if (i == 0) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = mask_;
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = mask_;
|
||||
} else if (i == 1) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = -mask_;
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = -mask_;
|
||||
}
|
||||
|
||||
fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunFwdTxfm(input_extreme_block, output_block, pitch_));
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
|
||||
output_block, pitch_));
|
||||
|
||||
// The minimum quant value is 4.
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
@ -449,12 +464,12 @@ class Trans16x16TestBase {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
|
||||
}
|
||||
if (i == 0) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = mask_;
|
||||
}
|
||||
if (i == 1) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = -mask_;
|
||||
}
|
||||
if (i == 0)
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = mask_;
|
||||
if (i == 1)
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = -mask_;
|
||||
|
||||
fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
|
||||
|
||||
@ -468,25 +483,26 @@ class Trans16x16TestBase {
|
||||
|
||||
// quantization with maximum allowed step sizes
|
||||
output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred;
|
||||
for (int j = 1; j < kNumCoeffs; ++j) {
|
||||
for (int j = 1; j < kNumCoeffs; ++j)
|
||||
output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred;
|
||||
}
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
inv_txfm_ref(output_ref_block, CAST_TO_BYTEPTR(ref16), pitch_,
|
||||
inv_txfm_ref(output_ref_block, CONVERT_TO_BYTEPTR(ref16), pitch_,
|
||||
tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(output_ref_block, CAST_TO_BYTEPTR(dst16), pitch_));
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block,
|
||||
CONVERT_TO_BYTEPTR(dst16), pitch_));
|
||||
#endif
|
||||
}
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) EXPECT_EQ(ref[j], dst[j]);
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
EXPECT_EQ(ref[j], dst[j]);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) EXPECT_EQ(ref16[j], dst16[j]);
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
EXPECT_EQ(ref16[j], dst16[j]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -523,15 +539,15 @@ class Trans16x16TestBase {
|
||||
}
|
||||
|
||||
reference_16x16_dct_2d(in, out_r);
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
|
||||
}
|
||||
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), 16));
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
|
||||
16));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
}
|
||||
|
||||
@ -544,7 +560,8 @@ class Trans16x16TestBase {
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
const uint32_t error = diff * diff;
|
||||
EXPECT_GE(1u, error)
|
||||
<< "Error: 16x16 IDCT has error " << error << " at index " << j;
|
||||
<< "Error: 16x16 IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -585,9 +602,9 @@ class Trans16x16TestBase {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
|
||||
} else {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_txfm(coeff, CAST_TO_BYTEPTR(ref16), pitch_);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_));
|
||||
ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_);
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
|
||||
pitch_));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
}
|
||||
|
||||
@ -599,8 +616,9 @@ class Trans16x16TestBase {
|
||||
const uint32_t diff = dst[j] - ref[j];
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
const uint32_t error = diff * diff;
|
||||
EXPECT_EQ(0u, error) << "Error: 16x16 IDCT Comparison has error "
|
||||
<< error << " at index " << j;
|
||||
EXPECT_EQ(0u, error)
|
||||
<< "Error: 16x16 IDCT Comparison has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -613,25 +631,32 @@ class Trans16x16TestBase {
|
||||
IhtFunc inv_txfm_ref;
|
||||
};
|
||||
|
||||
class Trans16x16DCT : public Trans16x16TestBase,
|
||||
public ::testing::TestWithParam<Dct16x16Param> {
|
||||
class Trans16x16DCT
|
||||
: public Trans16x16TestBase,
|
||||
public ::testing::TestWithParam<Dct16x16Param> {
|
||||
public:
|
||||
virtual ~Trans16x16DCT() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
pitch_ = 16;
|
||||
pitch_ = 16;
|
||||
fwd_txfm_ref = fdct16x16_ref;
|
||||
inv_txfm_ref = idct16x16_ref;
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
switch (bit_depth_) {
|
||||
case VPX_BITS_10: inv_txfm_ref = idct16x16_10_ref; break;
|
||||
case VPX_BITS_12: inv_txfm_ref = idct16x16_12_ref; break;
|
||||
default: inv_txfm_ref = idct16x16_ref; break;
|
||||
case VPX_BITS_10:
|
||||
inv_txfm_ref = idct16x16_10_ref;
|
||||
break;
|
||||
case VPX_BITS_12:
|
||||
inv_txfm_ref = idct16x16_12_ref;
|
||||
break;
|
||||
default:
|
||||
inv_txfm_ref = idct16x16_ref;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
inv_txfm_ref = idct16x16_ref;
|
||||
@ -651,11 +676,17 @@ class Trans16x16DCT : public Trans16x16TestBase,
|
||||
IdctFunc inv_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(Trans16x16DCT, AccuracyCheck) { RunAccuracyCheck(); }
|
||||
TEST_P(Trans16x16DCT, AccuracyCheck) {
|
||||
RunAccuracyCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans16x16DCT, CoeffCheck) { RunCoeffCheck(); }
|
||||
TEST_P(Trans16x16DCT, CoeffCheck) {
|
||||
RunCoeffCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans16x16DCT, MemCheck) { RunMemCheck(); }
|
||||
TEST_P(Trans16x16DCT, MemCheck) {
|
||||
RunMemCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans16x16DCT, QuantCheck) {
|
||||
// Use maximally allowed quantization step sizes for DC and AC
|
||||
@ -663,27 +694,36 @@ TEST_P(Trans16x16DCT, QuantCheck) {
|
||||
RunQuantCheck(1336, 1828);
|
||||
}
|
||||
|
||||
TEST_P(Trans16x16DCT, InvAccuracyCheck) { RunInvAccuracyCheck(); }
|
||||
TEST_P(Trans16x16DCT, InvAccuracyCheck) {
|
||||
RunInvAccuracyCheck();
|
||||
}
|
||||
|
||||
class Trans16x16HT : public Trans16x16TestBase,
|
||||
public ::testing::TestWithParam<Ht16x16Param> {
|
||||
class Trans16x16HT
|
||||
: public Trans16x16TestBase,
|
||||
public ::testing::TestWithParam<Ht16x16Param> {
|
||||
public:
|
||||
virtual ~Trans16x16HT() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
pitch_ = 16;
|
||||
pitch_ = 16;
|
||||
fwd_txfm_ref = fht16x16_ref;
|
||||
inv_txfm_ref = iht16x16_ref;
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
switch (bit_depth_) {
|
||||
case VPX_BITS_10: inv_txfm_ref = iht16x16_10; break;
|
||||
case VPX_BITS_12: inv_txfm_ref = iht16x16_12; break;
|
||||
default: inv_txfm_ref = iht16x16_ref; break;
|
||||
case VPX_BITS_10:
|
||||
inv_txfm_ref = iht16x16_10;
|
||||
break;
|
||||
case VPX_BITS_12:
|
||||
inv_txfm_ref = iht16x16_12;
|
||||
break;
|
||||
default:
|
||||
inv_txfm_ref = iht16x16_ref;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
inv_txfm_ref = iht16x16_ref;
|
||||
@ -703,11 +743,17 @@ class Trans16x16HT : public Trans16x16TestBase,
|
||||
IhtFunc inv_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(Trans16x16HT, AccuracyCheck) { RunAccuracyCheck(); }
|
||||
TEST_P(Trans16x16HT, AccuracyCheck) {
|
||||
RunAccuracyCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans16x16HT, CoeffCheck) { RunCoeffCheck(); }
|
||||
TEST_P(Trans16x16HT, CoeffCheck) {
|
||||
RunCoeffCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans16x16HT, MemCheck) { RunMemCheck(); }
|
||||
TEST_P(Trans16x16HT, MemCheck) {
|
||||
RunMemCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans16x16HT, QuantCheck) {
|
||||
// The encoder skips any non-DC intra prediction modes,
|
||||
@ -715,8 +761,9 @@ TEST_P(Trans16x16HT, QuantCheck) {
|
||||
RunQuantCheck(429, 729);
|
||||
}
|
||||
|
||||
class InvTrans16x16DCT : public Trans16x16TestBase,
|
||||
public ::testing::TestWithParam<Idct16x16Param> {
|
||||
class InvTrans16x16DCT
|
||||
: public Trans16x16TestBase,
|
||||
public ::testing::TestWithParam<Idct16x16Param> {
|
||||
public:
|
||||
virtual ~InvTrans16x16DCT() {}
|
||||
|
||||
@ -727,7 +774,7 @@ class InvTrans16x16DCT : public Trans16x16TestBase,
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
pitch_ = 16;
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
}
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
@ -745,7 +792,68 @@ TEST_P(InvTrans16x16DCT, CompareReference) {
|
||||
CompareInvReference(ref_txfm_, thresh_);
|
||||
}
|
||||
|
||||
using ::testing::make_tuple;
|
||||
class PartialTrans16x16Test
|
||||
: public ::testing::TestWithParam<
|
||||
std::tr1::tuple<FdctFunc, vpx_bit_depth_t> > {
|
||||
public:
|
||||
virtual ~PartialTrans16x16Test() {}
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
bit_depth_ = GET_PARAM(1);
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
vpx_bit_depth_t bit_depth_;
|
||||
FdctFunc fwd_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(PartialTrans16x16Test, Extremes) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int16_t maxval =
|
||||
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
|
||||
#else
|
||||
const int16_t maxval = 255;
|
||||
#endif
|
||||
const int minval = -maxval;
|
||||
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
|
||||
|
||||
for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval;
|
||||
output[0] = 0;
|
||||
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
|
||||
EXPECT_EQ((maxval * kNumCoeffs) >> 1, output[0]);
|
||||
|
||||
for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval;
|
||||
output[0] = 0;
|
||||
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
|
||||
EXPECT_EQ((minval * kNumCoeffs) >> 1, output[0]);
|
||||
}
|
||||
|
||||
TEST_P(PartialTrans16x16Test, Random) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int16_t maxval =
|
||||
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
|
||||
#else
|
||||
const int16_t maxval = 255;
|
||||
#endif
|
||||
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < kNumCoeffs; ++i) {
|
||||
const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1);
|
||||
input[i] = val;
|
||||
sum += val;
|
||||
}
|
||||
output[0] = 0;
|
||||
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
|
||||
EXPECT_EQ(sum >> 1, output[0]);
|
||||
}
|
||||
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
@ -755,10 +863,10 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 0, VPX_BITS_8)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(C, Trans16x16DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_c,
|
||||
&vpx_idct16x16_256_add_c,
|
||||
0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans16x16DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 0, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
@ -777,6 +885,11 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, PartialTrans16x16Test,
|
||||
::testing::Values(make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_8),
|
||||
make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans16x16HT,
|
||||
@ -785,44 +898,55 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(C, PartialTrans16x16Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_1_c,
|
||||
VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_NEON && !CONFIG_EMULATE_HARDWARE
|
||||
#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Trans16x16DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_neon,
|
||||
&vpx_idct16x16_256_add_neon, 0, VPX_BITS_8)));
|
||||
#endif // HAVE_NEON && !CONFIG_EMULATE_HARDWARE
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct16x16_c,
|
||||
&vpx_idct16x16_256_add_neon, 0, VPX_BITS_8)));
|
||||
#endif
|
||||
|
||||
#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans16x16DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_sse2,
|
||||
&vpx_idct16x16_256_add_sse2, 0, VPX_BITS_8)));
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct16x16_sse2,
|
||||
&vpx_idct16x16_256_add_sse2, 0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans16x16HT,
|
||||
::testing::Values(make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
|
||||
0, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
|
||||
1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
|
||||
2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
|
||||
3, VPX_BITS_8)));
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0,
|
||||
VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1,
|
||||
VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2,
|
||||
VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3,
|
||||
VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans16x16Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_1_sse2,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans16x16DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_highbd_fdct16x16_sse2, &idct16x16_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_256_add_10_sse2, 0,
|
||||
VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct16x16_sse2, &idct16x16_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_256_add_12_sse2, 0,
|
||||
VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct16x16_sse2, &vpx_idct16x16_256_add_c, 0,
|
||||
VPX_BITS_8)));
|
||||
make_tuple(&vpx_highbd_fdct16x16_sse2,
|
||||
&idct16x16_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct16x16_c,
|
||||
&idct16x16_256_add_10_sse2, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct16x16_sse2,
|
||||
&idct16x16_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct16x16_c,
|
||||
&idct16x16_256_add_12_sse2, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct16x16_sse2,
|
||||
&vpx_idct16x16_256_add_c, 0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans16x16HT,
|
||||
::testing::Values(
|
||||
@ -835,21 +959,26 @@ INSTANTIATE_TEST_CASE_P(
|
||||
// that to test both branches.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, InvTrans16x16DCT,
|
||||
::testing::Values(make_tuple(&idct16x16_10_add_10_c,
|
||||
&idct16x16_10_add_10_sse2, 3167, VPX_BITS_10),
|
||||
make_tuple(&idct16x16_10, &idct16x16_256_add_10_sse2,
|
||||
3167, VPX_BITS_10),
|
||||
make_tuple(&idct16x16_10_add_12_c,
|
||||
&idct16x16_10_add_12_sse2, 3167, VPX_BITS_12),
|
||||
make_tuple(&idct16x16_12, &idct16x16_256_add_12_sse2,
|
||||
3167, VPX_BITS_12)));
|
||||
::testing::Values(
|
||||
make_tuple(&idct16x16_10_add_10_c,
|
||||
&idct16x16_10_add_10_sse2, 3167, VPX_BITS_10),
|
||||
make_tuple(&idct16x16_10,
|
||||
&idct16x16_256_add_10_sse2, 3167, VPX_BITS_10),
|
||||
make_tuple(&idct16x16_10_add_12_c,
|
||||
&idct16x16_10_add_12_sse2, 3167, VPX_BITS_12),
|
||||
make_tuple(&idct16x16_12,
|
||||
&idct16x16_256_add_12_sse2, 3167, VPX_BITS_12)));
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans16x16Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_1_sse2,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(MSA, Trans16x16DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_msa,
|
||||
&vpx_idct16x16_256_add_msa,
|
||||
0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Trans16x16DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct16x16_msa,
|
||||
&vpx_idct16x16_256_add_msa, 0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Trans16x16HT,
|
||||
::testing::Values(
|
||||
@ -858,12 +987,8 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 3,
|
||||
VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(MSA, PartialTrans16x16Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_1_msa,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(VSX, Trans16x16DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct16x16_c,
|
||||
&vpx_idct16x16_256_add_vsx,
|
||||
0, VPX_BITS_8)));
|
||||
#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
} // namespace
|
||||
|
@ -25,11 +25,18 @@
|
||||
#include "vpx/vpx_codec.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_ports/mem.h"
|
||||
#include "vpx_ports/msvc.h" // for round()
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
namespace {
|
||||
#ifdef _MSC_VER
|
||||
static int round(double x) {
|
||||
if (x < 0)
|
||||
return static_cast<int>(ceil(x - 0.5));
|
||||
else
|
||||
return static_cast<int>(floor(x + 0.5));
|
||||
}
|
||||
#endif
|
||||
|
||||
const int kNumCoeffs = 1024;
|
||||
const double kPi = 3.141592653589793238462643383279502884;
|
||||
@ -37,10 +44,10 @@ void reference_32x32_dct_1d(const double in[32], double out[32]) {
|
||||
const double kInvSqrt2 = 0.707106781186547524400844362104;
|
||||
for (int k = 0; k < 32; k++) {
|
||||
out[k] = 0.0;
|
||||
for (int n = 0; n < 32; n++) {
|
||||
for (int n = 0; n < 32; n++)
|
||||
out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 64.0);
|
||||
}
|
||||
if (k == 0) out[k] = out[k] * kInvSqrt2;
|
||||
if (k == 0)
|
||||
out[k] = out[k] * kInvSqrt2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,33 +56,37 @@ void reference_32x32_dct_2d(const int16_t input[kNumCoeffs],
|
||||
// First transform columns
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
double temp_in[32], temp_out[32];
|
||||
for (int j = 0; j < 32; ++j) temp_in[j] = input[j * 32 + i];
|
||||
for (int j = 0; j < 32; ++j)
|
||||
temp_in[j] = input[j*32 + i];
|
||||
reference_32x32_dct_1d(temp_in, temp_out);
|
||||
for (int j = 0; j < 32; ++j) output[j * 32 + i] = temp_out[j];
|
||||
for (int j = 0; j < 32; ++j)
|
||||
output[j * 32 + i] = temp_out[j];
|
||||
}
|
||||
// Then transform rows
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
double temp_in[32], temp_out[32];
|
||||
for (int j = 0; j < 32; ++j) temp_in[j] = output[j + i * 32];
|
||||
for (int j = 0; j < 32; ++j)
|
||||
temp_in[j] = output[j + i*32];
|
||||
reference_32x32_dct_1d(temp_in, temp_out);
|
||||
// Scale by some magic number
|
||||
for (int j = 0; j < 32; ++j) output[j + i * 32] = temp_out[j] / 4;
|
||||
for (int j = 0; j < 32; ++j)
|
||||
output[j + i * 32] = temp_out[j] / 4;
|
||||
}
|
||||
}
|
||||
|
||||
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 ::testing::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t>
|
||||
typedef std::tr1::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t>
|
||||
Trans32x32Param;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
void idct32x32_10(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct32x32_1024_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
vpx_highbd_idct32x32_1024_add_c(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct32x32_12(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct32x32_1024_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
vpx_highbd_idct32x32_1024_add_c(in, out, stride, 12);
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
@ -85,8 +96,8 @@ class Trans32x32Test : public ::testing::TestWithParam<Trans32x32Param> {
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
version_ = GET_PARAM(2); // 0: high precision forward transform
|
||||
// 1: low precision version for rd loop
|
||||
version_ = GET_PARAM(2); // 0: high precision forward transform
|
||||
// 1: low precision version for rd loop
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
@ -136,20 +147,21 @@ TEST_P(Trans32x32Test, AccuracyCheck) {
|
||||
ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, dst, 32));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
inv_txfm_(test_temp_block, CAST_TO_BYTEPTR(dst16), 32));
|
||||
ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block,
|
||||
CONVERT_TO_BYTEPTR(dst16), 32));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int32_t diff =
|
||||
const uint32_t diff =
|
||||
bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
|
||||
#else
|
||||
const int32_t diff = dst[j] - src[j];
|
||||
const uint32_t diff = dst[j] - src[j];
|
||||
#endif
|
||||
const uint32_t error = diff * diff;
|
||||
if (max_error < error) max_error = error;
|
||||
if (max_error < error)
|
||||
max_error = error;
|
||||
total_error += error;
|
||||
}
|
||||
}
|
||||
@ -175,9 +187,8 @@ TEST_P(Trans32x32Test, CoeffCheck) {
|
||||
DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
|
||||
}
|
||||
|
||||
const int stride = 32;
|
||||
vpx_fdct32x32_c(input_block, output_ref_block, stride);
|
||||
@ -209,9 +220,11 @@ TEST_P(Trans32x32Test, MemCheck) {
|
||||
input_extreme_block[j] = rnd.Rand8() & 1 ? mask_ : -mask_;
|
||||
}
|
||||
if (i == 0) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = mask_;
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = mask_;
|
||||
} else if (i == 1) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = -mask_;
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = -mask_;
|
||||
}
|
||||
|
||||
const int stride = 32;
|
||||
@ -268,14 +281,13 @@ TEST_P(Trans32x32Test, InverseAccuracy) {
|
||||
}
|
||||
|
||||
reference_32x32_dct_2d(in, out_r);
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
|
||||
}
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, dst, 32));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, CAST_TO_BYTEPTR(dst16), 32));
|
||||
ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, CONVERT_TO_BYTEPTR(dst16), 32));
|
||||
#endif
|
||||
}
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
@ -286,50 +298,131 @@ TEST_P(Trans32x32Test, InverseAccuracy) {
|
||||
const int diff = dst[j] - src[j];
|
||||
#endif
|
||||
const int error = diff * diff;
|
||||
EXPECT_GE(1, error) << "Error: 32x32 IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
EXPECT_GE(1, error)
|
||||
<< "Error: 32x32 IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using ::testing::make_tuple;
|
||||
class PartialTrans32x32Test
|
||||
: public ::testing::TestWithParam<
|
||||
std::tr1::tuple<FwdTxfmFunc, vpx_bit_depth_t> > {
|
||||
public:
|
||||
virtual ~PartialTrans32x32Test() {}
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
bit_depth_ = GET_PARAM(1);
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
vpx_bit_depth_t bit_depth_;
|
||||
FwdTxfmFunc fwd_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(PartialTrans32x32Test, Extremes) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int16_t maxval =
|
||||
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
|
||||
#else
|
||||
const int16_t maxval = 255;
|
||||
#endif
|
||||
const int minval = -maxval;
|
||||
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
|
||||
|
||||
for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval;
|
||||
output[0] = 0;
|
||||
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
|
||||
EXPECT_EQ((maxval * kNumCoeffs) >> 3, output[0]);
|
||||
|
||||
for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval;
|
||||
output[0] = 0;
|
||||
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
|
||||
EXPECT_EQ((minval * kNumCoeffs) >> 3, output[0]);
|
||||
}
|
||||
|
||||
TEST_P(PartialTrans32x32Test, Random) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int16_t maxval =
|
||||
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
|
||||
#else
|
||||
const int16_t maxval = 255;
|
||||
#endif
|
||||
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < kNumCoeffs; ++i) {
|
||||
const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1);
|
||||
input[i] = val;
|
||||
sum += val;
|
||||
}
|
||||
output[0] = 0;
|
||||
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
|
||||
EXPECT_EQ(sum >> 3, output[0]);
|
||||
}
|
||||
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans32x32Test,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_highbd_fdct32x32_c, &idct32x32_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct32x32_rd_c, &idct32x32_10, 1, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct32x32_c, &idct32x32_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct32x32_rd_c, &idct32x32_12, 1, VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_c, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_c, &vpx_idct32x32_1024_add_c, 1,
|
||||
VPX_BITS_8)));
|
||||
make_tuple(&vpx_highbd_fdct32x32_c,
|
||||
&idct32x32_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct32x32_rd_c,
|
||||
&idct32x32_10, 1, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct32x32_c,
|
||||
&idct32x32_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct32x32_rd_c,
|
||||
&idct32x32_12, 1, VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct32x32_c,
|
||||
&vpx_idct32x32_1024_add_c, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_c,
|
||||
&vpx_idct32x32_1024_add_c, 1, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, PartialTrans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_8),
|
||||
make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_c, 0,
|
||||
VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_c, &vpx_idct32x32_1024_add_c,
|
||||
1, VPX_BITS_8)));
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct32x32_c,
|
||||
&vpx_idct32x32_1024_add_c, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_c,
|
||||
&vpx_idct32x32_1024_add_c, 1, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(C, PartialTrans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_c,
|
||||
VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_NEON && !CONFIG_EMULATE_HARDWARE
|
||||
#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Trans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_neon,
|
||||
&vpx_idct32x32_1024_add_neon, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_neon,
|
||||
&vpx_idct32x32_1024_add_neon, 1, VPX_BITS_8)));
|
||||
#endif // HAVE_NEON && !CONFIG_EMULATE_HARDWARE
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct32x32_c,
|
||||
&vpx_idct32x32_1024_add_neon, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_c,
|
||||
&vpx_idct32x32_1024_add_neon, 1, VPX_BITS_8)));
|
||||
#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_sse2,
|
||||
&vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_sse2,
|
||||
&vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct32x32_sse2,
|
||||
&vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_sse2,
|
||||
&vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
@ -346,32 +439,31 @@ INSTANTIATE_TEST_CASE_P(
|
||||
VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_sse2, &vpx_idct32x32_1024_add_c, 1,
|
||||
VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
AVX2, Trans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_avx2,
|
||||
&vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_avx2,
|
||||
&vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct32x32_avx2,
|
||||
&vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_avx2,
|
||||
&vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
|
||||
#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Trans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_msa,
|
||||
&vpx_idct32x32_1024_add_msa, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_msa,
|
||||
&vpx_idct32x32_1024_add_msa, 1, VPX_BITS_8)));
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct32x32_msa,
|
||||
&vpx_idct32x32_1024_add_msa, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_msa,
|
||||
&vpx_idct32x32_1024_add_msa, 1, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(MSA, PartialTrans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_msa,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
VSX, Trans32x32Test,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_vsx,
|
||||
0, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct32x32_rd_c,
|
||||
&vpx_idct32x32_1024_add_vsx, 1, VPX_BITS_8)));
|
||||
#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
} // namespace
|
||||
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "test/acm_random.h"
|
||||
#include "test/buffer.h"
|
||||
#include "test/clear_system_state.h"
|
||||
#include "test/register_state_check.h"
|
||||
#include "test/util.h"
|
||||
#include "vpx/vpx_codec.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_dsp/vpx_dsp_common.h"
|
||||
|
||||
using ::testing::make_tuple;
|
||||
using ::testing::tuple;
|
||||
using libvpx_test::ACMRandom;
|
||||
using libvpx_test::Buffer;
|
||||
|
||||
namespace {
|
||||
typedef void (*PartialFdctFunc)(const int16_t *in, tran_low_t *out, int stride);
|
||||
|
||||
typedef tuple<PartialFdctFunc, int /* size */, vpx_bit_depth_t>
|
||||
PartialFdctParam;
|
||||
|
||||
tran_low_t partial_fdct_ref(const Buffer<int16_t> &in, int size) {
|
||||
int64_t sum = 0;
|
||||
for (int y = 0; y < size; ++y) {
|
||||
for (int x = 0; x < size; ++x) {
|
||||
sum += in.TopLeftPixel()[y * in.stride() + x];
|
||||
}
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 4: sum *= 2; break;
|
||||
case 8: /*sum = sum;*/ break;
|
||||
case 16: sum >>= 1; break;
|
||||
case 32: sum >>= 3; break;
|
||||
}
|
||||
|
||||
return static_cast<tran_low_t>(sum);
|
||||
}
|
||||
|
||||
class PartialFdctTest : public ::testing::TestWithParam<PartialFdctParam> {
|
||||
public:
|
||||
PartialFdctTest() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
size_ = GET_PARAM(1);
|
||||
bit_depth_ = GET_PARAM(2);
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
void RunTest() {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int16_t maxvalue =
|
||||
clip_pixel_highbd(std::numeric_limits<int16_t>::max(), bit_depth_);
|
||||
const int16_t minvalue = -maxvalue;
|
||||
Buffer<int16_t> input_block =
|
||||
Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
|
||||
ASSERT_TRUE(input_block.Init());
|
||||
Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
|
||||
ASSERT_TRUE(output_block.Init());
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
if (i == 0) {
|
||||
input_block.Set(maxvalue);
|
||||
} else if (i == 1) {
|
||||
input_block.Set(minvalue);
|
||||
} else {
|
||||
input_block.Set(&rnd, minvalue, maxvalue);
|
||||
}
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input_block.TopLeftPixel(),
|
||||
output_block.TopLeftPixel(),
|
||||
input_block.stride()));
|
||||
|
||||
EXPECT_EQ(partial_fdct_ref(input_block, size_),
|
||||
output_block.TopLeftPixel()[0]);
|
||||
}
|
||||
}
|
||||
|
||||
PartialFdctFunc fwd_txfm_;
|
||||
vpx_bit_depth_t bit_depth_;
|
||||
int size_;
|
||||
};
|
||||
|
||||
TEST_P(PartialFdctTest, PartialFdctTest) { RunTest(); }
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, PartialFdctTest,
|
||||
::testing::Values(make_tuple(&vpx_highbd_fdct32x32_1_c, 32, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct32x32_1_c, 32, VPX_BITS_10),
|
||||
make_tuple(&vpx_fdct32x32_1_c, 32, VPX_BITS_8),
|
||||
make_tuple(&vpx_highbd_fdct16x16_1_c, 16, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct16x16_1_c, 16, VPX_BITS_10),
|
||||
make_tuple(&vpx_fdct16x16_1_c, 16, VPX_BITS_8),
|
||||
make_tuple(&vpx_highbd_fdct8x8_1_c, 8, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct8x8_1_c, 8, VPX_BITS_10),
|
||||
make_tuple(&vpx_fdct8x8_1_c, 8, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct4x4_1_c, 4, VPX_BITS_8)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, PartialFdctTest,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_c, 32, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct16x16_1_c, 16, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct8x8_1_c, 8, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct4x4_1_c, 4, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_SSE2
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, PartialFdctTest,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2, 32, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct16x16_1_sse2, 16, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct8x8_1_sse2, 8, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct4x4_1_sse2, 4, VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2
|
||||
|
||||
#if HAVE_NEON
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, PartialFdctTest,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_neon, 32, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct16x16_1_neon, 16, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_10),
|
||||
make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct4x4_1_neon, 4, VPX_BITS_8)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, PartialFdctTest,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_neon, 32, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct16x16_1_neon, 16, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct4x4_1_neon, 4, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if HAVE_MSA
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(MSA, PartialFdctTest,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_1_msa, 8,
|
||||
VPX_BITS_8)));
|
||||
#else // !CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, PartialFdctTest,
|
||||
::testing::Values(make_tuple(&vpx_fdct32x32_1_msa, 32, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct16x16_1_msa, 16, VPX_BITS_8),
|
||||
make_tuple(&vpx_fdct8x8_1_msa, 8, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_MSA
|
||||
} // namespace
|
728
test/dct_test.cc
728
test/dct_test.cc
@ -1,728 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vp9_rtcd.h"
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "test/acm_random.h"
|
||||
#include "test/buffer.h"
|
||||
#include "test/clear_system_state.h"
|
||||
#include "test/register_state_check.h"
|
||||
#include "test/util.h"
|
||||
#include "vp9/common/vp9_entropy.h"
|
||||
#include "vpx/vpx_codec.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_ports/mem.h"
|
||||
|
||||
using ::testing::make_tuple;
|
||||
using ::testing::tuple;
|
||||
using libvpx_test::ACMRandom;
|
||||
using libvpx_test::Buffer;
|
||||
|
||||
namespace {
|
||||
typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
|
||||
typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
|
||||
typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
|
||||
int tx_type);
|
||||
typedef void (*FhtFuncRef)(const Buffer<int16_t> &in, Buffer<tran_low_t> *out,
|
||||
int size, int tx_type);
|
||||
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
|
||||
int tx_type);
|
||||
typedef void (*IhtWithBdFunc)(const tran_low_t *in, uint8_t *out, int stride,
|
||||
int tx_type, int bd);
|
||||
|
||||
template <FdctFunc fn>
|
||||
void fdct_wrapper(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
|
||||
(void)tx_type;
|
||||
fn(in, out, stride);
|
||||
}
|
||||
|
||||
template <IdctFunc fn>
|
||||
void idct_wrapper(const tran_low_t *in, uint8_t *out, int stride, int tx_type,
|
||||
int bd) {
|
||||
(void)tx_type;
|
||||
(void)bd;
|
||||
fn(in, out, stride);
|
||||
}
|
||||
|
||||
template <IhtFunc fn>
|
||||
void iht_wrapper(const tran_low_t *in, uint8_t *out, int stride, int tx_type,
|
||||
int bd) {
|
||||
(void)bd;
|
||||
fn(in, out, stride, tx_type);
|
||||
}
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
typedef void (*HighbdIdctFunc)(const tran_low_t *in, uint16_t *out, int stride,
|
||||
int bd);
|
||||
|
||||
typedef void (*HighbdIhtFunc)(const tran_low_t *in, uint16_t *out, int stride,
|
||||
int tx_type, int bd);
|
||||
|
||||
template <HighbdIdctFunc fn>
|
||||
void highbd_idct_wrapper(const tran_low_t *in, uint8_t *out, int stride,
|
||||
int tx_type, int bd) {
|
||||
(void)tx_type;
|
||||
fn(in, CAST_TO_SHORTPTR(out), stride, bd);
|
||||
}
|
||||
|
||||
template <HighbdIhtFunc fn>
|
||||
void highbd_iht_wrapper(const tran_low_t *in, uint8_t *out, int stride,
|
||||
int tx_type, int bd) {
|
||||
fn(in, CAST_TO_SHORTPTR(out), stride, tx_type, bd);
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
struct FuncInfo {
|
||||
FhtFunc ft_func;
|
||||
IhtWithBdFunc it_func;
|
||||
int size;
|
||||
int pixel_size;
|
||||
};
|
||||
|
||||
/* forward transform, inverse transform, size, transform type, bit depth */
|
||||
typedef tuple<int, const FuncInfo *, int, vpx_bit_depth_t> DctParam;
|
||||
|
||||
void fdct_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
|
||||
int /*tx_type*/) {
|
||||
const int16_t *i = in.TopLeftPixel();
|
||||
const int i_stride = in.stride();
|
||||
tran_low_t *o = out->TopLeftPixel();
|
||||
if (size == 4) {
|
||||
vpx_fdct4x4_c(i, o, i_stride);
|
||||
} else if (size == 8) {
|
||||
vpx_fdct8x8_c(i, o, i_stride);
|
||||
} else if (size == 16) {
|
||||
vpx_fdct16x16_c(i, o, i_stride);
|
||||
} else if (size == 32) {
|
||||
vpx_fdct32x32_c(i, o, i_stride);
|
||||
}
|
||||
}
|
||||
|
||||
void fht_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
|
||||
int tx_type) {
|
||||
const int16_t *i = in.TopLeftPixel();
|
||||
const int i_stride = in.stride();
|
||||
tran_low_t *o = out->TopLeftPixel();
|
||||
if (size == 4) {
|
||||
vp9_fht4x4_c(i, o, i_stride, tx_type);
|
||||
} else if (size == 8) {
|
||||
vp9_fht8x8_c(i, o, i_stride, tx_type);
|
||||
} else if (size == 16) {
|
||||
vp9_fht16x16_c(i, o, i_stride, tx_type);
|
||||
}
|
||||
}
|
||||
|
||||
void fwht_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
|
||||
int /*tx_type*/) {
|
||||
ASSERT_EQ(size, 4);
|
||||
vp9_fwht4x4_c(in.TopLeftPixel(), out->TopLeftPixel(), in.stride());
|
||||
}
|
||||
|
||||
class TransTestBase : public ::testing::TestWithParam<DctParam> {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
const int idx = GET_PARAM(0);
|
||||
const FuncInfo *func_info = &(GET_PARAM(1)[idx]);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
fwd_txfm_ = func_info->ft_func;
|
||||
inv_txfm_ = func_info->it_func;
|
||||
size_ = func_info->size;
|
||||
pixel_size_ = func_info->pixel_size;
|
||||
max_pixel_value_ = (1 << bit_depth_) - 1;
|
||||
|
||||
// Randomize stride_ to a value less than or equal to 1024
|
||||
stride_ = rnd_(1024) + 1;
|
||||
if (stride_ < size_) {
|
||||
stride_ = size_;
|
||||
}
|
||||
// Align stride_ to 16 if it's bigger than 16.
|
||||
if (stride_ > 16) {
|
||||
stride_ &= ~15;
|
||||
}
|
||||
|
||||
block_size_ = size_ * stride_;
|
||||
|
||||
src_ = reinterpret_cast<uint8_t *>(
|
||||
vpx_memalign(16, pixel_size_ * block_size_));
|
||||
ASSERT_TRUE(src_ != NULL);
|
||||
dst_ = reinterpret_cast<uint8_t *>(
|
||||
vpx_memalign(16, pixel_size_ * block_size_));
|
||||
ASSERT_TRUE(dst_ != NULL);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
vpx_free(src_);
|
||||
src_ = NULL;
|
||||
vpx_free(dst_);
|
||||
dst_ = NULL;
|
||||
libvpx_test::ClearSystemState();
|
||||
}
|
||||
|
||||
void InitMem() {
|
||||
if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
|
||||
if (pixel_size_ == 1) {
|
||||
for (int j = 0; j < block_size_; ++j) {
|
||||
src_[j] = rnd_.Rand16() & max_pixel_value_;
|
||||
}
|
||||
for (int j = 0; j < block_size_; ++j) {
|
||||
dst_[j] = rnd_.Rand16() & max_pixel_value_;
|
||||
}
|
||||
} else {
|
||||
ASSERT_EQ(pixel_size_, 2);
|
||||
uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
|
||||
uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
|
||||
for (int j = 0; j < block_size_; ++j) {
|
||||
src[j] = rnd_.Rand16() & max_pixel_value_;
|
||||
}
|
||||
for (int j = 0; j < block_size_; ++j) {
|
||||
dst[j] = rnd_.Rand16() & max_pixel_value_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunFwdTxfm(const Buffer<int16_t> &in, Buffer<tran_low_t> *out) {
|
||||
fwd_txfm_(in.TopLeftPixel(), out->TopLeftPixel(), in.stride(), tx_type_);
|
||||
}
|
||||
|
||||
void RunInvTxfm(const Buffer<tran_low_t> &in, uint8_t *out) {
|
||||
inv_txfm_(in.TopLeftPixel(), out, stride_, tx_type_, bit_depth_);
|
||||
}
|
||||
|
||||
protected:
|
||||
void RunAccuracyCheck(int limit) {
|
||||
if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
Buffer<int16_t> test_input_block =
|
||||
Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
|
||||
ASSERT_TRUE(test_input_block.Init());
|
||||
Buffer<tran_low_t> test_temp_block =
|
||||
Buffer<tran_low_t>(size_, size_, 0, 16);
|
||||
ASSERT_TRUE(test_temp_block.Init());
|
||||
uint32_t max_error = 0;
|
||||
int64_t total_error = 0;
|
||||
const int count_test_block = 10000;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
InitMem();
|
||||
for (int h = 0; h < size_; ++h) {
|
||||
for (int w = 0; w < size_; ++w) {
|
||||
if (pixel_size_ == 1) {
|
||||
test_input_block.TopLeftPixel()[h * test_input_block.stride() + w] =
|
||||
src_[h * stride_ + w] - dst_[h * stride_ + w];
|
||||
} else {
|
||||
ASSERT_EQ(pixel_size_, 2);
|
||||
const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
|
||||
const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
|
||||
test_input_block.TopLeftPixel()[h * test_input_block.stride() + w] =
|
||||
src[h * stride_ + w] - dst[h * stride_ + w];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, &test_temp_block));
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst_));
|
||||
|
||||
for (int h = 0; h < size_; ++h) {
|
||||
for (int w = 0; w < size_; ++w) {
|
||||
int diff;
|
||||
if (pixel_size_ == 1) {
|
||||
diff = dst_[h * stride_ + w] - src_[h * stride_ + w];
|
||||
} else {
|
||||
ASSERT_EQ(pixel_size_, 2);
|
||||
const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
|
||||
const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
|
||||
diff = dst[h * stride_ + w] - src[h * stride_ + w];
|
||||
}
|
||||
const uint32_t error = diff * diff;
|
||||
if (max_error < error) max_error = error;
|
||||
total_error += error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_GE(static_cast<uint32_t>(limit), max_error)
|
||||
<< "Error: " << size_ << "x" << size_
|
||||
<< " transform/inverse transform has an individual round trip error > "
|
||||
<< limit;
|
||||
|
||||
EXPECT_GE(count_test_block * limit, total_error)
|
||||
<< "Error: " << size_ << "x" << size_
|
||||
<< " transform/inverse transform has average round trip error > "
|
||||
<< limit << " per block";
|
||||
}
|
||||
|
||||
void RunCoeffCheck() {
|
||||
if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = 5000;
|
||||
Buffer<int16_t> input_block =
|
||||
Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
|
||||
ASSERT_TRUE(input_block.Init());
|
||||
Buffer<tran_low_t> output_ref_block = Buffer<tran_low_t>(size_, size_, 0);
|
||||
ASSERT_TRUE(output_ref_block.Init());
|
||||
Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
|
||||
ASSERT_TRUE(output_block.Init());
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with input range [-max_pixel_value_,
|
||||
// max_pixel_value_].
|
||||
input_block.Set(&rnd, -max_pixel_value_, max_pixel_value_);
|
||||
|
||||
fwd_txfm_ref(input_block, &output_ref_block, size_, tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, &output_block));
|
||||
|
||||
// The minimum quant value is 4.
|
||||
EXPECT_TRUE(output_block.CheckValues(output_ref_block));
|
||||
if (::testing::Test::HasFailure()) {
|
||||
printf("Size: %d Transform type: %d\n", size_, tx_type_);
|
||||
output_block.PrintDifference(output_ref_block);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunMemCheck() {
|
||||
if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = 5000;
|
||||
Buffer<int16_t> input_extreme_block =
|
||||
Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
|
||||
ASSERT_TRUE(input_extreme_block.Init());
|
||||
Buffer<tran_low_t> output_ref_block = Buffer<tran_low_t>(size_, size_, 0);
|
||||
ASSERT_TRUE(output_ref_block.Init());
|
||||
Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
|
||||
ASSERT_TRUE(output_block.Init());
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with -max_pixel_value_ or max_pixel_value_.
|
||||
if (i == 0) {
|
||||
input_extreme_block.Set(max_pixel_value_);
|
||||
} else if (i == 1) {
|
||||
input_extreme_block.Set(-max_pixel_value_);
|
||||
} else {
|
||||
for (int h = 0; h < size_; ++h) {
|
||||
for (int w = 0; w < size_; ++w) {
|
||||
input_extreme_block
|
||||
.TopLeftPixel()[h * input_extreme_block.stride() + w] =
|
||||
rnd.Rand8() % 2 ? max_pixel_value_ : -max_pixel_value_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fwd_txfm_ref(input_extreme_block, &output_ref_block, size_, tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, &output_block));
|
||||
|
||||
// The minimum quant value is 4.
|
||||
EXPECT_TRUE(output_block.CheckValues(output_ref_block));
|
||||
for (int h = 0; h < size_; ++h) {
|
||||
for (int w = 0; w < size_; ++w) {
|
||||
EXPECT_GE(
|
||||
4 * DCT_MAX_VALUE << (bit_depth_ - 8),
|
||||
abs(output_block.TopLeftPixel()[h * output_block.stride() + w]))
|
||||
<< "Error: " << size_ << "x" << size_
|
||||
<< " transform has coefficient larger than 4*DCT_MAX_VALUE"
|
||||
<< " at " << w << "," << h;
|
||||
if (::testing::Test::HasFailure()) {
|
||||
printf("Size: %d Transform type: %d\n", size_, tx_type_);
|
||||
output_block.DumpBuffer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunInvAccuracyCheck(int limit) {
|
||||
if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = 1000;
|
||||
Buffer<int16_t> in = Buffer<int16_t>(size_, size_, 4);
|
||||
ASSERT_TRUE(in.Init());
|
||||
Buffer<tran_low_t> coeff = Buffer<tran_low_t>(size_, size_, 0, 16);
|
||||
ASSERT_TRUE(coeff.Init());
|
||||
Buffer<uint8_t> dst = Buffer<uint8_t>(size_, size_, 0, 16);
|
||||
ASSERT_TRUE(dst.Init());
|
||||
Buffer<uint8_t> src = Buffer<uint8_t>(size_, size_, 0);
|
||||
ASSERT_TRUE(src.Init());
|
||||
Buffer<uint16_t> dst16 = Buffer<uint16_t>(size_, size_, 0, 16);
|
||||
ASSERT_TRUE(dst16.Init());
|
||||
Buffer<uint16_t> src16 = Buffer<uint16_t>(size_, size_, 0);
|
||||
ASSERT_TRUE(src16.Init());
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
InitMem();
|
||||
// Initialize a test block with input range [-max_pixel_value_,
|
||||
// max_pixel_value_].
|
||||
for (int h = 0; h < size_; ++h) {
|
||||
for (int w = 0; w < size_; ++w) {
|
||||
if (pixel_size_ == 1) {
|
||||
in.TopLeftPixel()[h * in.stride() + w] =
|
||||
src_[h * stride_ + w] - dst_[h * stride_ + w];
|
||||
} else {
|
||||
ASSERT_EQ(pixel_size_, 2);
|
||||
const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
|
||||
const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
|
||||
in.TopLeftPixel()[h * in.stride() + w] =
|
||||
src[h * stride_ + w] - dst[h * stride_ + w];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fwd_txfm_ref(in, &coeff, size_, tx_type_);
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst_));
|
||||
|
||||
for (int h = 0; h < size_; ++h) {
|
||||
for (int w = 0; w < size_; ++w) {
|
||||
int diff;
|
||||
if (pixel_size_ == 1) {
|
||||
diff = dst_[h * stride_ + w] - src_[h * stride_ + w];
|
||||
} else {
|
||||
ASSERT_EQ(pixel_size_, 2);
|
||||
const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
|
||||
const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
|
||||
diff = dst[h * stride_ + w] - src[h * stride_ + w];
|
||||
}
|
||||
const uint32_t error = diff * diff;
|
||||
EXPECT_GE(static_cast<uint32_t>(limit), error)
|
||||
<< "Error: " << size_ << "x" << size_
|
||||
<< " inverse transform has error " << error << " at " << w << ","
|
||||
<< h;
|
||||
if (::testing::Test::HasFailure()) {
|
||||
printf("Size: %d Transform type: %d\n", size_, tx_type_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FhtFunc fwd_txfm_;
|
||||
FhtFuncRef fwd_txfm_ref;
|
||||
IhtWithBdFunc inv_txfm_;
|
||||
ACMRandom rnd_;
|
||||
uint8_t *src_;
|
||||
uint8_t *dst_;
|
||||
vpx_bit_depth_t bit_depth_;
|
||||
int tx_type_;
|
||||
int max_pixel_value_;
|
||||
int size_;
|
||||
int stride_;
|
||||
int pixel_size_;
|
||||
int block_size_;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class TransDCT : public TransTestBase {
|
||||
public:
|
||||
TransDCT() { fwd_txfm_ref = fdct_ref; }
|
||||
};
|
||||
|
||||
TEST_P(TransDCT, AccuracyCheck) {
|
||||
int t = 1;
|
||||
if (size_ == 16 && bit_depth_ > 10 && pixel_size_ == 2) {
|
||||
t = 2;
|
||||
} else if (size_ == 32 && bit_depth_ > 10 && pixel_size_ == 2) {
|
||||
t = 7;
|
||||
}
|
||||
RunAccuracyCheck(t);
|
||||
}
|
||||
|
||||
TEST_P(TransDCT, CoeffCheck) { RunCoeffCheck(); }
|
||||
|
||||
TEST_P(TransDCT, MemCheck) { RunMemCheck(); }
|
||||
|
||||
TEST_P(TransDCT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
|
||||
|
||||
static const FuncInfo dct_c_func_info[] = {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
{ &fdct_wrapper<vpx_highbd_fdct4x4_c>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct4x4_16_add_c>, 4, 2 },
|
||||
{ &fdct_wrapper<vpx_highbd_fdct8x8_c>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct8x8_64_add_c>, 8, 2 },
|
||||
{ &fdct_wrapper<vpx_highbd_fdct16x16_c>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct16x16_256_add_c>, 16, 2 },
|
||||
{ &fdct_wrapper<vpx_highbd_fdct32x32_c>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct32x32_1024_add_c>, 32, 2 },
|
||||
#endif
|
||||
{ &fdct_wrapper<vpx_fdct4x4_c>, &idct_wrapper<vpx_idct4x4_16_add_c>, 4, 1 },
|
||||
{ &fdct_wrapper<vpx_fdct8x8_c>, &idct_wrapper<vpx_idct8x8_64_add_c>, 8, 1 },
|
||||
{ &fdct_wrapper<vpx_fdct16x16_c>, &idct_wrapper<vpx_idct16x16_256_add_c>, 16,
|
||||
1 },
|
||||
{ &fdct_wrapper<vpx_fdct32x32_c>, &idct_wrapper<vpx_idct32x32_1024_add_c>, 32,
|
||||
1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, TransDCT,
|
||||
::testing::Combine(
|
||||
::testing::Range(0, static_cast<int>(sizeof(dct_c_func_info) /
|
||||
sizeof(dct_c_func_info[0]))),
|
||||
::testing::Values(dct_c_func_info), ::testing::Values(0),
|
||||
::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
|
||||
|
||||
#if !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_SSE2
|
||||
static const FuncInfo dct_sse2_func_info[] = {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
{ &fdct_wrapper<vpx_highbd_fdct4x4_sse2>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct4x4_16_add_sse2>, 4, 2 },
|
||||
{ &fdct_wrapper<vpx_highbd_fdct8x8_sse2>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct8x8_64_add_sse2>, 8, 2 },
|
||||
{ &fdct_wrapper<vpx_highbd_fdct16x16_sse2>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct16x16_256_add_sse2>, 16, 2 },
|
||||
{ &fdct_wrapper<vpx_highbd_fdct32x32_sse2>,
|
||||
&highbd_idct_wrapper<vpx_highbd_idct32x32_1024_add_sse2>, 32, 2 },
|
||||
#endif
|
||||
{ &fdct_wrapper<vpx_fdct4x4_sse2>, &idct_wrapper<vpx_idct4x4_16_add_sse2>, 4,
|
||||
1 },
|
||||
{ &fdct_wrapper<vpx_fdct8x8_sse2>, &idct_wrapper<vpx_idct8x8_64_add_sse2>, 8,
|
||||
1 },
|
||||
{ &fdct_wrapper<vpx_fdct16x16_sse2>,
|
||||
&idct_wrapper<vpx_idct16x16_256_add_sse2>, 16, 1 },
|
||||
{ &fdct_wrapper<vpx_fdct32x32_sse2>,
|
||||
&idct_wrapper<vpx_idct32x32_1024_add_sse2>, 32, 1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, TransDCT,
|
||||
::testing::Combine(
|
||||
::testing::Range(0, static_cast<int>(sizeof(dct_sse2_func_info) /
|
||||
sizeof(dct_sse2_func_info[0]))),
|
||||
::testing::Values(dct_sse2_func_info), ::testing::Values(0),
|
||||
::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
|
||||
#endif // HAVE_SSE2
|
||||
|
||||
#if HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH && ARCH_X86_64
|
||||
// vpx_fdct8x8_ssse3 is only available in 64 bit builds.
|
||||
static const FuncInfo dct_ssse3_func_info = {
|
||||
&fdct_wrapper<vpx_fdct8x8_ssse3>, &idct_wrapper<vpx_idct8x8_64_add_sse2>, 8, 1
|
||||
};
|
||||
|
||||
// TODO(johannkoenig): high bit depth fdct8x8.
|
||||
INSTANTIATE_TEST_CASE_P(SSSE3, TransDCT,
|
||||
::testing::Values(make_tuple(0, &dct_ssse3_func_info, 0,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH && ARCH_X86_64
|
||||
|
||||
#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH
|
||||
static const FuncInfo dct_avx2_func_info = {
|
||||
&fdct_wrapper<vpx_fdct32x32_avx2>, &idct_wrapper<vpx_idct32x32_1024_add_sse2>,
|
||||
32, 1
|
||||
};
|
||||
|
||||
// TODO(johannkoenig): high bit depth fdct32x32.
|
||||
INSTANTIATE_TEST_CASE_P(AVX2, TransDCT,
|
||||
::testing::Values(make_tuple(0, &dct_avx2_func_info, 0,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_NEON
|
||||
static const FuncInfo dct_neon_func_info[4] = {
|
||||
{ &fdct_wrapper<vpx_fdct4x4_neon>, &idct_wrapper<vpx_idct4x4_16_add_neon>, 4,
|
||||
1 },
|
||||
{ &fdct_wrapper<vpx_fdct8x8_neon>, &idct_wrapper<vpx_idct8x8_64_add_neon>, 8,
|
||||
1 },
|
||||
{ &fdct_wrapper<vpx_fdct16x16_neon>,
|
||||
&idct_wrapper<vpx_idct16x16_256_add_neon>, 16, 1 },
|
||||
{ &fdct_wrapper<vpx_fdct32x32_neon>,
|
||||
&idct_wrapper<vpx_idct32x32_1024_add_neon>, 32, 1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, TransDCT,
|
||||
::testing::Combine(::testing::Range(0, 4),
|
||||
::testing::Values(dct_neon_func_info),
|
||||
::testing::Values(0), ::testing::Values(VPX_BITS_8)));
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH
|
||||
static const FuncInfo dct_msa_func_info[4] = {
|
||||
{ &fdct_wrapper<vpx_fdct4x4_msa>, &idct_wrapper<vpx_idct4x4_16_add_msa>, 4,
|
||||
1 },
|
||||
{ &fdct_wrapper<vpx_fdct8x8_msa>, &idct_wrapper<vpx_idct8x8_64_add_msa>, 8,
|
||||
1 },
|
||||
{ &fdct_wrapper<vpx_fdct16x16_msa>, &idct_wrapper<vpx_idct16x16_256_add_msa>,
|
||||
16, 1 },
|
||||
{ &fdct_wrapper<vpx_fdct32x32_msa>, &idct_wrapper<vpx_idct32x32_1024_add_msa>,
|
||||
32, 1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MSA, TransDCT,
|
||||
::testing::Combine(::testing::Range(0, 4),
|
||||
::testing::Values(dct_msa_func_info),
|
||||
::testing::Values(0),
|
||||
::testing::Values(VPX_BITS_8)));
|
||||
#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH
|
||||
static const FuncInfo dct_vsx_func_info = {
|
||||
&fdct_wrapper<vpx_fdct4x4_c>, &idct_wrapper<vpx_idct4x4_16_add_vsx>, 4, 1
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(VSX, TransDCT,
|
||||
::testing::Values(make_tuple(0, &dct_vsx_func_info, 0,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH &&
|
||||
|
||||
#endif // !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class TransHT : public TransTestBase {
|
||||
public:
|
||||
TransHT() { fwd_txfm_ref = fht_ref; }
|
||||
};
|
||||
|
||||
TEST_P(TransHT, AccuracyCheck) {
|
||||
RunAccuracyCheck(size_ == 16 && bit_depth_ > 10 && pixel_size_ == 2 ? 2 : 1);
|
||||
}
|
||||
|
||||
TEST_P(TransHT, CoeffCheck) { RunCoeffCheck(); }
|
||||
|
||||
TEST_P(TransHT, MemCheck) { RunMemCheck(); }
|
||||
|
||||
TEST_P(TransHT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
|
||||
|
||||
static const FuncInfo ht_c_func_info[] = {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
{ &vp9_highbd_fht4x4_c, &highbd_iht_wrapper<vp9_highbd_iht4x4_16_add_c>, 4,
|
||||
2 },
|
||||
{ &vp9_highbd_fht8x8_c, &highbd_iht_wrapper<vp9_highbd_iht8x8_64_add_c>, 8,
|
||||
2 },
|
||||
{ &vp9_highbd_fht16x16_c, &highbd_iht_wrapper<vp9_highbd_iht16x16_256_add_c>,
|
||||
16, 2 },
|
||||
#endif
|
||||
{ &vp9_fht4x4_c, &iht_wrapper<vp9_iht4x4_16_add_c>, 4, 1 },
|
||||
{ &vp9_fht8x8_c, &iht_wrapper<vp9_iht8x8_64_add_c>, 8, 1 },
|
||||
{ &vp9_fht16x16_c, &iht_wrapper<vp9_iht16x16_256_add_c>, 16, 1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, TransHT,
|
||||
::testing::Combine(
|
||||
::testing::Range(0, static_cast<int>(sizeof(ht_c_func_info) /
|
||||
sizeof(ht_c_func_info[0]))),
|
||||
::testing::Values(ht_c_func_info), ::testing::Range(0, 4),
|
||||
::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
|
||||
|
||||
#if !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_NEON
|
||||
|
||||
static const FuncInfo ht_neon_func_info[] = {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
{ &vp9_highbd_fht4x4_c, &highbd_iht_wrapper<vp9_highbd_iht4x4_16_add_neon>, 4,
|
||||
2 },
|
||||
{ &vp9_highbd_fht8x8_c, &highbd_iht_wrapper<vp9_highbd_iht8x8_64_add_neon>, 8,
|
||||
2 },
|
||||
{ &vp9_highbd_fht16x16_c,
|
||||
&highbd_iht_wrapper<vp9_highbd_iht16x16_256_add_neon>, 16, 2 },
|
||||
#endif
|
||||
{ &vp9_fht4x4_c, &iht_wrapper<vp9_iht4x4_16_add_neon>, 4, 1 },
|
||||
{ &vp9_fht8x8_c, &iht_wrapper<vp9_iht8x8_64_add_neon>, 8, 1 },
|
||||
{ &vp9_fht16x16_c, &iht_wrapper<vp9_iht16x16_256_add_neon>, 16, 1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, TransHT,
|
||||
::testing::Combine(
|
||||
::testing::Range(0, static_cast<int>(sizeof(ht_neon_func_info) /
|
||||
sizeof(ht_neon_func_info[0]))),
|
||||
::testing::Values(ht_neon_func_info), ::testing::Range(0, 4),
|
||||
::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if HAVE_SSE2
|
||||
|
||||
static const FuncInfo ht_sse2_func_info[3] = {
|
||||
{ &vp9_fht4x4_sse2, &iht_wrapper<vp9_iht4x4_16_add_sse2>, 4, 1 },
|
||||
{ &vp9_fht8x8_sse2, &iht_wrapper<vp9_iht8x8_64_add_sse2>, 8, 1 },
|
||||
{ &vp9_fht16x16_sse2, &iht_wrapper<vp9_iht16x16_256_add_sse2>, 16, 1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, TransHT,
|
||||
::testing::Combine(::testing::Range(0, 3),
|
||||
::testing::Values(ht_sse2_func_info),
|
||||
::testing::Range(0, 4),
|
||||
::testing::Values(VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2
|
||||
|
||||
#if HAVE_SSE4_1 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static const FuncInfo ht_sse4_1_func_info[3] = {
|
||||
{ &vp9_highbd_fht4x4_c, &highbd_iht_wrapper<vp9_highbd_iht4x4_16_add_sse4_1>,
|
||||
4, 2 },
|
||||
{ vp9_highbd_fht8x8_c, &highbd_iht_wrapper<vp9_highbd_iht8x8_64_add_sse4_1>,
|
||||
8, 2 },
|
||||
{ &vp9_highbd_fht16x16_c,
|
||||
&highbd_iht_wrapper<vp9_highbd_iht16x16_256_add_sse4_1>, 16, 2 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE4_1, TransHT,
|
||||
::testing::Combine(::testing::Range(0, 3),
|
||||
::testing::Values(ht_sse4_1_func_info),
|
||||
::testing::Range(0, 4),
|
||||
::testing::Values(VPX_BITS_8, VPX_BITS_10,
|
||||
VPX_BITS_12)));
|
||||
#endif // HAVE_SSE4_1 && CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#endif // !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class TransWHT : public TransTestBase {
|
||||
public:
|
||||
TransWHT() { fwd_txfm_ref = fwht_ref; }
|
||||
};
|
||||
|
||||
TEST_P(TransWHT, AccuracyCheck) { RunAccuracyCheck(0); }
|
||||
|
||||
TEST_P(TransWHT, CoeffCheck) { RunCoeffCheck(); }
|
||||
|
||||
TEST_P(TransWHT, MemCheck) { RunMemCheck(); }
|
||||
|
||||
TEST_P(TransWHT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
|
||||
|
||||
static const FuncInfo wht_c_func_info[] = {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
{ &fdct_wrapper<vp9_highbd_fwht4x4_c>,
|
||||
&highbd_idct_wrapper<vpx_highbd_iwht4x4_16_add_c>, 4, 2 },
|
||||
#endif
|
||||
{ &fdct_wrapper<vp9_fwht4x4_c>, &idct_wrapper<vpx_iwht4x4_16_add_c>, 4, 1 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, TransWHT,
|
||||
::testing::Combine(
|
||||
::testing::Range(0, static_cast<int>(sizeof(wht_c_func_info) /
|
||||
sizeof(wht_c_func_info[0]))),
|
||||
::testing::Values(wht_c_func_info), ::testing::Values(0),
|
||||
::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
|
||||
|
||||
#if HAVE_SSE2 && !CONFIG_EMULATE_HARDWARE
|
||||
static const FuncInfo wht_sse2_func_info = {
|
||||
&fdct_wrapper<vp9_fwht4x4_sse2>, &idct_wrapper<vpx_iwht4x4_16_add_sse2>, 4, 1
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, TransWHT,
|
||||
::testing::Values(make_tuple(0, &wht_sse2_func_info, 0,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2 && !CONFIG_EMULATE_HARDWARE
|
||||
} // namespace
|
@ -26,9 +26,12 @@ TEST(DecodeAPI, InvalidParams) {
|
||||
#endif
|
||||
#if CONFIG_VP9_DECODER
|
||||
&vpx_codec_vp9_dx_algo,
|
||||
#endif
|
||||
#if CONFIG_VP10_DECODER
|
||||
&vpx_codec_vp10_dx_algo,
|
||||
#endif
|
||||
};
|
||||
uint8_t buf[1] = { 0 };
|
||||
uint8_t buf[1] = {0};
|
||||
vpx_codec_ctx_t dec;
|
||||
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(NULL, NULL, NULL, 0));
|
||||
@ -51,7 +54,8 @@ TEST(DecodeAPI, InvalidParams) {
|
||||
vpx_codec_decode(&dec, buf, NELEMENTS(buf), NULL, 0));
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
|
||||
vpx_codec_decode(&dec, NULL, NELEMENTS(buf), NULL, 0));
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(&dec, buf, 0, NULL, 0));
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
|
||||
vpx_codec_decode(&dec, buf, 0, NULL, 0));
|
||||
|
||||
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
|
||||
}
|
||||
@ -76,9 +80,12 @@ TEST(DecodeAPI, OptionalParams) {
|
||||
// Test VP9 codec controls after a decode error to ensure the code doesn't
|
||||
// misbehave.
|
||||
void TestVp9Controls(vpx_codec_ctx_t *dec) {
|
||||
static const int kControls[] = { VP8D_GET_LAST_REF_UPDATES,
|
||||
VP8D_GET_FRAME_CORRUPTED,
|
||||
VP9D_GET_DISPLAY_SIZE, VP9D_GET_FRAME_SIZE };
|
||||
static const int kControls[] = {
|
||||
VP8D_GET_LAST_REF_UPDATES,
|
||||
VP8D_GET_FRAME_CORRUPTED,
|
||||
VP9D_GET_DISPLAY_SIZE,
|
||||
VP9D_GET_FRAME_SIZE
|
||||
};
|
||||
int val[2];
|
||||
|
||||
for (int i = 0; i < NELEMENTS(kControls); ++i) {
|
||||
@ -87,7 +94,9 @@ void TestVp9Controls(vpx_codec_ctx_t *dec) {
|
||||
case VP8D_GET_FRAME_CORRUPTED:
|
||||
EXPECT_EQ(VPX_CODEC_ERROR, res) << kControls[i];
|
||||
break;
|
||||
default: EXPECT_EQ(VPX_CODEC_OK, res) << kControls[i]; break;
|
||||
default:
|
||||
EXPECT_EQ(VPX_CODEC_OK, res) << kControls[i];
|
||||
break;
|
||||
}
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
|
||||
vpx_codec_control_(dec, kControls[i], NULL));
|
||||
@ -144,9 +153,10 @@ TEST(DecodeAPI, Vp9PeekSI) {
|
||||
// size 10, this should return VPX_CODEC_UNSUP_BITSTREAM and after that it
|
||||
// should return VPX_CODEC_CORRUPT_FRAME.
|
||||
const uint8_t data[32] = {
|
||||
0x85, 0xa4, 0xc1, 0xa1, 0x38, 0x81, 0xa3, 0x49, 0x83, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x85, 0xa4, 0xc1, 0xa1, 0x38, 0x81, 0xa3, 0x49,
|
||||
0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
for (uint32_t data_sz = 1; data_sz <= 32; ++data_sz) {
|
||||
@ -155,9 +165,9 @@ TEST(DecodeAPI, Vp9PeekSI) {
|
||||
if (data_sz >= 8) {
|
||||
vpx_codec_ctx_t dec;
|
||||
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0));
|
||||
EXPECT_EQ(
|
||||
(data_sz < 10) ? VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_CORRUPT_FRAME,
|
||||
vpx_codec_decode(&dec, data, data_sz, NULL, 0));
|
||||
EXPECT_EQ((data_sz < 10) ?
|
||||
VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_CORRUPT_FRAME,
|
||||
vpx_codec_decode(&dec, data, data_sz, NULL, 0));
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter));
|
||||
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
|
||||
@ -172,21 +182,4 @@ TEST(DecodeAPI, Vp9PeekSI) {
|
||||
}
|
||||
#endif // CONFIG_VP9_DECODER
|
||||
|
||||
TEST(DecodeAPI, HighBitDepthCapability) {
|
||||
// VP8 should not claim VP9 HBD as a capability.
|
||||
#if CONFIG_VP8_DECODER
|
||||
const vpx_codec_caps_t vp8_caps = vpx_codec_get_caps(&vpx_codec_vp8_dx_algo);
|
||||
EXPECT_EQ(vp8_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
|
||||
#endif
|
||||
|
||||
#if CONFIG_VP9_DECODER
|
||||
const vpx_codec_caps_t vp9_caps = vpx_codec_get_caps(&vpx_codec_vp9_dx_algo);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, VPX_CODEC_CAP_HIGHBITDEPTH);
|
||||
#else
|
||||
EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -21,20 +21,21 @@
|
||||
#include "./ivfenc.h"
|
||||
#include "./vpx_version.h"
|
||||
|
||||
using ::testing::make_tuple;
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
namespace {
|
||||
|
||||
#define VIDEO_NAME 0
|
||||
#define THREADS 1
|
||||
|
||||
const int kMaxPsnr = 100;
|
||||
const double kUsecsInSec = 1000000.0;
|
||||
const char kNewEncodeOutputFile[] = "new_encode.ivf";
|
||||
|
||||
/*
|
||||
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[] = {
|
||||
make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1),
|
||||
@ -69,7 +70,8 @@ const DecodePerfParam kVP9DecodePerfVectors[] = {
|
||||
power/temp/min max frame decode times/etc
|
||||
*/
|
||||
|
||||
class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {};
|
||||
class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {
|
||||
};
|
||||
|
||||
TEST_P(DecodePerfTest, PerfTest) {
|
||||
const char *const video_name = GET_PARAM(VIDEO_NAME);
|
||||
@ -90,7 +92,8 @@ TEST_P(DecodePerfTest, PerfTest) {
|
||||
}
|
||||
|
||||
vpx_usec_timer_mark(&t);
|
||||
const double elapsed_secs = double(vpx_usec_timer_elapsed(&t)) / kUsecsInSec;
|
||||
const double elapsed_secs = double(vpx_usec_timer_elapsed(&t))
|
||||
/ kUsecsInSec;
|
||||
const unsigned frames = video.frame_number();
|
||||
const double fps = double(frames) / elapsed_secs;
|
||||
|
||||
@ -108,13 +111,17 @@ TEST_P(DecodePerfTest, PerfTest) {
|
||||
INSTANTIATE_TEST_CASE_P(VP9, DecodePerfTest,
|
||||
::testing::ValuesIn(kVP9DecodePerfVectors));
|
||||
|
||||
class VP9NewEncodeDecodePerfTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
class VP9NewEncodeDecodePerfTest :
|
||||
public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
protected:
|
||||
VP9NewEncodeDecodePerfTest()
|
||||
: EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)), speed_(0),
|
||||
outfile_(0), out_frames_(0) {}
|
||||
: EncoderTest(GET_PARAM(0)),
|
||||
encoding_mode_(GET_PARAM(1)),
|
||||
speed_(0),
|
||||
outfile_(0),
|
||||
out_frames_(0) {
|
||||
}
|
||||
|
||||
virtual ~VP9NewEncodeDecodePerfTest() {}
|
||||
|
||||
@ -153,9 +160,8 @@ class VP9NewEncodeDecodePerfTest
|
||||
|
||||
virtual void EndPassHook() {
|
||||
if (outfile_ != NULL) {
|
||||
if (!fseek(outfile_, 0, SEEK_SET)) {
|
||||
if (!fseek(outfile_, 0, SEEK_SET))
|
||||
ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
|
||||
}
|
||||
fclose(outfile_);
|
||||
outfile_ = NULL;
|
||||
}
|
||||
@ -165,9 +171,8 @@ class VP9NewEncodeDecodePerfTest
|
||||
++out_frames_;
|
||||
|
||||
// Write initial file header if first frame.
|
||||
if (pkt->data.frame.pts == 0) {
|
||||
if (pkt->data.frame.pts == 0)
|
||||
ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
|
||||
}
|
||||
|
||||
// Write frame header and data.
|
||||
ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz);
|
||||
@ -175,9 +180,11 @@ class VP9NewEncodeDecodePerfTest
|
||||
pkt->data.frame.sz);
|
||||
}
|
||||
|
||||
virtual bool DoDecode() const { return false; }
|
||||
virtual bool DoDecode() { return false; }
|
||||
|
||||
void set_speed(unsigned int speed) { speed_ = speed; }
|
||||
void set_speed(unsigned int speed) {
|
||||
speed_ = speed;
|
||||
}
|
||||
|
||||
private:
|
||||
libvpx_test::TestMode encoding_mode_;
|
||||
@ -189,7 +196,10 @@ class VP9NewEncodeDecodePerfTest
|
||||
struct EncodePerfTestVideo {
|
||||
EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
|
||||
uint32_t bitrate_, int frames_)
|
||||
: name(name_), width(width_), height(height_), bitrate(bitrate_),
|
||||
: name(name_),
|
||||
width(width_),
|
||||
height(height_),
|
||||
bitrate(bitrate_),
|
||||
frames(frames_) {}
|
||||
const char *name;
|
||||
uint32_t width;
|
||||
@ -215,8 +225,10 @@ TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) {
|
||||
|
||||
const char *video_name = kVP9EncodePerfTestVectors[i].name;
|
||||
libvpx_test::I420VideoSource video(
|
||||
video_name, kVP9EncodePerfTestVectors[i].width,
|
||||
kVP9EncodePerfTestVectors[i].height, timebase.den, timebase.num, 0,
|
||||
video_name,
|
||||
kVP9EncodePerfTestVectors[i].width,
|
||||
kVP9EncodePerfTestVectors[i].height,
|
||||
timebase.den, timebase.num, 0,
|
||||
kVP9EncodePerfTestVectors[i].frames);
|
||||
set_speed(2);
|
||||
|
||||
@ -256,6 +268,6 @@ TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) {
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(VP9NewEncodeDecodePerfTest,
|
||||
::testing::Values(::libvpx_test::kTwoPassGood));
|
||||
VP9_INSTANTIATE_TEST_CASE(
|
||||
VP9NewEncodeDecodePerfTest, ::testing::Values(::libvpx_test::kTwoPassGood));
|
||||
} // namespace
|
||||
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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 "test/codec_factory.h"
|
||||
#include "test/decode_test_driver.h"
|
||||
#include "test/ivf_video_source.h"
|
||||
#include "test/test_vectors.h"
|
||||
#include "test/util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const unsigned int kNumFrames = 19;
|
||||
|
||||
class DecodeSvcTest : public ::libvpx_test::DecoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<const char *> {
|
||||
protected:
|
||||
DecodeSvcTest() : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)) {}
|
||||
virtual ~DecodeSvcTest() {}
|
||||
|
||||
virtual void PreDecodeFrameHook(
|
||||
const libvpx_test::CompressedVideoSource &video,
|
||||
libvpx_test::Decoder *decoder) {
|
||||
if (video.frame_number() == 0)
|
||||
decoder->Control(VP9_DECODE_SVC_SPATIAL_LAYER, spatial_layer_);
|
||||
}
|
||||
|
||||
virtual void DecompressedFrameHook(const vpx_image_t &img,
|
||||
const unsigned int frame_number) {
|
||||
ASSERT_EQ(img.d_w, width_);
|
||||
ASSERT_EQ(img.d_h, height_);
|
||||
total_frames_ = frame_number;
|
||||
}
|
||||
|
||||
int spatial_layer_;
|
||||
unsigned int width_;
|
||||
unsigned int height_;
|
||||
unsigned int total_frames_;
|
||||
};
|
||||
|
||||
// SVC test vector is 1280x720, with 3 spatial layers, and 20 frames.
|
||||
|
||||
// Decode the SVC test vector, which has 3 spatial layers, and decode up to
|
||||
// spatial layer 0. Verify the resolution of each decoded frame and the total
|
||||
// number of frames decoded. This results in 1/4x1/4 resolution (320x180).
|
||||
TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer0) {
|
||||
const std::string filename = GET_PARAM(1);
|
||||
testing::internal::scoped_ptr<libvpx_test::CompressedVideoSource> video;
|
||||
video.reset(new libvpx_test::IVFVideoSource(filename));
|
||||
ASSERT_TRUE(video.get() != NULL);
|
||||
video->Init();
|
||||
total_frames_ = 0;
|
||||
spatial_layer_ = 0;
|
||||
width_ = 320;
|
||||
height_ = 180;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
|
||||
ASSERT_EQ(total_frames_, kNumFrames);
|
||||
}
|
||||
|
||||
// Decode the SVC test vector, which has 3 spatial layers, and decode up to
|
||||
// spatial layer 1. Verify the resolution of each decoded frame and the total
|
||||
// number of frames decoded. This results in 1/2x1/2 resolution (640x360).
|
||||
TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer1) {
|
||||
const std::string filename = GET_PARAM(1);
|
||||
testing::internal::scoped_ptr<libvpx_test::CompressedVideoSource> video;
|
||||
video.reset(new libvpx_test::IVFVideoSource(filename));
|
||||
ASSERT_TRUE(video.get() != NULL);
|
||||
video->Init();
|
||||
total_frames_ = 0;
|
||||
spatial_layer_ = 1;
|
||||
width_ = 640;
|
||||
height_ = 360;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
|
||||
ASSERT_EQ(total_frames_, kNumFrames);
|
||||
}
|
||||
|
||||
// Decode the SVC test vector, which has 3 spatial layers, and decode up to
|
||||
// spatial layer 2. Verify the resolution of each decoded frame and the total
|
||||
// number of frames decoded. This results in the full resolution (1280x720).
|
||||
TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer2) {
|
||||
const std::string filename = GET_PARAM(1);
|
||||
testing::internal::scoped_ptr<libvpx_test::CompressedVideoSource> video;
|
||||
video.reset(new libvpx_test::IVFVideoSource(filename));
|
||||
ASSERT_TRUE(video.get() != NULL);
|
||||
video->Init();
|
||||
total_frames_ = 0;
|
||||
spatial_layer_ = 2;
|
||||
width_ = 1280;
|
||||
height_ = 720;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
|
||||
ASSERT_EQ(total_frames_, kNumFrames);
|
||||
}
|
||||
|
||||
// Decode the SVC test vector, which has 3 spatial layers, and decode up to
|
||||
// spatial layer 10. Verify the resolution of each decoded frame and the total
|
||||
// number of frames decoded. This is beyond the number of spatial layers, so
|
||||
// the decoding should result in the full resolution (1280x720).
|
||||
TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer10) {
|
||||
const std::string filename = GET_PARAM(1);
|
||||
testing::internal::scoped_ptr<libvpx_test::CompressedVideoSource> video;
|
||||
video.reset(new libvpx_test::IVFVideoSource(filename));
|
||||
ASSERT_TRUE(video.get() != NULL);
|
||||
video->Init();
|
||||
total_frames_ = 0;
|
||||
spatial_layer_ = 10;
|
||||
width_ = 1280;
|
||||
height_ = 720;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
|
||||
ASSERT_EQ(total_frames_, kNumFrames);
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(
|
||||
DecodeSvcTest, ::testing::ValuesIn(libvpx_test::kVP9TestVectorsSvc,
|
||||
libvpx_test::kVP9TestVectorsSvc +
|
||||
libvpx_test::kNumVP9TestVectorsSvc));
|
||||
} // namespace
|
@ -21,8 +21,9 @@ const char kVP8Name[] = "WebM Project VP8";
|
||||
|
||||
vpx_codec_err_t Decoder::PeekStream(const uint8_t *cxdata, size_t size,
|
||||
vpx_codec_stream_info_t *stream_info) {
|
||||
return vpx_codec_peek_stream_info(
|
||||
CodecInterface(), cxdata, static_cast<unsigned int>(size), stream_info);
|
||||
return vpx_codec_peek_stream_info(CodecInterface(),
|
||||
cxdata, static_cast<unsigned int>(size),
|
||||
stream_info);
|
||||
}
|
||||
|
||||
vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size) {
|
||||
@ -34,8 +35,9 @@ vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size,
|
||||
vpx_codec_err_t res_dec;
|
||||
InitOnce();
|
||||
API_REGISTER_STATE_CHECK(
|
||||
res_dec = vpx_codec_decode(
|
||||
&decoder_, cxdata, static_cast<unsigned int>(size), user_priv, 0));
|
||||
res_dec = vpx_codec_decode(&decoder_,
|
||||
cxdata, static_cast<unsigned int>(size),
|
||||
user_priv, 0));
|
||||
return res_dec;
|
||||
}
|
||||
|
||||
@ -52,21 +54,20 @@ void DecoderTest::HandlePeekResult(Decoder *const decoder,
|
||||
/* 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
|
||||
* frame, which must be a keyframe. */
|
||||
if (video->frame_number() == 0) {
|
||||
ASSERT_EQ(VPX_CODEC_OK, res_peek)
|
||||
<< "Peek return failed: " << vpx_codec_err_to_string(res_peek);
|
||||
}
|
||||
if (video->frame_number() == 0)
|
||||
ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
|
||||
<< vpx_codec_err_to_string(res_peek);
|
||||
} else {
|
||||
/* The Vp9 implementation of PeekStream returns an error only if the
|
||||
* data passed to it isn't a valid Vp9 chunk. */
|
||||
ASSERT_EQ(VPX_CODEC_OK, res_peek)
|
||||
<< "Peek return failed: " << vpx_codec_err_to_string(res_peek);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
|
||||
<< vpx_codec_err_to_string(res_peek);
|
||||
}
|
||||
}
|
||||
|
||||
void DecoderTest::RunLoop(CompressedVideoSource *video,
|
||||
const vpx_codec_dec_cfg_t &dec_cfg) {
|
||||
Decoder *const decoder = codec_->CreateDecoder(dec_cfg, flags_);
|
||||
Decoder* const decoder = codec_->CreateDecoder(dec_cfg, flags_, 0);
|
||||
ASSERT_TRUE(decoder != NULL);
|
||||
bool end_of_file = false;
|
||||
|
||||
@ -79,14 +80,16 @@ void DecoderTest::RunLoop(CompressedVideoSource *video,
|
||||
stream_info.sz = sizeof(stream_info);
|
||||
|
||||
if (video->cxdata() != NULL) {
|
||||
const vpx_codec_err_t res_peek = decoder->PeekStream(
|
||||
video->cxdata(), video->frame_size(), &stream_info);
|
||||
const vpx_codec_err_t res_peek = decoder->PeekStream(video->cxdata(),
|
||||
video->frame_size(),
|
||||
&stream_info);
|
||||
HandlePeekResult(decoder, video, res_peek);
|
||||
ASSERT_FALSE(::testing::Test::HasFailure());
|
||||
|
||||
vpx_codec_err_t res_dec =
|
||||
decoder->DecodeFrame(video->cxdata(), video->frame_size());
|
||||
if (!HandleDecodeResult(res_dec, *video, decoder)) break;
|
||||
vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(),
|
||||
video->frame_size());
|
||||
if (!HandleDecodeResult(res_dec, *video, decoder))
|
||||
break;
|
||||
} else {
|
||||
// Signal end of the file to the decoder.
|
||||
const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);
|
||||
@ -98,9 +101,8 @@ void DecoderTest::RunLoop(CompressedVideoSource *video,
|
||||
const vpx_image_t *img = NULL;
|
||||
|
||||
// Get decompressed data
|
||||
while ((img = dec_iter.Next())) {
|
||||
while ((img = dec_iter.Next()))
|
||||
DecompressedFrameHook(*img, video->frame_number());
|
||||
}
|
||||
}
|
||||
delete decoder;
|
||||
}
|
||||
@ -114,6 +116,8 @@ void DecoderTest::set_cfg(const vpx_codec_dec_cfg_t &dec_cfg) {
|
||||
memcpy(&cfg_, &dec_cfg, sizeof(cfg_));
|
||||
}
|
||||
|
||||
void DecoderTest::set_flags(const vpx_codec_flags_t flags) { flags_ = flags; }
|
||||
void DecoderTest::set_flags(const vpx_codec_flags_t flags) {
|
||||
flags_ = flags;
|
||||
}
|
||||
|
||||
} // namespace libvpx_test
|
||||
|
@ -26,11 +26,13 @@ class DxDataIterator {
|
||||
explicit DxDataIterator(vpx_codec_ctx_t *decoder)
|
||||
: decoder_(decoder), iter_(NULL) {}
|
||||
|
||||
const vpx_image_t *Next() { return vpx_codec_get_frame(decoder_, &iter_); }
|
||||
const vpx_image_t *Next() {
|
||||
return vpx_codec_get_frame(decoder_, &iter_);
|
||||
}
|
||||
|
||||
private:
|
||||
vpx_codec_ctx_t *decoder_;
|
||||
vpx_codec_iter_t iter_;
|
||||
vpx_codec_ctx_t *decoder_;
|
||||
vpx_codec_iter_t iter_;
|
||||
};
|
||||
|
||||
// Provides a simplified interface to manage one video decoding.
|
||||
@ -38,17 +40,20 @@ class DxDataIterator {
|
||||
// as more tests are added.
|
||||
class Decoder {
|
||||
public:
|
||||
explicit Decoder(vpx_codec_dec_cfg_t cfg)
|
||||
: cfg_(cfg), flags_(0), init_done_(false) {
|
||||
Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
|
||||
: cfg_(cfg), flags_(0), deadline_(deadline), init_done_(false) {
|
||||
memset(&decoder_, 0, sizeof(decoder_));
|
||||
}
|
||||
|
||||
Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag)
|
||||
: cfg_(cfg), flags_(flag), init_done_(false) {
|
||||
Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
|
||||
unsigned long deadline) // NOLINT
|
||||
: cfg_(cfg), flags_(flag), deadline_(deadline), init_done_(false) {
|
||||
memset(&decoder_, 0, sizeof(decoder_));
|
||||
}
|
||||
|
||||
virtual ~Decoder() { vpx_codec_destroy(&decoder_); }
|
||||
virtual ~Decoder() {
|
||||
vpx_codec_destroy(&decoder_);
|
||||
}
|
||||
|
||||
vpx_codec_err_t PeekStream(const uint8_t *cxdata, size_t size,
|
||||
vpx_codec_stream_info_t *stream_info);
|
||||
@ -58,9 +63,17 @@ class Decoder {
|
||||
vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size,
|
||||
void *user_priv);
|
||||
|
||||
DxDataIterator GetDxData() { return DxDataIterator(&decoder_); }
|
||||
DxDataIterator GetDxData() {
|
||||
return DxDataIterator(&decoder_);
|
||||
}
|
||||
|
||||
void Control(int ctrl_id, int arg) { Control(ctrl_id, arg, VPX_CODEC_OK); }
|
||||
void set_deadline(unsigned long deadline) {
|
||||
deadline_ = deadline;
|
||||
}
|
||||
|
||||
void Control(int ctrl_id, int arg) {
|
||||
Control(ctrl_id, arg, VPX_CODEC_OK);
|
||||
}
|
||||
|
||||
void Control(int ctrl_id, const void *arg) {
|
||||
InitOnce();
|
||||
@ -74,7 +87,7 @@ class Decoder {
|
||||
ASSERT_EQ(expected_value, res) << DecodeError();
|
||||
}
|
||||
|
||||
const char *DecodeError() {
|
||||
const char* DecodeError() {
|
||||
const char *detail = vpx_codec_error_detail(&decoder_);
|
||||
return detail ? detail : vpx_codec_error(&decoder_);
|
||||
}
|
||||
@ -84,34 +97,38 @@ class Decoder {
|
||||
vpx_get_frame_buffer_cb_fn_t cb_get,
|
||||
vpx_release_frame_buffer_cb_fn_t cb_release, void *user_priv) {
|
||||
InitOnce();
|
||||
return vpx_codec_set_frame_buffer_functions(&decoder_, cb_get, cb_release,
|
||||
user_priv);
|
||||
return vpx_codec_set_frame_buffer_functions(
|
||||
&decoder_, cb_get, cb_release, user_priv);
|
||||
}
|
||||
|
||||
const char *GetDecoderName() const {
|
||||
const char* GetDecoderName() const {
|
||||
return vpx_codec_iface_name(CodecInterface());
|
||||
}
|
||||
|
||||
bool IsVP8() const;
|
||||
|
||||
vpx_codec_ctx_t *GetDecoder() { return &decoder_; }
|
||||
vpx_codec_ctx_t * GetDecoder() {
|
||||
return &decoder_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t *CodecInterface() const = 0;
|
||||
virtual vpx_codec_iface_t* CodecInterface() const = 0;
|
||||
|
||||
void InitOnce() {
|
||||
if (!init_done_) {
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_dec_init(&decoder_, CodecInterface(), &cfg_, flags_);
|
||||
const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_,
|
||||
CodecInterface(),
|
||||
&cfg_, flags_);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
|
||||
init_done_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
vpx_codec_ctx_t decoder_;
|
||||
vpx_codec_ctx_t decoder_;
|
||||
vpx_codec_dec_cfg_t cfg_;
|
||||
vpx_codec_flags_t flags_;
|
||||
bool init_done_;
|
||||
vpx_codec_flags_t flags_;
|
||||
unsigned int deadline_;
|
||||
bool init_done_;
|
||||
};
|
||||
|
||||
// Common test functionality for all Decoder tests.
|
||||
@ -126,35 +143,37 @@ class DecoderTest {
|
||||
virtual void set_flags(const vpx_codec_flags_t flags);
|
||||
|
||||
// Hook to be called before decompressing every frame.
|
||||
virtual void PreDecodeFrameHook(const CompressedVideoSource & /*video*/,
|
||||
Decoder * /*decoder*/) {}
|
||||
virtual void PreDecodeFrameHook(const CompressedVideoSource& /*video*/,
|
||||
Decoder* /*decoder*/) {}
|
||||
|
||||
// Hook to be called to handle decode result. Return true to continue.
|
||||
virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
|
||||
const CompressedVideoSource & /*video*/,
|
||||
const CompressedVideoSource& /*video*/,
|
||||
Decoder *decoder) {
|
||||
EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
|
||||
return VPX_CODEC_OK == res_dec;
|
||||
}
|
||||
|
||||
// Hook to be called on every decompressed frame.
|
||||
virtual void DecompressedFrameHook(const vpx_image_t & /*img*/,
|
||||
virtual void DecompressedFrameHook(const vpx_image_t& /*img*/,
|
||||
const unsigned int /*frame_number*/) {}
|
||||
|
||||
// Hook to be called on peek result
|
||||
virtual void HandlePeekResult(Decoder *const decoder,
|
||||
virtual void HandlePeekResult(Decoder* const decoder,
|
||||
CompressedVideoSource *video,
|
||||
const vpx_codec_err_t res_peek);
|
||||
|
||||
protected:
|
||||
explicit DecoderTest(const CodecFactory *codec)
|
||||
: codec_(codec), cfg_(), flags_(0) {}
|
||||
: codec_(codec),
|
||||
cfg_(),
|
||||
flags_(0) {}
|
||||
|
||||
virtual ~DecoderTest() {}
|
||||
|
||||
const CodecFactory *codec_;
|
||||
vpx_codec_dec_cfg_t cfg_;
|
||||
vpx_codec_flags_t flags_;
|
||||
vpx_codec_flags_t flags_;
|
||||
};
|
||||
|
||||
} // namespace libvpx_test
|
||||
|
@ -25,9 +25,12 @@ TEST(EncodeAPI, InvalidParams) {
|
||||
#endif
|
||||
#if CONFIG_VP9_ENCODER
|
||||
&vpx_codec_vp9_cx_algo,
|
||||
#endif
|
||||
#if CONFIG_VP10_ENCODER
|
||||
&vpx_codec_vp10_cx_algo,
|
||||
#endif
|
||||
};
|
||||
uint8_t buf[1] = { 0 };
|
||||
uint8_t buf[1] = {0};
|
||||
vpx_image_t img;
|
||||
vpx_codec_ctx_t enc;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
@ -62,134 +65,4 @@ TEST(EncodeAPI, InvalidParams) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(EncodeAPI, HighBitDepthCapability) {
|
||||
// VP8 should not claim VP9 HBD as a capability.
|
||||
#if CONFIG_VP8_ENCODER
|
||||
const vpx_codec_caps_t vp8_caps = vpx_codec_get_caps(&vpx_codec_vp8_cx_algo);
|
||||
EXPECT_EQ(vp8_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
|
||||
#endif
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
const vpx_codec_caps_t vp9_caps = vpx_codec_get_caps(&vpx_codec_vp9_cx_algo);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, VPX_CODEC_CAP_HIGHBITDEPTH);
|
||||
#else
|
||||
EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_VP8_ENCODER
|
||||
TEST(EncodeAPI, ImageSizeSetting) {
|
||||
const int width = 711;
|
||||
const int height = 360;
|
||||
const int bps = 12;
|
||||
vpx_image_t img;
|
||||
vpx_codec_ctx_t enc;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
uint8_t *img_buf = reinterpret_cast<uint8_t *>(
|
||||
calloc(width * height * bps / 8, sizeof(*img_buf)));
|
||||
vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &cfg, 0);
|
||||
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
vpx_img_wrap(&img, VPX_IMG_FMT_I420, width, height, 1, img_buf);
|
||||
|
||||
vpx_codec_enc_init(&enc, vpx_codec_vp8_cx(), &cfg, 0);
|
||||
|
||||
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, &img, 0, 1, 0, 0));
|
||||
|
||||
free(img_buf);
|
||||
|
||||
vpx_codec_destroy(&enc);
|
||||
}
|
||||
#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
|
||||
|
@ -26,7 +26,10 @@ const double kUsecsInSec = 1000000.0;
|
||||
struct EncodePerfTestVideo {
|
||||
EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
|
||||
uint32_t bitrate_, int frames_)
|
||||
: name(name_), width(width_), height(height_), bitrate(bitrate_),
|
||||
: name(name_),
|
||||
width(width_),
|
||||
height(height_),
|
||||
bitrate(bitrate_),
|
||||
frames(frames_) {}
|
||||
const char *name;
|
||||
uint32_t width;
|
||||
@ -42,8 +45,8 @@ const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
|
||||
EncodePerfTestVideo("macmarcostationary_640_480_30.yuv", 640, 480, 200, 718),
|
||||
EncodePerfTestVideo("niklas_640_480_30.yuv", 640, 480, 200, 471),
|
||||
EncodePerfTestVideo("tacomanarrows_640_480_30.yuv", 640, 480, 200, 300),
|
||||
EncodePerfTestVideo("tacomasmallcameramovement_640_480_30.yuv", 640, 480, 200,
|
||||
300),
|
||||
EncodePerfTestVideo("tacomasmallcameramovement_640_480_30.yuv",
|
||||
640, 480, 200, 300),
|
||||
EncodePerfTestVideo("thaloundeskmtg_640_480_30.yuv", 640, 480, 200, 300),
|
||||
EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
|
||||
};
|
||||
@ -58,8 +61,12 @@ class VP9EncodePerfTest
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
protected:
|
||||
VP9EncodePerfTest()
|
||||
: EncoderTest(GET_PARAM(0)), min_psnr_(kMaxPsnr), nframes_(0),
|
||||
encoding_mode_(GET_PARAM(1)), speed_(0), threads_(1) {}
|
||||
: EncoderTest(GET_PARAM(0)),
|
||||
min_psnr_(kMaxPsnr),
|
||||
nframes_(0),
|
||||
encoding_mode_(GET_PARAM(1)),
|
||||
speed_(0),
|
||||
threads_(1) {}
|
||||
|
||||
virtual ~VP9EncodePerfTest() {}
|
||||
|
||||
@ -100,18 +107,24 @@ class VP9EncodePerfTest
|
||||
|
||||
virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
if (pkt->data.psnr.psnr[0] < min_psnr_) {
|
||||
min_psnr_ = pkt->data.psnr.psnr[0];
|
||||
min_psnr_= pkt->data.psnr.psnr[0];
|
||||
}
|
||||
}
|
||||
|
||||
// for performance reasons don't decode
|
||||
virtual bool DoDecode() const { return false; }
|
||||
virtual bool DoDecode() { return 0; }
|
||||
|
||||
double min_psnr() const { return min_psnr_; }
|
||||
double min_psnr() const {
|
||||
return min_psnr_;
|
||||
}
|
||||
|
||||
void set_speed(unsigned int speed) { speed_ = speed; }
|
||||
void set_speed(unsigned int speed) {
|
||||
speed_ = speed;
|
||||
}
|
||||
|
||||
void set_threads(unsigned int threads) { threads_ = threads; }
|
||||
void set_threads(unsigned int threads) {
|
||||
threads_ = threads;
|
||||
}
|
||||
|
||||
private:
|
||||
double min_psnr_;
|
||||
@ -126,12 +139,11 @@ TEST_P(VP9EncodePerfTest, PerfTest) {
|
||||
for (size_t j = 0; j < NELEMENTS(kEncodePerfTestSpeeds); ++j) {
|
||||
for (size_t k = 0; k < NELEMENTS(kEncodePerfTestThreads); ++k) {
|
||||
if (kVP9EncodePerfTestVectors[i].width < 512 &&
|
||||
kEncodePerfTestThreads[k] > 1) {
|
||||
kEncodePerfTestThreads[k] > 1)
|
||||
continue;
|
||||
} else if (kVP9EncodePerfTestVectors[i].width < 1024 &&
|
||||
kEncodePerfTestThreads[k] > 2) {
|
||||
else if (kVP9EncodePerfTestVectors[i].width < 1024 &&
|
||||
kEncodePerfTestThreads[k] > 2)
|
||||
continue;
|
||||
}
|
||||
|
||||
set_threads(kEncodePerfTestThreads[k]);
|
||||
SetUp();
|
||||
@ -145,8 +157,10 @@ TEST_P(VP9EncodePerfTest, PerfTest) {
|
||||
const unsigned frames = kVP9EncodePerfTestVectors[i].frames;
|
||||
const char *video_name = kVP9EncodePerfTestVectors[i].name;
|
||||
libvpx_test::I420VideoSource video(
|
||||
video_name, kVP9EncodePerfTestVectors[i].width,
|
||||
kVP9EncodePerfTestVectors[i].height, timebase.den, timebase.num, 0,
|
||||
video_name,
|
||||
kVP9EncodePerfTestVectors[i].width,
|
||||
kVP9EncodePerfTestVectors[i].height,
|
||||
timebase.den, timebase.num, 0,
|
||||
kVP9EncodePerfTestVectors[i].frames);
|
||||
set_speed(kEncodePerfTestSpeeds[j]);
|
||||
|
||||
@ -183,6 +197,6 @@ TEST_P(VP9EncodePerfTest, PerfTest) {
|
||||
}
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(VP9EncodePerfTest,
|
||||
::testing::Values(::libvpx_test::kRealTime));
|
||||
VP9_INSTANTIATE_TEST_CASE(
|
||||
VP9EncodePerfTest, ::testing::Values(::libvpx_test::kRealTime));
|
||||
} // namespace
|
||||
|
@ -30,7 +30,8 @@ void Encoder::InitEncoder(VideoSource *video) {
|
||||
cfg_.g_timebase = video->timebase();
|
||||
cfg_.rc_twopass_stats_in = stats_->buf();
|
||||
|
||||
res = vpx_codec_enc_init(&encoder_, CodecInterface(), &cfg_, init_flags_);
|
||||
res = vpx_codec_enc_init(&encoder_, CodecInterface(), &cfg_,
|
||||
init_flags_);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
|
||||
|
||||
#if CONFIG_VP9_ENCODER
|
||||
@ -41,6 +42,15 @@ void Encoder::InitEncoder(VideoSource *video) {
|
||||
log2_tile_columns);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
|
||||
} else
|
||||
#endif
|
||||
#if CONFIG_VP10_ENCODER
|
||||
if (CodecInterface() == &vpx_codec_vp10_cx_algo) {
|
||||
// Default to 1 tile column for VP10.
|
||||
const int log2_tile_columns = 0;
|
||||
res = vpx_codec_control_(&encoder_, VP9E_SET_TILE_COLUMNS,
|
||||
log2_tile_columns);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if CONFIG_VP8_ENCODER
|
||||
@ -52,17 +62,17 @@ void Encoder::InitEncoder(VideoSource *video) {
|
||||
}
|
||||
|
||||
void Encoder::EncodeFrame(VideoSource *video, const unsigned long frame_flags) {
|
||||
if (video->img()) {
|
||||
if (video->img())
|
||||
EncodeFrameInternal(*video, frame_flags);
|
||||
} else {
|
||||
else
|
||||
Flush();
|
||||
}
|
||||
|
||||
// Handle twopass stats
|
||||
CxDataIterator iter = GetCxData();
|
||||
|
||||
while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
|
||||
if (pkt->kind != VPX_CODEC_STATS_PKT) continue;
|
||||
if (pkt->kind != VPX_CODEC_STATS_PKT)
|
||||
continue;
|
||||
|
||||
stats_->Append(*pkt);
|
||||
}
|
||||
@ -82,15 +92,15 @@ void Encoder::EncodeFrameInternal(const VideoSource &video,
|
||||
}
|
||||
|
||||
// Encode the frame
|
||||
API_REGISTER_STATE_CHECK(res = vpx_codec_encode(&encoder_, img, video.pts(),
|
||||
video.duration(), frame_flags,
|
||||
deadline_));
|
||||
API_REGISTER_STATE_CHECK(
|
||||
res = vpx_codec_encode(&encoder_, img, video.pts(), video.duration(),
|
||||
frame_flags, deadline_));
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
|
||||
}
|
||||
|
||||
void Encoder::Flush() {
|
||||
const vpx_codec_err_t res =
|
||||
vpx_codec_encode(&encoder_, NULL, 0, 0, 0, deadline_);
|
||||
const vpx_codec_err_t res = vpx_codec_encode(&encoder_, NULL, 0, 0, 0,
|
||||
deadline_);
|
||||
if (!encoder_.priv)
|
||||
ASSERT_EQ(VPX_CODEC_ERROR, res) << EncoderError();
|
||||
else
|
||||
@ -105,57 +115,60 @@ void EncoderTest::InitializeConfig() {
|
||||
|
||||
void EncoderTest::SetMode(TestMode mode) {
|
||||
switch (mode) {
|
||||
case kRealTime: deadline_ = VPX_DL_REALTIME; break;
|
||||
case kRealTime:
|
||||
deadline_ = VPX_DL_REALTIME;
|
||||
break;
|
||||
|
||||
case kOnePassGood:
|
||||
case kTwoPassGood: deadline_ = VPX_DL_GOOD_QUALITY; break;
|
||||
case kTwoPassGood:
|
||||
deadline_ = VPX_DL_GOOD_QUALITY;
|
||||
break;
|
||||
|
||||
case kOnePassBest:
|
||||
case kTwoPassBest: deadline_ = VPX_DL_BEST_QUALITY; break;
|
||||
case kTwoPassBest:
|
||||
deadline_ = VPX_DL_BEST_QUALITY;
|
||||
break;
|
||||
|
||||
default: ASSERT_TRUE(false) << "Unexpected mode " << mode;
|
||||
default:
|
||||
ASSERT_TRUE(false) << "Unexpected mode " << mode;
|
||||
}
|
||||
|
||||
if (mode == kTwoPassGood || mode == kTwoPassBest) {
|
||||
if (mode == kTwoPassGood || mode == kTwoPassBest)
|
||||
passes_ = 2;
|
||||
} else {
|
||||
else
|
||||
passes_ = 1;
|
||||
}
|
||||
}
|
||||
// The function should return "true" most of the time, therefore no early
|
||||
// break-out is implemented within the match checking process.
|
||||
static bool compare_img(const vpx_image_t *img1, const vpx_image_t *img2) {
|
||||
bool match = (img1->fmt == img2->fmt) && (img1->cs == img2->cs) &&
|
||||
(img1->d_w == img2->d_w) && (img1->d_h == img2->d_h);
|
||||
static bool compare_img(const vpx_image_t *img1,
|
||||
const vpx_image_t *img2) {
|
||||
bool match = (img1->fmt == img2->fmt) &&
|
||||
(img1->cs == img2->cs) &&
|
||||
(img1->d_w == img2->d_w) &&
|
||||
(img1->d_h == img2->d_h);
|
||||
|
||||
const unsigned int width_y = img1->d_w;
|
||||
const unsigned int width_y = img1->d_w;
|
||||
const unsigned int height_y = img1->d_h;
|
||||
unsigned int i;
|
||||
for (i = 0; i < height_y; ++i) {
|
||||
for (i = 0; i < height_y; ++i)
|
||||
match = (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
|
||||
img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
|
||||
width_y) == 0) &&
|
||||
match;
|
||||
}
|
||||
const unsigned int width_uv = (img1->d_w + 1) >> 1;
|
||||
width_y) == 0) && match;
|
||||
const unsigned int width_uv = (img1->d_w + 1) >> 1;
|
||||
const unsigned int height_uv = (img1->d_h + 1) >> 1;
|
||||
for (i = 0; i < height_uv; ++i) {
|
||||
for (i = 0; i < height_uv; ++i)
|
||||
match = (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
|
||||
img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U],
|
||||
width_uv) == 0) &&
|
||||
match;
|
||||
}
|
||||
for (i = 0; i < height_uv; ++i) {
|
||||
width_uv) == 0) && match;
|
||||
for (i = 0; i < height_uv; ++i)
|
||||
match = (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V],
|
||||
img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V],
|
||||
width_uv) == 0) &&
|
||||
match;
|
||||
}
|
||||
width_uv) == 0) && match;
|
||||
return match;
|
||||
}
|
||||
|
||||
void EncoderTest::MismatchHook(const vpx_image_t * /*img1*/,
|
||||
const vpx_image_t * /*img2*/) {
|
||||
void EncoderTest::MismatchHook(const vpx_image_t* /*img1*/,
|
||||
const vpx_image_t* /*img2*/) {
|
||||
ASSERT_TRUE(0) << "Encode/Decode mismatch found";
|
||||
}
|
||||
|
||||
@ -168,41 +181,36 @@ void EncoderTest::RunLoop(VideoSource *video) {
|
||||
for (unsigned int pass = 0; pass < passes_; pass++) {
|
||||
last_pts_ = 0;
|
||||
|
||||
if (passes_ == 1) {
|
||||
if (passes_ == 1)
|
||||
cfg_.g_pass = VPX_RC_ONE_PASS;
|
||||
} else if (pass == 0) {
|
||||
else if (pass == 0)
|
||||
cfg_.g_pass = VPX_RC_FIRST_PASS;
|
||||
} else {
|
||||
else
|
||||
cfg_.g_pass = VPX_RC_LAST_PASS;
|
||||
}
|
||||
|
||||
BeginPassHook(pass);
|
||||
testing::internal::scoped_ptr<Encoder> encoder(
|
||||
codec_->CreateEncoder(cfg_, deadline_, init_flags_, &stats_));
|
||||
ASSERT_TRUE(encoder.get() != NULL);
|
||||
Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_,
|
||||
&stats_);
|
||||
ASSERT_TRUE(encoder != NULL);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(video->Begin());
|
||||
video->Begin();
|
||||
encoder->InitEncoder(video);
|
||||
ASSERT_FALSE(::testing::Test::HasFatalFailure());
|
||||
|
||||
unsigned long dec_init_flags = 0; // NOLINT
|
||||
// Use fragment decoder if encoder outputs partitions.
|
||||
// NOTE: fragment decoder and partition encoder are only supported by VP8.
|
||||
if (init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) {
|
||||
if (init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION)
|
||||
dec_init_flags |= VPX_CODEC_USE_INPUT_FRAGMENTS;
|
||||
}
|
||||
testing::internal::scoped_ptr<Decoder> decoder(
|
||||
codec_->CreateDecoder(dec_cfg, dec_init_flags));
|
||||
Decoder* const decoder = codec_->CreateDecoder(dec_cfg, dec_init_flags, 0);
|
||||
bool again;
|
||||
for (again = true; again; video->Next()) {
|
||||
again = (video->img() != NULL);
|
||||
|
||||
PreEncodeFrameHook(video);
|
||||
PreEncodeFrameHook(video, encoder.get());
|
||||
PreEncodeFrameHook(video, encoder);
|
||||
encoder->EncodeFrame(video, frame_flags_);
|
||||
|
||||
PostEncodeFrameHook();
|
||||
|
||||
CxDataIterator iter = encoder->GetCxData();
|
||||
|
||||
bool has_cxdata = false;
|
||||
@ -213,11 +221,12 @@ void EncoderTest::RunLoop(VideoSource *video) {
|
||||
switch (pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
has_cxdata = true;
|
||||
if (decoder.get() != NULL && DoDecode()) {
|
||||
if (decoder && DoDecode()) {
|
||||
vpx_codec_err_t res_dec = decoder->DecodeFrame(
|
||||
(const uint8_t *)pkt->data.frame.buf, pkt->data.frame.sz);
|
||||
(const uint8_t*)pkt->data.frame.buf, pkt->data.frame.sz);
|
||||
|
||||
if (!HandleDecodeResult(res_dec, *video, decoder.get())) break;
|
||||
if (!HandleDecodeResult(res_dec, *video, decoder))
|
||||
break;
|
||||
|
||||
has_dxdata = true;
|
||||
}
|
||||
@ -226,18 +235,20 @@ void EncoderTest::RunLoop(VideoSource *video) {
|
||||
FramePktHook(pkt);
|
||||
break;
|
||||
|
||||
case VPX_CODEC_PSNR_PKT: PSNRPktHook(pkt); break;
|
||||
case VPX_CODEC_PSNR_PKT:
|
||||
PSNRPktHook(pkt);
|
||||
break;
|
||||
|
||||
case VPX_CODEC_STATS_PKT: StatsPktHook(pkt); break;
|
||||
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flush the decoder when there are no more fragments.
|
||||
if ((init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) && has_dxdata) {
|
||||
const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);
|
||||
if (!HandleDecodeResult(res_dec, *video, decoder.get())) break;
|
||||
if (!HandleDecodeResult(res_dec, *video, decoder))
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_dxdata && has_cxdata) {
|
||||
@ -250,14 +261,21 @@ void EncoderTest::RunLoop(VideoSource *video) {
|
||||
MismatchHook(img_enc, img_dec);
|
||||
}
|
||||
}
|
||||
if (img_dec) DecompressedFrameHook(*img_dec, video->pts());
|
||||
if (img_dec)
|
||||
DecompressedFrameHook(*img_dec, video->pts());
|
||||
}
|
||||
if (!Continue()) break;
|
||||
if (!Continue())
|
||||
break;
|
||||
}
|
||||
|
||||
EndPassHook();
|
||||
|
||||
if (!Continue()) break;
|
||||
if (decoder)
|
||||
delete decoder;
|
||||
delete encoder;
|
||||
|
||||
if (!Continue())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vpx_config.h"
|
||||
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
|
||||
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
|
||||
#include "vpx/vp8cx.h"
|
||||
#endif
|
||||
#include "vpx/vpx_encoder.h"
|
||||
@ -33,17 +33,19 @@ enum TestMode {
|
||||
kTwoPassGood,
|
||||
kTwoPassBest
|
||||
};
|
||||
#define ALL_TEST_MODES \
|
||||
::testing::Values(::libvpx_test::kRealTime, ::libvpx_test::kOnePassGood, \
|
||||
::libvpx_test::kOnePassBest, ::libvpx_test::kTwoPassGood, \
|
||||
::libvpx_test::kTwoPassBest)
|
||||
#define ALL_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
|
||||
::libvpx_test::kOnePassGood, \
|
||||
::libvpx_test::kOnePassBest, \
|
||||
::libvpx_test::kTwoPassGood, \
|
||||
::libvpx_test::kTwoPassBest)
|
||||
|
||||
#define ONE_PASS_TEST_MODES \
|
||||
::testing::Values(::libvpx_test::kRealTime, ::libvpx_test::kOnePassGood, \
|
||||
::libvpx_test::kOnePassBest)
|
||||
#define ONE_PASS_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
|
||||
::libvpx_test::kOnePassGood, \
|
||||
::libvpx_test::kOnePassBest)
|
||||
|
||||
#define TWO_PASS_TEST_MODES ::testing::Values(::libvpx_test::kTwoPassGood, \
|
||||
::libvpx_test::kTwoPassBest)
|
||||
|
||||
#define TWO_PASS_TEST_MODES \
|
||||
::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kTwoPassBest)
|
||||
|
||||
// Provides an object to handle the libvpx get_cx_data() iteration pattern
|
||||
class CxDataIterator {
|
||||
@ -56,8 +58,8 @@ class CxDataIterator {
|
||||
}
|
||||
|
||||
private:
|
||||
vpx_codec_ctx_t *encoder_;
|
||||
vpx_codec_iter_t iter_;
|
||||
vpx_codec_ctx_t *encoder_;
|
||||
vpx_codec_iter_t iter_;
|
||||
};
|
||||
|
||||
// Implements an in-memory store for libvpx twopass statistics
|
||||
@ -73,12 +75,15 @@ class TwopassStatsStore {
|
||||
return buf;
|
||||
}
|
||||
|
||||
void Reset() { buffer_.clear(); }
|
||||
void Reset() {
|
||||
buffer_.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string buffer_;
|
||||
std::string buffer_;
|
||||
};
|
||||
|
||||
|
||||
// Provides a simplified interface to manage one video encoding pass, given
|
||||
// a configuration and video source.
|
||||
//
|
||||
@ -92,9 +97,13 @@ class Encoder {
|
||||
memset(&encoder_, 0, sizeof(encoder_));
|
||||
}
|
||||
|
||||
virtual ~Encoder() { vpx_codec_destroy(&encoder_); }
|
||||
virtual ~Encoder() {
|
||||
vpx_codec_destroy(&encoder_);
|
||||
}
|
||||
|
||||
CxDataIterator GetCxData() { return CxDataIterator(&encoder_); }
|
||||
CxDataIterator GetCxData() {
|
||||
return CxDataIterator(&encoder_);
|
||||
}
|
||||
|
||||
void InitEncoder(VideoSource *video);
|
||||
|
||||
@ -106,7 +115,9 @@ class Encoder {
|
||||
void EncodeFrame(VideoSource *video, const unsigned long frame_flags);
|
||||
|
||||
// Convenience wrapper for EncodeFrame()
|
||||
void EncodeFrame(VideoSource *video) { EncodeFrame(video, 0); }
|
||||
void EncodeFrame(VideoSource *video) {
|
||||
EncodeFrame(video, 0);
|
||||
}
|
||||
|
||||
void Control(int ctrl_id, int arg) {
|
||||
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
|
||||
@ -128,41 +139,29 @@ class Encoder {
|
||||
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) {
|
||||
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_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 || CONFIG_VP10_ENCODER
|
||||
void Control(int ctrl_id, vpx_active_map_t *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, vpx_roi_map_t *arg) {
|
||||
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Config(const vpx_codec_enc_cfg_t *cfg) {
|
||||
const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
|
||||
cfg_ = *cfg;
|
||||
}
|
||||
|
||||
void set_deadline(unsigned long deadline) { deadline_ = deadline; }
|
||||
void set_deadline(unsigned long deadline) {
|
||||
deadline_ = deadline;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual vpx_codec_iface_t *CodecInterface() const = 0;
|
||||
virtual vpx_codec_iface_t* CodecInterface() const = 0;
|
||||
|
||||
const char *EncoderError() {
|
||||
const char *detail = vpx_codec_error_detail(&encoder_);
|
||||
@ -176,11 +175,11 @@ class Encoder {
|
||||
// Flush the encoder on EOS
|
||||
void Flush();
|
||||
|
||||
vpx_codec_ctx_t encoder_;
|
||||
vpx_codec_enc_cfg_t cfg_;
|
||||
unsigned long deadline_;
|
||||
unsigned long init_flags_;
|
||||
TwopassStatsStore *stats_;
|
||||
vpx_codec_ctx_t encoder_;
|
||||
vpx_codec_enc_cfg_t cfg_;
|
||||
unsigned long deadline_;
|
||||
unsigned long init_flags_;
|
||||
TwopassStatsStore *stats_;
|
||||
};
|
||||
|
||||
// Common test functionality for all Encoder tests.
|
||||
@ -222,40 +221,36 @@ class EncoderTest {
|
||||
virtual void EndPassHook() {}
|
||||
|
||||
// Hook to be called before encoding a frame.
|
||||
virtual void PreEncodeFrameHook(VideoSource * /*video*/) {}
|
||||
virtual void PreEncodeFrameHook(VideoSource * /*video*/,
|
||||
Encoder * /*encoder*/) {}
|
||||
|
||||
virtual void PostEncodeFrameHook() {}
|
||||
virtual void PreEncodeFrameHook(VideoSource* /*video*/) {}
|
||||
virtual void PreEncodeFrameHook(VideoSource* /*video*/,
|
||||
Encoder* /*encoder*/) {}
|
||||
|
||||
// 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*/) {}
|
||||
|
||||
// Hook to be called on every PSNR packet.
|
||||
virtual void PSNRPktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {}
|
||||
|
||||
// Hook to be called on every first pass stats packet.
|
||||
virtual void StatsPktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {}
|
||||
virtual void PSNRPktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {}
|
||||
|
||||
// Hook to determine whether the encode loop should continue.
|
||||
virtual bool Continue() const {
|
||||
return !(::testing::Test::HasFatalFailure() || abort_);
|
||||
}
|
||||
|
||||
const CodecFactory *codec_;
|
||||
const CodecFactory *codec_;
|
||||
// Hook to determine whether to decode frame after encoding
|
||||
virtual bool DoDecode() const { return 1; }
|
||||
|
||||
// Hook to handle encode/decode mismatch
|
||||
virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2);
|
||||
virtual void MismatchHook(const vpx_image_t *img1,
|
||||
const vpx_image_t *img2);
|
||||
|
||||
// Hook to be called on every decompressed frame.
|
||||
virtual void DecompressedFrameHook(const vpx_image_t & /*img*/,
|
||||
virtual void DecompressedFrameHook(const vpx_image_t& /*img*/,
|
||||
vpx_codec_pts_t /*pts*/) {}
|
||||
|
||||
// Hook to be called to handle decode result. Return true to continue.
|
||||
virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
|
||||
const VideoSource & /*video*/,
|
||||
const VideoSource& /*video*/,
|
||||
Decoder *decoder) {
|
||||
EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
|
||||
return VPX_CODEC_OK == res_dec;
|
||||
@ -267,15 +262,15 @@ class EncoderTest {
|
||||
return pkt;
|
||||
}
|
||||
|
||||
bool abort_;
|
||||
vpx_codec_enc_cfg_t cfg_;
|
||||
vpx_codec_dec_cfg_t dec_cfg_;
|
||||
unsigned int passes_;
|
||||
unsigned long deadline_;
|
||||
TwopassStatsStore stats_;
|
||||
unsigned long init_flags_;
|
||||
unsigned long frame_flags_;
|
||||
vpx_codec_pts_t last_pts_;
|
||||
bool abort_;
|
||||
vpx_codec_enc_cfg_t cfg_;
|
||||
vpx_codec_dec_cfg_t dec_cfg_;
|
||||
unsigned int passes_;
|
||||
unsigned long deadline_;
|
||||
TwopassStatsStore stats_;
|
||||
unsigned long init_flags_;
|
||||
unsigned long frame_flags_;
|
||||
vpx_codec_pts_t last_pts_;
|
||||
};
|
||||
|
||||
} // namespace libvpx_test
|
||||
|
@ -19,13 +19,16 @@ namespace {
|
||||
const int kMaxErrorFrames = 12;
|
||||
const int kMaxDroppableFrames = 12;
|
||||
|
||||
class ErrorResilienceTestLarge
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> {
|
||||
class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> {
|
||||
protected:
|
||||
ErrorResilienceTestLarge()
|
||||
: EncoderTest(GET_PARAM(0)), svc_support_(GET_PARAM(2)), psnr_(0.0),
|
||||
nframes_(0), mismatch_psnr_(0.0), mismatch_nframes_(0),
|
||||
: EncoderTest(GET_PARAM(0)),
|
||||
svc_support_(GET_PARAM(2)),
|
||||
psnr_(0.0),
|
||||
nframes_(0),
|
||||
mismatch_psnr_(0.0),
|
||||
mismatch_nframes_(0),
|
||||
encoding_mode_(GET_PARAM(1)) {
|
||||
Reset();
|
||||
}
|
||||
@ -63,69 +66,81 @@ class ErrorResilienceTestLarge
|
||||
// LAST is updated on base/layer 0, GOLDEN updated on layer 1.
|
||||
// Non-zero pattern_switch parameter means pattern will switch to
|
||||
// not using LAST for frame_num >= pattern_switch.
|
||||
int SetFrameFlags(int frame_num, int num_temp_layers, int pattern_switch) {
|
||||
int SetFrameFlags(int frame_num,
|
||||
int num_temp_layers,
|
||||
int pattern_switch) {
|
||||
int frame_flags = 0;
|
||||
if (num_temp_layers == 2) {
|
||||
if (frame_num % 2 == 0) {
|
||||
if (frame_num < pattern_switch || pattern_switch == 0) {
|
||||
// Layer 0: predict from LAST and ARF, update LAST.
|
||||
frame_flags =
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
if (frame_num % 2 == 0) {
|
||||
if (frame_num < pattern_switch || pattern_switch == 0) {
|
||||
// Layer 0: predict from LAST and ARF, update LAST.
|
||||
frame_flags = VP8_EFLAG_NO_REF_GF |
|
||||
VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
} else {
|
||||
// Layer 0: predict from GF and ARF, update GF.
|
||||
frame_flags = VP8_EFLAG_NO_REF_LAST |
|
||||
VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
}
|
||||
} else {
|
||||
// Layer 0: predict from GF and ARF, update GF.
|
||||
frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
if (frame_num < pattern_switch || pattern_switch == 0) {
|
||||
// Layer 1: predict from L, GF, and ARF, update GF.
|
||||
frame_flags = VP8_EFLAG_NO_UPD_ARF |
|
||||
VP8_EFLAG_NO_UPD_LAST;
|
||||
} else {
|
||||
// Layer 1: predict from GF and ARF, update GF.
|
||||
frame_flags = VP8_EFLAG_NO_REF_LAST |
|
||||
VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (frame_num < pattern_switch || pattern_switch == 0) {
|
||||
// Layer 1: predict from L, GF, and ARF, update GF.
|
||||
frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
} else {
|
||||
// Layer 1: predict from GF and ARF, update GF.
|
||||
frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
}
|
||||
}
|
||||
}
|
||||
return frame_flags;
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video) {
|
||||
frame_flags_ &=
|
||||
~(VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF);
|
||||
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder * /*encoder*/) {
|
||||
frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF);
|
||||
// For temporal layer case.
|
||||
if (cfg_.ts_number_layers > 1) {
|
||||
frame_flags_ =
|
||||
SetFrameFlags(video->frame(), cfg_.ts_number_layers, pattern_switch_);
|
||||
frame_flags_ = SetFrameFlags(video->frame(),
|
||||
cfg_.ts_number_layers,
|
||||
pattern_switch_);
|
||||
for (unsigned int i = 0; i < droppable_nframes_; ++i) {
|
||||
if (droppable_frames_[i] == video->frame()) {
|
||||
std::cout << "Encoding droppable frame: " << droppable_frames_[i]
|
||||
<< "\n";
|
||||
std::cout << "Encoding droppable frame: "
|
||||
<< droppable_frames_[i] << "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (droppable_nframes_ > 0 &&
|
||||
(cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
|
||||
for (unsigned int i = 0; i < droppable_nframes_; ++i) {
|
||||
if (droppable_frames_[i] == video->frame()) {
|
||||
std::cout << "Encoding droppable frame: " << droppable_frames_[i]
|
||||
<< "\n";
|
||||
frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (droppable_nframes_ > 0 &&
|
||||
(cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
|
||||
for (unsigned int i = 0; i < droppable_nframes_; ++i) {
|
||||
if (droppable_frames_[i] == video->frame()) {
|
||||
std::cout << "Encoding droppable frame: "
|
||||
<< droppable_frames_[i] << "\n";
|
||||
frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double GetAveragePsnr() const {
|
||||
if (nframes_) return psnr_ / nframes_;
|
||||
if (nframes_)
|
||||
return psnr_ / nframes_;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double GetAverageMismatchPsnr() const {
|
||||
if (mismatch_nframes_) return mismatch_psnr_ / mismatch_nframes_;
|
||||
if (mismatch_nframes_)
|
||||
return mismatch_psnr_ / mismatch_nframes_;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -143,7 +158,8 @@ class ErrorResilienceTestLarge
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) {
|
||||
virtual void MismatchHook(const vpx_image_t *img1,
|
||||
const vpx_image_t *img2) {
|
||||
double mismatch_psnr = compute_psnr(img1, img2);
|
||||
mismatch_psnr_ += mismatch_psnr;
|
||||
++mismatch_nframes_;
|
||||
@ -151,32 +167,32 @@ class ErrorResilienceTestLarge
|
||||
}
|
||||
|
||||
void SetErrorFrames(int num, unsigned int *list) {
|
||||
if (num > kMaxErrorFrames) {
|
||||
if (num > kMaxErrorFrames)
|
||||
num = kMaxErrorFrames;
|
||||
} else if (num < 0) {
|
||||
else if (num < 0)
|
||||
num = 0;
|
||||
}
|
||||
error_nframes_ = num;
|
||||
for (unsigned int i = 0; i < error_nframes_; ++i) {
|
||||
for (unsigned int i = 0; i < error_nframes_; ++i)
|
||||
error_frames_[i] = list[i];
|
||||
}
|
||||
}
|
||||
|
||||
void SetDroppableFrames(int num, unsigned int *list) {
|
||||
if (num > kMaxDroppableFrames) {
|
||||
if (num > kMaxDroppableFrames)
|
||||
num = kMaxDroppableFrames;
|
||||
} else if (num < 0) {
|
||||
else if (num < 0)
|
||||
num = 0;
|
||||
}
|
||||
droppable_nframes_ = num;
|
||||
for (unsigned int i = 0; i < droppable_nframes_; ++i) {
|
||||
for (unsigned int i = 0; i < droppable_nframes_; ++i)
|
||||
droppable_frames_[i] = list[i];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int GetMismatchFrames() { return mismatch_nframes_; }
|
||||
unsigned int GetMismatchFrames() {
|
||||
return mismatch_nframes_;
|
||||
}
|
||||
|
||||
void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; }
|
||||
void SetPatternSwitch(int frame_switch) {
|
||||
pattern_switch_ = frame_switch;
|
||||
}
|
||||
|
||||
bool svc_support_;
|
||||
|
||||
@ -249,14 +265,15 @@ TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
|
||||
// In addition to isolated loss/drop, add a long consecutive series
|
||||
// (of size 9) of dropped frames.
|
||||
unsigned int num_droppable_frames = 11;
|
||||
unsigned int droppable_frame_list[] = { 5, 16, 22, 23, 24, 25,
|
||||
26, 27, 28, 29, 30 };
|
||||
unsigned int droppable_frame_list[] = {5, 16, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30};
|
||||
SetDroppableFrames(num_droppable_frames, droppable_frame_list);
|
||||
SetErrorFrames(num_droppable_frames, droppable_frame_list);
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
// Test that no mismatches have been found
|
||||
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
|
||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
|
||||
std::cout << " Mismatch frames: "
|
||||
<< GetMismatchFrames() << "\n";
|
||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
||||
|
||||
// Reset previously set of error/droppable frames.
|
||||
Reset();
|
||||
@ -289,7 +306,8 @@ TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
|
||||
// layer, so successful decoding is expected.
|
||||
TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
|
||||
// This test doesn't run if SVC is not supported.
|
||||
if (!svc_support_) return;
|
||||
if (!svc_support_)
|
||||
return;
|
||||
|
||||
const vpx_rational timebase = { 33333333, 1000000000 };
|
||||
cfg_.g_timebase = timebase;
|
||||
@ -319,13 +337,14 @@ TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
|
||||
// The odd frames are the enhancement layer for 2 layer pattern, so set
|
||||
// those frames as droppable. Drop the last 7 frames.
|
||||
unsigned int num_droppable_frames = 7;
|
||||
unsigned int droppable_frame_list[] = { 27, 29, 31, 33, 35, 37, 39 };
|
||||
unsigned int droppable_frame_list[] = {27, 29, 31, 33, 35, 37, 39};
|
||||
SetDroppableFrames(num_droppable_frames, droppable_frame_list);
|
||||
SetErrorFrames(num_droppable_frames, droppable_frame_list);
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
// Test that no mismatches have been found
|
||||
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
|
||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
|
||||
std::cout << " Mismatch frames: "
|
||||
<< GetMismatchFrames() << "\n";
|
||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
||||
|
||||
// Reset previously set of error/droppable frames.
|
||||
Reset();
|
||||
@ -336,7 +355,8 @@ TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
|
||||
// sequence, the LAST ref is not used anymore.
|
||||
TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) {
|
||||
// This test doesn't run if SVC is not supported.
|
||||
if (!svc_support_) return;
|
||||
if (!svc_support_)
|
||||
return;
|
||||
|
||||
const vpx_rational timebase = { 33333333, 1000000000 };
|
||||
cfg_.g_timebase = timebase;
|
||||
@ -365,19 +385,20 @@ TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) {
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
// Test that no mismatches have been found
|
||||
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
|
||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
|
||||
std::cout << " Mismatch frames: "
|
||||
<< GetMismatchFrames() << "\n";
|
||||
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
||||
|
||||
// Reset previously set of error/droppable frames.
|
||||
Reset();
|
||||
}
|
||||
|
||||
class ErrorResilienceTestLargeCodecControls
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
class ErrorResilienceTestLargeCodecControls : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
protected:
|
||||
ErrorResilienceTestLargeCodecControls()
|
||||
: EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)) {
|
||||
: EncoderTest(GET_PARAM(0)),
|
||||
encoding_mode_(GET_PARAM(1)) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
@ -416,8 +437,8 @@ class ErrorResilienceTestLargeCodecControls
|
||||
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;
|
||||
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 |
|
||||
@ -430,9 +451,9 @@ class ErrorResilienceTestLargeCodecControls
|
||||
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
|
||||
} else if ((frame_num - 2) % 4 == 0) {
|
||||
// Layer 1: predict from L, G, update G.
|
||||
frame_flags =
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF;
|
||||
} else if ((frame_num - 1) % 2 == 0) {
|
||||
frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
|
||||
VP8_EFLAG_NO_REF_ARF;
|
||||
} else if ((frame_num - 1) % 2 == 0) {
|
||||
// Layer 2: predict from L, G, ARF; update ARG.
|
||||
frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
|
||||
}
|
||||
@ -446,7 +467,7 @@ class ErrorResilienceTestLargeCodecControls
|
||||
if (frame_num % 2 == 0) {
|
||||
layer_id = 0;
|
||||
} else {
|
||||
layer_id = 1;
|
||||
layer_id = 1;
|
||||
}
|
||||
} else if (num_temp_layers == 3) {
|
||||
if (frame_num % 4 == 0) {
|
||||
@ -463,16 +484,16 @@ class ErrorResilienceTestLargeCodecControls
|
||||
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
|
||||
libvpx_test::Encoder *encoder) {
|
||||
if (cfg_.ts_number_layers > 1) {
|
||||
int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
|
||||
int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
|
||||
if (video->frame() > 0) {
|
||||
encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
|
||||
encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
|
||||
}
|
||||
const vpx_rational_t tb = video->timebase();
|
||||
timebase_ = static_cast<double>(tb.num) / tb.den;
|
||||
duration_ = 0;
|
||||
return;
|
||||
int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
|
||||
int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
|
||||
if (video->frame() > 0) {
|
||||
encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
|
||||
encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
|
||||
}
|
||||
const vpx_rational_t tb = video->timebase();
|
||||
timebase_ = static_cast<double>(tb.num) / tb.den;
|
||||
duration_ = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,28 +519,26 @@ class ErrorResilienceTestLargeCodecControls
|
||||
|
||||
virtual void EndPassHook(void) {
|
||||
duration_ = (last_pts_ + 1) * timebase_;
|
||||
if (cfg_.ts_number_layers > 1) {
|
||||
if (cfg_.ts_number_layers > 1) {
|
||||
for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
|
||||
++layer) {
|
||||
++layer) {
|
||||
if (bits_total_[layer]) {
|
||||
// Effective file datarate:
|
||||
effective_datarate_[layer] =
|
||||
(bits_total_[layer] / 1000.0) / duration_;
|
||||
effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double effective_datarate_[3];
|
||||
|
||||
private:
|
||||
libvpx_test::TestMode encoding_mode_;
|
||||
vpx_codec_pts_t last_pts_;
|
||||
double timebase_;
|
||||
int64_t bits_total_[3];
|
||||
double duration_;
|
||||
int tot_frame_number_;
|
||||
};
|
||||
private:
|
||||
libvpx_test::TestMode encoding_mode_;
|
||||
vpx_codec_pts_t last_pts_;
|
||||
double timebase_;
|
||||
int64_t bits_total_[3];
|
||||
double duration_;
|
||||
int tot_frame_number_;
|
||||
};
|
||||
|
||||
// Check two codec controls used for:
|
||||
// (1) for setting temporal layer id, and (2) for settings encoder flags.
|
||||
@ -563,12 +582,10 @@ TEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) {
|
||||
for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
|
||||
ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
|
||||
<< " The datarate for the file is lower than target by too much, "
|
||||
"for layer: "
|
||||
<< j;
|
||||
"for layer: " << j;
|
||||
ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
|
||||
<< " The datarate for the file is greater than target by too much, "
|
||||
"for layer: "
|
||||
<< j;
|
||||
"for layer: " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -579,4 +596,7 @@ VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLargeCodecControls,
|
||||
ONE_PASS_TEST_MODES);
|
||||
VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
|
||||
::testing::Values(true));
|
||||
// SVC-related tests don't run for VP10 since SVC is not supported.
|
||||
VP10_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
|
||||
::testing::Values(false));
|
||||
} // namespace
|
||||
|
@ -15,7 +15,7 @@
|
||||
example_tests=$(ls $(dirname $0)/*.sh)
|
||||
|
||||
# List of script names to exclude.
|
||||
exclude_list="examples stress tools_common"
|
||||
exclude_list="examples tools_common"
|
||||
|
||||
# Filter out the scripts in $exclude_list.
|
||||
for word in ${exclude_list}; do
|
||||
|
@ -35,18 +35,20 @@ struct ExternalFrameBuffer {
|
||||
class ExternalFrameBufferList {
|
||||
public:
|
||||
ExternalFrameBufferList()
|
||||
: num_buffers_(0), num_used_buffers_(0), ext_fb_list_(NULL) {}
|
||||
: num_buffers_(0),
|
||||
ext_fb_list_(NULL) {}
|
||||
|
||||
virtual ~ExternalFrameBufferList() {
|
||||
for (int i = 0; i < num_buffers_; ++i) {
|
||||
delete[] ext_fb_list_[i].data;
|
||||
delete [] ext_fb_list_[i].data;
|
||||
}
|
||||
delete[] ext_fb_list_;
|
||||
delete [] ext_fb_list_;
|
||||
}
|
||||
|
||||
// Creates the list to hold the external buffers. Returns true on success.
|
||||
bool CreateBufferList(int num_buffers) {
|
||||
if (num_buffers < 0) return false;
|
||||
if (num_buffers < 0)
|
||||
return false;
|
||||
|
||||
num_buffers_ = num_buffers;
|
||||
ext_fb_list_ = new ExternalFrameBuffer[num_buffers_];
|
||||
@ -62,18 +64,17 @@ class ExternalFrameBufferList {
|
||||
int GetFreeFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
|
||||
EXPECT_TRUE(fb != NULL);
|
||||
const int idx = FindFreeBufferIndex();
|
||||
if (idx == num_buffers_) return -1;
|
||||
if (idx == num_buffers_)
|
||||
return -1;
|
||||
|
||||
if (ext_fb_list_[idx].size < min_size) {
|
||||
delete[] ext_fb_list_[idx].data;
|
||||
delete [] ext_fb_list_[idx].data;
|
||||
ext_fb_list_[idx].data = new uint8_t[min_size];
|
||||
memset(ext_fb_list_[idx].data, 0, min_size);
|
||||
ext_fb_list_[idx].size = min_size;
|
||||
}
|
||||
|
||||
SetFrameBuffer(idx, fb);
|
||||
|
||||
num_used_buffers_++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -82,10 +83,11 @@ class ExternalFrameBufferList {
|
||||
int GetZeroFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
|
||||
EXPECT_TRUE(fb != NULL);
|
||||
const int idx = FindFreeBufferIndex();
|
||||
if (idx == num_buffers_) return -1;
|
||||
if (idx == num_buffers_)
|
||||
return -1;
|
||||
|
||||
if (ext_fb_list_[idx].size < min_size) {
|
||||
delete[] ext_fb_list_[idx].data;
|
||||
delete [] ext_fb_list_[idx].data;
|
||||
ext_fb_list_[idx].data = NULL;
|
||||
ext_fb_list_[idx].size = min_size;
|
||||
}
|
||||
@ -102,14 +104,13 @@ class ExternalFrameBufferList {
|
||||
return -1;
|
||||
}
|
||||
ExternalFrameBuffer *const ext_fb =
|
||||
reinterpret_cast<ExternalFrameBuffer *>(fb->priv);
|
||||
reinterpret_cast<ExternalFrameBuffer*>(fb->priv);
|
||||
if (ext_fb == NULL) {
|
||||
EXPECT_TRUE(ext_fb != NULL);
|
||||
return -1;
|
||||
}
|
||||
EXPECT_EQ(1, ext_fb->in_use);
|
||||
ext_fb->in_use = 0;
|
||||
num_used_buffers_--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -118,15 +119,13 @@ class ExternalFrameBufferList {
|
||||
void CheckXImageFrameBuffer(const vpx_image_t *img) {
|
||||
if (img->fb_priv != NULL) {
|
||||
const struct ExternalFrameBuffer *const ext_fb =
|
||||
reinterpret_cast<ExternalFrameBuffer *>(img->fb_priv);
|
||||
reinterpret_cast<ExternalFrameBuffer*>(img->fb_priv);
|
||||
|
||||
ASSERT_TRUE(img->planes[0] >= ext_fb->data &&
|
||||
img->planes[0] < (ext_fb->data + ext_fb->size));
|
||||
}
|
||||
}
|
||||
|
||||
int num_used_buffers() const { return num_used_buffers_; }
|
||||
|
||||
private:
|
||||
// Returns the index of the first free frame buffer. Returns |num_buffers_|
|
||||
// if there are no free frame buffers.
|
||||
@ -134,7 +133,8 @@ class ExternalFrameBufferList {
|
||||
int i;
|
||||
// Find a free frame buffer.
|
||||
for (i = 0; i < num_buffers_; ++i) {
|
||||
if (!ext_fb_list_[i].in_use) break;
|
||||
if (!ext_fb_list_[i].in_use)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@ -151,7 +151,6 @@ class ExternalFrameBufferList {
|
||||
}
|
||||
|
||||
int num_buffers_;
|
||||
int num_used_buffers_;
|
||||
ExternalFrameBuffer *ext_fb_list_;
|
||||
};
|
||||
|
||||
@ -162,15 +161,16 @@ class ExternalFrameBufferList {
|
||||
int get_vp9_frame_buffer(void *user_priv, size_t min_size,
|
||||
vpx_codec_frame_buffer_t *fb) {
|
||||
ExternalFrameBufferList *const fb_list =
|
||||
reinterpret_cast<ExternalFrameBufferList *>(user_priv);
|
||||
reinterpret_cast<ExternalFrameBufferList*>(user_priv);
|
||||
return fb_list->GetFreeFrameBuffer(min_size, fb);
|
||||
}
|
||||
|
||||
// Callback used by libvpx to tell the application that |fb| is not needed
|
||||
// anymore.
|
||||
int release_vp9_frame_buffer(void *user_priv, vpx_codec_frame_buffer_t *fb) {
|
||||
int release_vp9_frame_buffer(void *user_priv,
|
||||
vpx_codec_frame_buffer_t *fb) {
|
||||
ExternalFrameBufferList *const fb_list =
|
||||
reinterpret_cast<ExternalFrameBufferList *>(user_priv);
|
||||
reinterpret_cast<ExternalFrameBufferList*>(user_priv);
|
||||
return fb_list->ReturnFrameBuffer(fb);
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ int release_vp9_frame_buffer(void *user_priv, vpx_codec_frame_buffer_t *fb) {
|
||||
int get_vp9_zero_frame_buffer(void *user_priv, size_t min_size,
|
||||
vpx_codec_frame_buffer_t *fb) {
|
||||
ExternalFrameBufferList *const fb_list =
|
||||
reinterpret_cast<ExternalFrameBufferList *>(user_priv);
|
||||
reinterpret_cast<ExternalFrameBufferList*>(user_priv);
|
||||
return fb_list->GetZeroFrameBuffer(min_size, fb);
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ int get_vp9_zero_frame_buffer(void *user_priv, size_t min_size,
|
||||
int get_vp9_one_less_byte_frame_buffer(void *user_priv, size_t min_size,
|
||||
vpx_codec_frame_buffer_t *fb) {
|
||||
ExternalFrameBufferList *const fb_list =
|
||||
reinterpret_cast<ExternalFrameBufferList *>(user_priv);
|
||||
reinterpret_cast<ExternalFrameBufferList*>(user_priv);
|
||||
return fb_list->GetFreeFrameBuffer(min_size - 1, fb);
|
||||
}
|
||||
|
||||
@ -203,14 +203,16 @@ int do_not_release_vp9_frame_buffer(void *user_priv,
|
||||
// Class for testing passing in external frame buffers to libvpx.
|
||||
class ExternalFrameBufferMD5Test
|
||||
: public ::libvpx_test::DecoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<const char *> {
|
||||
public ::libvpx_test::CodecTestWithParam<const char*> {
|
||||
protected:
|
||||
ExternalFrameBufferMD5Test()
|
||||
: DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)),
|
||||
md5_file_(NULL), num_buffers_(0) {}
|
||||
md5_file_(NULL),
|
||||
num_buffers_(0) {}
|
||||
|
||||
virtual ~ExternalFrameBufferMD5Test() {
|
||||
if (md5_file_ != NULL) fclose(md5_file_);
|
||||
if (md5_file_ != NULL)
|
||||
fclose(md5_file_);
|
||||
}
|
||||
|
||||
virtual void PreDecodeFrameHook(
|
||||
@ -220,15 +222,15 @@ class ExternalFrameBufferMD5Test
|
||||
// Have libvpx use frame buffers we create.
|
||||
ASSERT_TRUE(fb_list_.CreateBufferList(num_buffers_));
|
||||
ASSERT_EQ(VPX_CODEC_OK,
|
||||
decoder->SetFrameBufferFunctions(GetVP9FrameBuffer,
|
||||
ReleaseVP9FrameBuffer, this));
|
||||
decoder->SetFrameBufferFunctions(
|
||||
GetVP9FrameBuffer, ReleaseVP9FrameBuffer, this));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenMD5File(const std::string &md5_file_name_) {
|
||||
md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
|
||||
ASSERT_TRUE(md5_file_ != NULL)
|
||||
<< "Md5 file open failed. Filename: " << md5_file_name_;
|
||||
ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: "
|
||||
<< md5_file_name_;
|
||||
}
|
||||
|
||||
virtual void DecompressedFrameHook(const vpx_image_t &img,
|
||||
@ -256,7 +258,7 @@ class ExternalFrameBufferMD5Test
|
||||
static int GetVP9FrameBuffer(void *user_priv, size_t min_size,
|
||||
vpx_codec_frame_buffer_t *fb) {
|
||||
ExternalFrameBufferMD5Test *const md5Test =
|
||||
reinterpret_cast<ExternalFrameBufferMD5Test *>(user_priv);
|
||||
reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
|
||||
return md5Test->fb_list_.GetFreeFrameBuffer(min_size, fb);
|
||||
}
|
||||
|
||||
@ -265,7 +267,7 @@ class ExternalFrameBufferMD5Test
|
||||
static int ReleaseVP9FrameBuffer(void *user_priv,
|
||||
vpx_codec_frame_buffer_t *fb) {
|
||||
ExternalFrameBufferMD5Test *const md5Test =
|
||||
reinterpret_cast<ExternalFrameBufferMD5Test *>(user_priv);
|
||||
reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
|
||||
return md5Test->fb_list_.ReturnFrameBuffer(fb);
|
||||
}
|
||||
|
||||
@ -280,12 +282,14 @@ class ExternalFrameBufferMD5Test
|
||||
|
||||
#if CONFIG_WEBM_IO
|
||||
const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
|
||||
const char kVP9NonRefTestFile[] = "vp90-2-22-svc_1280x720_1.webm";
|
||||
|
||||
// Class for testing passing in external frame buffers to libvpx.
|
||||
class ExternalFrameBufferTest : public ::testing::Test {
|
||||
protected:
|
||||
ExternalFrameBufferTest() : video_(NULL), decoder_(NULL), num_buffers_(0) {}
|
||||
ExternalFrameBufferTest()
|
||||
: video_(NULL),
|
||||
decoder_(NULL),
|
||||
num_buffers_(0) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
|
||||
@ -300,14 +304,13 @@ class ExternalFrameBufferTest : public ::testing::Test {
|
||||
|
||||
virtual void TearDown() {
|
||||
delete decoder_;
|
||||
decoder_ = NULL;
|
||||
delete video_;
|
||||
video_ = NULL;
|
||||
}
|
||||
|
||||
// Passes the external frame buffer information to libvpx.
|
||||
vpx_codec_err_t SetFrameBufferFunctions(
|
||||
int num_buffers, vpx_get_frame_buffer_cb_fn_t cb_get,
|
||||
int num_buffers,
|
||||
vpx_get_frame_buffer_cb_fn_t cb_get,
|
||||
vpx_release_frame_buffer_cb_fn_t cb_release) {
|
||||
if (num_buffers > 0) {
|
||||
num_buffers_ = num_buffers;
|
||||
@ -321,7 +324,8 @@ class ExternalFrameBufferTest : public ::testing::Test {
|
||||
const vpx_codec_err_t res =
|
||||
decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
|
||||
CheckDecodedFrames();
|
||||
if (res == VPX_CODEC_OK) video_->Next();
|
||||
if (res == VPX_CODEC_OK)
|
||||
video_->Next();
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -329,13 +333,14 @@ class ExternalFrameBufferTest : public ::testing::Test {
|
||||
for (; video_->cxdata() != NULL; video_->Next()) {
|
||||
const vpx_codec_err_t res =
|
||||
decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
|
||||
if (res != VPX_CODEC_OK) return res;
|
||||
if (res != VPX_CODEC_OK)
|
||||
return res;
|
||||
CheckDecodedFrames();
|
||||
}
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
void CheckDecodedFrames() {
|
||||
libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
|
||||
const vpx_image_t *img = NULL;
|
||||
@ -351,25 +356,6 @@ class ExternalFrameBufferTest : public ::testing::Test {
|
||||
int num_buffers_;
|
||||
ExternalFrameBufferList fb_list_;
|
||||
};
|
||||
|
||||
class ExternalFrameBufferNonRefTest : public ExternalFrameBufferTest {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
video_ = new libvpx_test::WebMVideoSource(kVP9NonRefTestFile);
|
||||
ASSERT_TRUE(video_ != NULL);
|
||||
video_->Init();
|
||||
video_->Begin();
|
||||
|
||||
vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
|
||||
decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
|
||||
ASSERT_TRUE(decoder_ != NULL);
|
||||
}
|
||||
|
||||
virtual void CheckFrameBufferRelease() {
|
||||
TearDown();
|
||||
ASSERT_EQ(0, fb_list_.num_used_buffers());
|
||||
}
|
||||
};
|
||||
#endif // CONFIG_WEBM_IO
|
||||
|
||||
// This test runs through the set of test vectors, and decodes them.
|
||||
@ -379,6 +365,7 @@ class ExternalFrameBufferNonRefTest : public ExternalFrameBufferTest {
|
||||
// Otherwise, the test failed.
|
||||
TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
|
||||
const std::string filename = GET_PARAM(kVideoNameParam);
|
||||
libvpx_test::CompressedVideoSource *video = NULL;
|
||||
|
||||
// Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
|
||||
// #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
|
||||
@ -393,19 +380,18 @@ TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
|
||||
#endif
|
||||
|
||||
// Open compressed video file.
|
||||
testing::internal::scoped_ptr<libvpx_test::CompressedVideoSource> video;
|
||||
if (filename.substr(filename.length() - 3, 3) == "ivf") {
|
||||
video.reset(new libvpx_test::IVFVideoSource(filename));
|
||||
video = new libvpx_test::IVFVideoSource(filename);
|
||||
} else {
|
||||
#if CONFIG_WEBM_IO
|
||||
video.reset(new libvpx_test::WebMVideoSource(filename));
|
||||
video = new libvpx_test::WebMVideoSource(filename);
|
||||
#else
|
||||
fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
|
||||
filename.c_str());
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
ASSERT_TRUE(video.get() != NULL);
|
||||
ASSERT_TRUE(video != NULL);
|
||||
video->Init();
|
||||
|
||||
// Construct md5 file name.
|
||||
@ -413,7 +399,8 @@ TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
|
||||
OpenMD5File(md5_filename);
|
||||
|
||||
// Decode frame, and check the md5 matching.
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video));
|
||||
delete video;
|
||||
}
|
||||
|
||||
#if CONFIG_WEBM_IO
|
||||
@ -422,8 +409,8 @@ TEST_F(ExternalFrameBufferTest, MinFrameBuffers) {
|
||||
// #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS.
|
||||
const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
|
||||
ASSERT_EQ(VPX_CODEC_OK,
|
||||
SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
|
||||
release_vp9_frame_buffer));
|
||||
SetFrameBufferFunctions(
|
||||
num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
|
||||
ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
|
||||
}
|
||||
|
||||
@ -434,8 +421,8 @@ TEST_F(ExternalFrameBufferTest, EightJitterBuffers) {
|
||||
const int num_buffers =
|
||||
VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
|
||||
ASSERT_EQ(VPX_CODEC_OK,
|
||||
SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
|
||||
release_vp9_frame_buffer));
|
||||
SetFrameBufferFunctions(
|
||||
num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
|
||||
ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
|
||||
}
|
||||
|
||||
@ -445,11 +432,9 @@ TEST_F(ExternalFrameBufferTest, NotEnoughBuffers) {
|
||||
// only use 5 frame buffers at one time.
|
||||
const int num_buffers = 2;
|
||||
ASSERT_EQ(VPX_CODEC_OK,
|
||||
SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
|
||||
release_vp9_frame_buffer));
|
||||
SetFrameBufferFunctions(
|
||||
num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
|
||||
ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
|
||||
// Only run this on long clips. Decoding a very short clip will return
|
||||
// VPX_CODEC_OK even with only 2 buffers.
|
||||
ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
|
||||
}
|
||||
|
||||
@ -472,17 +457,18 @@ TEST_F(ExternalFrameBufferTest, NullRealloc) {
|
||||
|
||||
TEST_F(ExternalFrameBufferTest, ReallocOneLessByte) {
|
||||
const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
|
||||
ASSERT_EQ(VPX_CODEC_OK, SetFrameBufferFunctions(
|
||||
num_buffers, get_vp9_one_less_byte_frame_buffer,
|
||||
release_vp9_frame_buffer));
|
||||
ASSERT_EQ(VPX_CODEC_OK,
|
||||
SetFrameBufferFunctions(
|
||||
num_buffers, get_vp9_one_less_byte_frame_buffer,
|
||||
release_vp9_frame_buffer));
|
||||
ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
|
||||
}
|
||||
|
||||
TEST_F(ExternalFrameBufferTest, NullGetFunction) {
|
||||
const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
|
||||
ASSERT_EQ(
|
||||
VPX_CODEC_INVALID_PARAM,
|
||||
SetFrameBufferFunctions(num_buffers, NULL, release_vp9_frame_buffer));
|
||||
ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
|
||||
SetFrameBufferFunctions(num_buffers, NULL,
|
||||
release_vp9_frame_buffer));
|
||||
}
|
||||
|
||||
TEST_F(ExternalFrameBufferTest, NullReleaseFunction) {
|
||||
@ -495,23 +481,13 @@ TEST_F(ExternalFrameBufferTest, SetAfterDecode) {
|
||||
const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
|
||||
ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
|
||||
ASSERT_EQ(VPX_CODEC_ERROR,
|
||||
SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
|
||||
release_vp9_frame_buffer));
|
||||
}
|
||||
|
||||
TEST_F(ExternalFrameBufferNonRefTest, ReleaseNonRefFrameBuffer) {
|
||||
const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
|
||||
ASSERT_EQ(VPX_CODEC_OK,
|
||||
SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
|
||||
release_vp9_frame_buffer));
|
||||
ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
|
||||
CheckFrameBufferRelease();
|
||||
SetFrameBufferFunctions(
|
||||
num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
|
||||
}
|
||||
#endif // CONFIG_WEBM_IO
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(
|
||||
ExternalFrameBufferMD5Test,
|
||||
::testing::ValuesIn(libvpx_test::kVP9TestVectors,
|
||||
libvpx_test::kVP9TestVectors +
|
||||
libvpx_test::kNumVP9TestVectors));
|
||||
VP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test,
|
||||
::testing::ValuesIn(libvpx_test::kVP9TestVectors,
|
||||
libvpx_test::kVP9TestVectors +
|
||||
libvpx_test::kNumVP9TestVectors));
|
||||
} // namespace
|
||||
|
554
test/fdct4x4_test.cc
Normal file
554
test/fdct4x4_test.cc
Normal file
@ -0,0 +1,554 @@
|
||||
/*
|
||||
* 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 <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vp9_rtcd.h"
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "test/acm_random.h"
|
||||
#include "test/clear_system_state.h"
|
||||
#include "test/register_state_check.h"
|
||||
#include "test/util.h"
|
||||
#include "vp9/common/vp9_entropy.h"
|
||||
#include "vpx/vpx_codec.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_ports/mem.h"
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
namespace {
|
||||
const int kNumCoeffs = 16;
|
||||
typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
|
||||
typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
|
||||
typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
|
||||
int tx_type);
|
||||
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
|
||||
int tx_type);
|
||||
|
||||
typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct4x4Param;
|
||||
typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht4x4Param;
|
||||
|
||||
void fdct4x4_ref(const int16_t *in, tran_low_t *out, int stride,
|
||||
int /*tx_type*/) {
|
||||
vpx_fdct4x4_c(in, out, stride);
|
||||
}
|
||||
|
||||
void fht4x4_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
|
||||
vp9_fht4x4_c(in, out, stride, tx_type);
|
||||
}
|
||||
|
||||
void fwht4x4_ref(const int16_t *in, tran_low_t *out, int stride,
|
||||
int /*tx_type*/) {
|
||||
vp9_fwht4x4_c(in, out, stride);
|
||||
}
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
void idct4x4_10(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct4x4_16_add_c(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct4x4_12(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct4x4_16_add_c(in, out, stride, 12);
|
||||
}
|
||||
|
||||
void iht4x4_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
|
||||
vp9_highbd_iht4x4_16_add_c(in, out, stride, tx_type, 10);
|
||||
}
|
||||
|
||||
void iht4x4_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
|
||||
vp9_highbd_iht4x4_16_add_c(in, out, stride, tx_type, 12);
|
||||
}
|
||||
|
||||
void iwht4x4_10(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_iwht4x4_16_add_c(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void iwht4x4_12(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_iwht4x4_16_add_c(in, out, stride, 12);
|
||||
}
|
||||
|
||||
#if HAVE_SSE2
|
||||
void idct4x4_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct4x4_16_add_sse2(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct4x4_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct4x4_16_add_sse2(in, out, stride, 12);
|
||||
}
|
||||
#endif // HAVE_SSE2
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
class Trans4x4TestBase {
|
||||
public:
|
||||
virtual ~Trans4x4TestBase() {}
|
||||
|
||||
protected:
|
||||
virtual void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) = 0;
|
||||
|
||||
virtual void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) = 0;
|
||||
|
||||
void RunAccuracyCheck(int limit) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
uint32_t max_error = 0;
|
||||
int64_t total_error = 0;
|
||||
const int count_test_block = 10000;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
|
||||
#endif
|
||||
|
||||
// Initialize a test block with input range [-255, 255].
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
src[j] = rnd.Rand8();
|
||||
dst[j] = rnd.Rand8();
|
||||
test_input_block[j] = src[j] - dst[j];
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
src16[j] = rnd.Rand16() & mask_;
|
||||
dst16[j] = rnd.Rand16() & mask_;
|
||||
test_input_block[j] = src16[j] - dst16[j];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
|
||||
test_temp_block, pitch_));
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block,
|
||||
CONVERT_TO_BYTEPTR(dst16), pitch_));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const uint32_t diff =
|
||||
bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
|
||||
#else
|
||||
ASSERT_EQ(VPX_BITS_8, bit_depth_);
|
||||
const uint32_t diff = dst[j] - src[j];
|
||||
#endif
|
||||
const uint32_t error = diff * diff;
|
||||
if (max_error < error)
|
||||
max_error = error;
|
||||
total_error += error;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_GE(static_cast<uint32_t>(limit), max_error)
|
||||
<< "Error: 4x4 FHT/IHT has an individual round trip error > "
|
||||
<< limit;
|
||||
|
||||
EXPECT_GE(count_test_block * limit, total_error)
|
||||
<< "Error: 4x4 FHT/IHT has average round trip error > " << limit
|
||||
<< " per block";
|
||||
}
|
||||
|
||||
void RunCoeffCheck() {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = 5000;
|
||||
DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with input range [-mask_, mask_].
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
|
||||
|
||||
fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
|
||||
|
||||
// The minimum quant value is 4.
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
EXPECT_EQ(output_block[j], output_ref_block[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void RunMemCheck() {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = 5000;
|
||||
DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with input range [-mask_, mask_].
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
|
||||
}
|
||||
if (i == 0) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = mask_;
|
||||
} else if (i == 1) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
input_extreme_block[j] = -mask_;
|
||||
}
|
||||
|
||||
fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
|
||||
ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
|
||||
output_block, pitch_));
|
||||
|
||||
// The minimum quant value is 4.
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
EXPECT_EQ(output_block[j], output_ref_block[j]);
|
||||
EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j]))
|
||||
<< "Error: 4x4 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunInvAccuracyCheck(int limit) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = 1000;
|
||||
DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with input range [-mask_, mask_].
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
src[j] = rnd.Rand8();
|
||||
dst[j] = rnd.Rand8();
|
||||
in[j] = src[j] - dst[j];
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
src16[j] = rnd.Rand16() & mask_;
|
||||
dst16[j] = rnd.Rand16() & mask_;
|
||||
in[j] = src16[j] - dst16[j];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
fwd_txfm_ref(in, coeff, pitch_, tx_type_);
|
||||
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
|
||||
pitch_));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const uint32_t diff =
|
||||
bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
|
||||
#else
|
||||
const uint32_t diff = dst[j] - src[j];
|
||||
#endif
|
||||
const uint32_t error = diff * diff;
|
||||
EXPECT_GE(static_cast<uint32_t>(limit), error)
|
||||
<< "Error: 4x4 IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pitch_;
|
||||
int tx_type_;
|
||||
FhtFunc fwd_txfm_ref;
|
||||
vpx_bit_depth_t bit_depth_;
|
||||
int mask_;
|
||||
};
|
||||
|
||||
class Trans4x4DCT
|
||||
: public Trans4x4TestBase,
|
||||
public ::testing::TestWithParam<Dct4x4Param> {
|
||||
public:
|
||||
virtual ~Trans4x4DCT() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
pitch_ = 4;
|
||||
fwd_txfm_ref = fdct4x4_ref;
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
|
||||
fwd_txfm_(in, out, stride);
|
||||
}
|
||||
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
|
||||
inv_txfm_(out, dst, stride);
|
||||
}
|
||||
|
||||
FdctFunc fwd_txfm_;
|
||||
IdctFunc inv_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(Trans4x4DCT, AccuracyCheck) {
|
||||
RunAccuracyCheck(1);
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4DCT, CoeffCheck) {
|
||||
RunCoeffCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4DCT, MemCheck) {
|
||||
RunMemCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4DCT, InvAccuracyCheck) {
|
||||
RunInvAccuracyCheck(1);
|
||||
}
|
||||
|
||||
class Trans4x4HT
|
||||
: public Trans4x4TestBase,
|
||||
public ::testing::TestWithParam<Ht4x4Param> {
|
||||
public:
|
||||
virtual ~Trans4x4HT() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
pitch_ = 4;
|
||||
fwd_txfm_ref = fht4x4_ref;
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
|
||||
fwd_txfm_(in, out, stride, tx_type_);
|
||||
}
|
||||
|
||||
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
|
||||
inv_txfm_(out, dst, stride, tx_type_);
|
||||
}
|
||||
|
||||
FhtFunc fwd_txfm_;
|
||||
IhtFunc inv_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(Trans4x4HT, AccuracyCheck) {
|
||||
RunAccuracyCheck(1);
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4HT, CoeffCheck) {
|
||||
RunCoeffCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4HT, MemCheck) {
|
||||
RunMemCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4HT, InvAccuracyCheck) {
|
||||
RunInvAccuracyCheck(1);
|
||||
}
|
||||
|
||||
class Trans4x4WHT
|
||||
: public Trans4x4TestBase,
|
||||
public ::testing::TestWithParam<Dct4x4Param> {
|
||||
public:
|
||||
virtual ~Trans4x4WHT() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
pitch_ = 4;
|
||||
fwd_txfm_ref = fwht4x4_ref;
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
|
||||
fwd_txfm_(in, out, stride);
|
||||
}
|
||||
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
|
||||
inv_txfm_(out, dst, stride);
|
||||
}
|
||||
|
||||
FdctFunc fwd_txfm_;
|
||||
IdctFunc inv_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(Trans4x4WHT, AccuracyCheck) {
|
||||
RunAccuracyCheck(0);
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4WHT, CoeffCheck) {
|
||||
RunCoeffCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4WHT, MemCheck) {
|
||||
RunMemCheck();
|
||||
}
|
||||
|
||||
TEST_P(Trans4x4WHT, InvAccuracyCheck) {
|
||||
RunInvAccuracyCheck(0);
|
||||
}
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans4x4DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 0, VPX_BITS_8)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans4x4DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 0, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans4x4HT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 1, VPX_BITS_10),
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 2, VPX_BITS_10),
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 3, VPX_BITS_10),
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 1, VPX_BITS_12),
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 2, VPX_BITS_12),
|
||||
make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 3, VPX_BITS_12),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans4x4HT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans4x4WHT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_12, 0, VPX_BITS_12),
|
||||
make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, Trans4x4WHT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Trans4x4DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct4x4_c,
|
||||
&vpx_idct4x4_16_add_neon, 0, VPX_BITS_8)));
|
||||
#endif // HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Trans4x4HT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 0, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 3, VPX_BITS_8)));
|
||||
#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if CONFIG_USE_X86INC && HAVE_MMX && !CONFIG_VP9_HIGHBITDEPTH && \
|
||||
!CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MMX, Trans4x4WHT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fwht4x4_mmx, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8)));
|
||||
#endif
|
||||
|
||||
#if CONFIG_USE_X86INC && HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && \
|
||||
!CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans4x4WHT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_sse2, 0, VPX_BITS_8)));
|
||||
#endif
|
||||
|
||||
#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans4x4DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct4x4_sse2,
|
||||
&vpx_idct4x4_16_add_sse2, 0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans4x4HT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 0, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 3, VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans4x4DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_10_sse2, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_10_sse2, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_12_sse2, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_12_sse2, 0, VPX_BITS_12),
|
||||
make_tuple(&vpx_fdct4x4_sse2, &vpx_idct4x4_16_add_c, 0,
|
||||
VPX_BITS_8)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Trans4x4HT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8)));
|
||||
#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Trans4x4DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct4x4_msa, &vpx_idct4x4_16_add_msa, 0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Trans4x4HT,
|
||||
::testing::Values(
|
||||
make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 0, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 3, VPX_BITS_8)));
|
||||
#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
} // namespace
|
@ -43,18 +43,18 @@ 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,
|
||||
int tx_type);
|
||||
|
||||
typedef ::testing::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param;
|
||||
typedef ::testing::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param;
|
||||
typedef ::testing::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct8x8Param;
|
||||
typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param;
|
||||
typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param;
|
||||
typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct8x8Param;
|
||||
|
||||
void reference_8x8_dct_1d(const double in[8], double out[8]) {
|
||||
const double kInvSqrt2 = 0.707106781186547524400844362104;
|
||||
for (int k = 0; k < 8; k++) {
|
||||
out[k] = 0.0;
|
||||
for (int n = 0; n < 8; n++) {
|
||||
for (int n = 0; n < 8; n++)
|
||||
out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 16.0);
|
||||
}
|
||||
if (k == 0) out[k] = out[k] * kInvSqrt2;
|
||||
if (k == 0)
|
||||
out[k] = out[k] * kInvSqrt2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,20 +63,25 @@ void reference_8x8_dct_2d(const int16_t input[kNumCoeffs],
|
||||
// First transform columns
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
double temp_in[8], temp_out[8];
|
||||
for (int j = 0; j < 8; ++j) temp_in[j] = input[j * 8 + i];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
temp_in[j] = input[j*8 + i];
|
||||
reference_8x8_dct_1d(temp_in, temp_out);
|
||||
for (int j = 0; j < 8; ++j) output[j * 8 + i] = temp_out[j];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
output[j * 8 + i] = temp_out[j];
|
||||
}
|
||||
// Then transform rows
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
double temp_in[8], temp_out[8];
|
||||
for (int j = 0; j < 8; ++j) temp_in[j] = output[j + i * 8];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
temp_in[j] = output[j + i*8];
|
||||
reference_8x8_dct_1d(temp_in, temp_out);
|
||||
// Scale by some magic number
|
||||
for (int j = 0; j < 8; ++j) output[j + i * 8] = temp_out[j] * 2;
|
||||
for (int j = 0; j < 8; ++j)
|
||||
output[j + i * 8] = temp_out[j] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fdct8x8_ref(const int16_t *in, tran_low_t *out, int stride,
|
||||
int /*tx_type*/) {
|
||||
vpx_fdct8x8_c(in, out, stride);
|
||||
@ -88,45 +93,45 @@ void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
void idct8x8_10(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
vpx_highbd_idct8x8_64_add_c(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct8x8_12(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
vpx_highbd_idct8x8_64_add_c(in, out, stride, 12);
|
||||
}
|
||||
|
||||
void iht8x8_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
|
||||
vp9_highbd_iht8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 10);
|
||||
vp9_highbd_iht8x8_64_add_c(in, out, stride, tx_type, 10);
|
||||
}
|
||||
|
||||
void iht8x8_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
|
||||
vp9_highbd_iht8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 12);
|
||||
vp9_highbd_iht8x8_64_add_c(in, out, stride, tx_type, 12);
|
||||
}
|
||||
|
||||
#if HAVE_SSE2
|
||||
|
||||
void idct8x8_12_add_10_c(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_12_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
void idct8x8_10_add_10_c(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_10_add_c(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct8x8_12_add_12_c(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_12_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
void idct8x8_10_add_12_c(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_10_add_c(in, out, stride, 12);
|
||||
}
|
||||
|
||||
void idct8x8_12_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_12_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
void idct8x8_10_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_10_add_sse2(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct8x8_12_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_12_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
void idct8x8_10_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_10_add_sse2(in, out, stride, 12);
|
||||
}
|
||||
|
||||
void idct8x8_64_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_64_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
|
||||
vpx_highbd_idct8x8_64_add_sse2(in, out, stride, 10);
|
||||
}
|
||||
|
||||
void idct8x8_64_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
|
||||
vpx_highbd_idct8x8_64_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
|
||||
vpx_highbd_idct8x8_64_add_sse2(in, out, stride, 12);
|
||||
}
|
||||
#endif // HAVE_SSE2
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
@ -150,19 +155,17 @@ class FwdTrans8x8TestBase {
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with input range [-255, 255].
|
||||
for (int j = 0; j < 64; ++j) {
|
||||
for (int j = 0; j < 64; ++j)
|
||||
test_input_block[j] = ((rnd.Rand16() >> (16 - bit_depth_)) & mask_) -
|
||||
((rnd.Rand16() >> (16 - bit_depth_)) & mask_);
|
||||
}
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunFwdTxfm(test_input_block, test_output_block, pitch_));
|
||||
|
||||
for (int j = 0; j < 64; ++j) {
|
||||
if (test_output_block[j] < 0) {
|
||||
if (test_output_block[j] < 0)
|
||||
++count_sign_block[j][0];
|
||||
} else if (test_output_block[j] > 0) {
|
||||
else if (test_output_block[j] > 0)
|
||||
++count_sign_block[j][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,26 +177,25 @@ class FwdTrans8x8TestBase {
|
||||
<< 1. * max_diff / count_test_block * 100 << "%"
|
||||
<< " for input range [-255, 255] at index " << j
|
||||
<< " count0: " << count_sign_block[j][0]
|
||||
<< " count1: " << count_sign_block[j][1] << " diff: " << diff;
|
||||
<< " count1: " << count_sign_block[j][1]
|
||||
<< " diff: " << diff;
|
||||
}
|
||||
|
||||
memset(count_sign_block, 0, sizeof(count_sign_block));
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
// Initialize a test block with input range [-mask_ / 16, mask_ / 16].
|
||||
for (int j = 0; j < 64; ++j) {
|
||||
test_input_block[j] =
|
||||
((rnd.Rand16() & mask_) >> 4) - ((rnd.Rand16() & mask_) >> 4);
|
||||
}
|
||||
for (int j = 0; j < 64; ++j)
|
||||
test_input_block[j] = ((rnd.Rand16() & mask_) >> 4) -
|
||||
((rnd.Rand16() & mask_) >> 4);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunFwdTxfm(test_input_block, test_output_block, pitch_));
|
||||
|
||||
for (int j = 0; j < 64; ++j) {
|
||||
if (test_output_block[j] < 0) {
|
||||
if (test_output_block[j] < 0)
|
||||
++count_sign_block[j][0];
|
||||
} else if (test_output_block[j] > 0) {
|
||||
else if (test_output_block[j] > 0)
|
||||
++count_sign_block[j][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,7 +207,8 @@ class FwdTrans8x8TestBase {
|
||||
<< 1. * max_diff / count_test_block * 100 << "%"
|
||||
<< " for input range [-15, 15] at index " << j
|
||||
<< " count0: " << count_sign_block[j][0]
|
||||
<< " count1: " << count_sign_block[j][1] << " diff: " << diff;
|
||||
<< " count1: " << count_sign_block[j][1]
|
||||
<< " diff: " << diff;
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,22 +245,23 @@ class FwdTrans8x8TestBase {
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunFwdTxfm(test_input_block, test_temp_block, pitch_));
|
||||
for (int j = 0; j < 64; ++j) {
|
||||
if (test_temp_block[j] > 0) {
|
||||
test_temp_block[j] += 2;
|
||||
test_temp_block[j] /= 4;
|
||||
test_temp_block[j] *= 4;
|
||||
} else {
|
||||
test_temp_block[j] -= 2;
|
||||
test_temp_block[j] /= 4;
|
||||
test_temp_block[j] *= 4;
|
||||
}
|
||||
if (test_temp_block[j] > 0) {
|
||||
test_temp_block[j] += 2;
|
||||
test_temp_block[j] /= 4;
|
||||
test_temp_block[j] *= 4;
|
||||
} else {
|
||||
test_temp_block[j] -= 2;
|
||||
test_temp_block[j] /= 4;
|
||||
test_temp_block[j] *= 4;
|
||||
}
|
||||
}
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(test_temp_block, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(test_temp_block, CAST_TO_BYTEPTR(dst16), pitch_));
|
||||
RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -269,18 +273,19 @@ class FwdTrans8x8TestBase {
|
||||
const int diff = dst[j] - src[j];
|
||||
#endif
|
||||
const int error = diff * diff;
|
||||
if (max_error < error) max_error = error;
|
||||
if (max_error < error)
|
||||
max_error = error;
|
||||
total_error += error;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
|
||||
<< "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
|
||||
<< " roundtrip error > 1";
|
||||
<< "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
|
||||
<< " roundtrip error > 1";
|
||||
|
||||
EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
|
||||
<< "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
|
||||
<< "error > 1/5 per block";
|
||||
EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error)
|
||||
<< "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
|
||||
<< "error > 1/5 per block";
|
||||
}
|
||||
|
||||
void RunExtremalCheck() {
|
||||
@ -336,11 +341,12 @@ class FwdTrans8x8TestBase {
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
fwd_txfm_ref(test_input_block, ref_temp_block, pitch_, tx_type_));
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(test_temp_block, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(test_temp_block, CAST_TO_BYTEPTR(dst16), pitch_));
|
||||
RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -352,7 +358,8 @@ class FwdTrans8x8TestBase {
|
||||
const int diff = dst[j] - src[j];
|
||||
#endif
|
||||
const int error = diff * diff;
|
||||
if (max_error < error) max_error = error;
|
||||
if (max_error < error)
|
||||
max_error = error;
|
||||
total_error += error;
|
||||
|
||||
const int coeff_diff = test_temp_block[j] - ref_temp_block[j];
|
||||
@ -363,7 +370,7 @@ class FwdTrans8x8TestBase {
|
||||
<< "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has"
|
||||
<< "an individual roundtrip error > 1";
|
||||
|
||||
EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
|
||||
EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error)
|
||||
<< "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average"
|
||||
<< " roundtrip error > 1/5 per block";
|
||||
|
||||
@ -404,29 +411,29 @@ class FwdTrans8x8TestBase {
|
||||
}
|
||||
|
||||
reference_8x8_dct_2d(in, out_r);
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
|
||||
}
|
||||
|
||||
if (bit_depth_ == VPX_BITS_8) {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_));
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
|
||||
pitch_));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int diff =
|
||||
const uint32_t diff =
|
||||
bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
|
||||
#else
|
||||
const int diff = dst[j] - src[j];
|
||||
const uint32_t diff = dst[j] - src[j];
|
||||
#endif
|
||||
const uint32_t error = diff * diff;
|
||||
EXPECT_GE(1u << 2 * (bit_depth_ - 8), error)
|
||||
<< "Error: 8x8 IDCT has error " << error << " at index " << j;
|
||||
<< "Error: 8x8 IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -442,26 +449,25 @@ class FwdTrans8x8TestBase {
|
||||
double out_r[kNumCoeffs];
|
||||
|
||||
// Initialize a test block with input range [-mask_, mask_].
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
in[j] = rnd.Rand8() % 2 == 0 ? mask_ : -mask_;
|
||||
}
|
||||
|
||||
RunFwdTxfm(in, coeff, pitch_);
|
||||
reference_8x8_dct_2d(in, out_r);
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
for (int j = 0; j < kNumCoeffs; ++j)
|
||||
coeff_r[j] = static_cast<tran_low_t>(round(out_r[j]));
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
const int32_t diff = coeff[j] - coeff_r[j];
|
||||
const uint32_t diff = coeff[j] - coeff_r[j];
|
||||
const uint32_t error = diff * diff;
|
||||
EXPECT_GE(9u << 2 * (bit_depth_ - 8), error)
|
||||
<< "Error: 8x8 DCT has error " << error << " at index " << j;
|
||||
<< "Error: 8x8 DCT has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CompareInvReference(IdctFunc ref_txfm, int thresh) {
|
||||
void CompareInvReference(IdctFunc ref_txfm, int thresh) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = 10000;
|
||||
const int eob = 12;
|
||||
@ -478,7 +484,7 @@ class FwdTrans8x8TestBase {
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
if (j < eob) {
|
||||
// Random values less than the threshold, either positive or negative
|
||||
coeff[scan[j]] = rnd(thresh) * (1 - 2 * (i % 2));
|
||||
coeff[scan[j]] = rnd(thresh) * (1-2*(i%2));
|
||||
} else {
|
||||
coeff[scan[j]] = 0;
|
||||
}
|
||||
@ -497,22 +503,23 @@ class FwdTrans8x8TestBase {
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
ref_txfm(coeff, CAST_TO_BYTEPTR(ref16), pitch_);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_));
|
||||
ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_);
|
||||
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
|
||||
pitch_));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int diff =
|
||||
const uint32_t diff =
|
||||
bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
|
||||
#else
|
||||
const int diff = dst[j] - ref[j];
|
||||
const uint32_t diff = dst[j] - ref[j];
|
||||
#endif
|
||||
const uint32_t error = diff * diff;
|
||||
EXPECT_EQ(0u, error)
|
||||
<< "Error: 8x8 IDCT has error " << error << " at index " << j;
|
||||
<< "Error: 8x8 IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -523,16 +530,17 @@ class FwdTrans8x8TestBase {
|
||||
int mask_;
|
||||
};
|
||||
|
||||
class FwdTrans8x8DCT : public FwdTrans8x8TestBase,
|
||||
public ::testing::TestWithParam<Dct8x8Param> {
|
||||
class FwdTrans8x8DCT
|
||||
: public FwdTrans8x8TestBase,
|
||||
public ::testing::TestWithParam<Dct8x8Param> {
|
||||
public:
|
||||
virtual ~FwdTrans8x8DCT() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
pitch_ = 8;
|
||||
tx_type_ = GET_PARAM(2);
|
||||
pitch_ = 8;
|
||||
fwd_txfm_ref = fdct8x8_ref;
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
@ -552,26 +560,37 @@ class FwdTrans8x8DCT : public FwdTrans8x8TestBase,
|
||||
IdctFunc inv_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(FwdTrans8x8DCT, SignBiasCheck) { RunSignBiasCheck(); }
|
||||
TEST_P(FwdTrans8x8DCT, SignBiasCheck) {
|
||||
RunSignBiasCheck();
|
||||
}
|
||||
|
||||
TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) { RunRoundTripErrorCheck(); }
|
||||
TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) {
|
||||
RunRoundTripErrorCheck();
|
||||
}
|
||||
|
||||
TEST_P(FwdTrans8x8DCT, ExtremalCheck) { RunExtremalCheck(); }
|
||||
TEST_P(FwdTrans8x8DCT, ExtremalCheck) {
|
||||
RunExtremalCheck();
|
||||
}
|
||||
|
||||
TEST_P(FwdTrans8x8DCT, FwdAccuracyCheck) { RunFwdAccuracyCheck(); }
|
||||
TEST_P(FwdTrans8x8DCT, FwdAccuracyCheck) {
|
||||
RunFwdAccuracyCheck();
|
||||
}
|
||||
|
||||
TEST_P(FwdTrans8x8DCT, InvAccuracyCheck) { RunInvAccuracyCheck(); }
|
||||
TEST_P(FwdTrans8x8DCT, InvAccuracyCheck) {
|
||||
RunInvAccuracyCheck();
|
||||
}
|
||||
|
||||
class FwdTrans8x8HT : public FwdTrans8x8TestBase,
|
||||
public ::testing::TestWithParam<Ht8x8Param> {
|
||||
class FwdTrans8x8HT
|
||||
: public FwdTrans8x8TestBase,
|
||||
public ::testing::TestWithParam<Ht8x8Param> {
|
||||
public:
|
||||
virtual ~FwdTrans8x8HT() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fwd_txfm_ = GET_PARAM(0);
|
||||
inv_txfm_ = GET_PARAM(1);
|
||||
tx_type_ = GET_PARAM(2);
|
||||
pitch_ = 8;
|
||||
tx_type_ = GET_PARAM(2);
|
||||
pitch_ = 8;
|
||||
fwd_txfm_ref = fht8x8_ref;
|
||||
bit_depth_ = GET_PARAM(3);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
@ -591,14 +610,21 @@ class FwdTrans8x8HT : public FwdTrans8x8TestBase,
|
||||
IhtFunc inv_txfm_;
|
||||
};
|
||||
|
||||
TEST_P(FwdTrans8x8HT, SignBiasCheck) { RunSignBiasCheck(); }
|
||||
TEST_P(FwdTrans8x8HT, SignBiasCheck) {
|
||||
RunSignBiasCheck();
|
||||
}
|
||||
|
||||
TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) { RunRoundTripErrorCheck(); }
|
||||
TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) {
|
||||
RunRoundTripErrorCheck();
|
||||
}
|
||||
|
||||
TEST_P(FwdTrans8x8HT, ExtremalCheck) { RunExtremalCheck(); }
|
||||
TEST_P(FwdTrans8x8HT, ExtremalCheck) {
|
||||
RunExtremalCheck();
|
||||
}
|
||||
|
||||
class InvTrans8x8DCT : public FwdTrans8x8TestBase,
|
||||
public ::testing::TestWithParam<Idct8x8Param> {
|
||||
class InvTrans8x8DCT
|
||||
: public FwdTrans8x8TestBase,
|
||||
public ::testing::TestWithParam<Idct8x8Param> {
|
||||
public:
|
||||
virtual ~InvTrans8x8DCT() {}
|
||||
|
||||
@ -628,7 +654,7 @@ TEST_P(InvTrans8x8DCT, CompareReference) {
|
||||
CompareInvReference(ref_txfm_, thresh_);
|
||||
}
|
||||
|
||||
using ::testing::make_tuple;
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
@ -638,10 +664,10 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_10, 0, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_12, 0, VPX_BITS_12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(C, FwdTrans8x8DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_c,
|
||||
&vpx_idct8x8_64_add_c, 0,
|
||||
VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
C, FwdTrans8x8DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
@ -670,13 +696,15 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_NEON && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(NEON, FwdTrans8x8DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_neon,
|
||||
&vpx_idct8x8_64_add_neon,
|
||||
0, VPX_BITS_8)));
|
||||
#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, FwdTrans8x8DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct8x8_neon, &vpx_idct8x8_64_add_neon, 0,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if !CONFIG_VP9_HIGHBITDEPTH
|
||||
#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, FwdTrans8x8HT,
|
||||
::testing::Values(
|
||||
@ -684,14 +712,14 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 1, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 3, VPX_BITS_8)));
|
||||
#endif // !CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_NEON && !CONFIG_EMULATE_HARDWARE
|
||||
#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, FwdTrans8x8DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_sse2,
|
||||
&vpx_idct8x8_64_add_sse2,
|
||||
0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, FwdTrans8x8DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_sse2, 0,
|
||||
VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, FwdTrans8x8HT,
|
||||
::testing::Values(
|
||||
@ -704,16 +732,16 @@ INSTANTIATE_TEST_CASE_P(
|
||||
#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, FwdTrans8x8DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_c, 0,
|
||||
VPX_BITS_8),
|
||||
make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_64_add_10_sse2,
|
||||
12, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct8x8_sse2,
|
||||
&idct8x8_64_add_10_sse2, 12, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_64_add_12_sse2,
|
||||
12, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct8x8_sse2,
|
||||
&idct8x8_64_add_12_sse2, 12, VPX_BITS_12)));
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8),
|
||||
make_tuple(&vpx_highbd_fdct8x8_c,
|
||||
&idct8x8_64_add_10_sse2, 12, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct8x8_sse2,
|
||||
&idct8x8_64_add_10_sse2, 12, VPX_BITS_10),
|
||||
make_tuple(&vpx_highbd_fdct8x8_c,
|
||||
&idct8x8_64_add_12_sse2, 12, VPX_BITS_12),
|
||||
make_tuple(&vpx_highbd_fdct8x8_sse2,
|
||||
&idct8x8_64_add_12_sse2, 12, VPX_BITS_12)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, FwdTrans8x8HT,
|
||||
@ -728,27 +756,30 @@ INSTANTIATE_TEST_CASE_P(
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, InvTrans8x8DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&idct8x8_12_add_10_c, &idct8x8_12_add_10_sse2, 6225,
|
||||
VPX_BITS_10),
|
||||
make_tuple(&idct8x8_10, &idct8x8_64_add_10_sse2, 6225, VPX_BITS_10),
|
||||
make_tuple(&idct8x8_12_add_12_c, &idct8x8_12_add_12_sse2, 6225,
|
||||
VPX_BITS_12),
|
||||
make_tuple(&idct8x8_12, &idct8x8_64_add_12_sse2, 6225, VPX_BITS_12)));
|
||||
make_tuple(&idct8x8_10_add_10_c,
|
||||
&idct8x8_10_add_10_sse2, 6225, VPX_BITS_10),
|
||||
make_tuple(&idct8x8_10,
|
||||
&idct8x8_64_add_10_sse2, 6225, VPX_BITS_10),
|
||||
make_tuple(&idct8x8_10_add_12_c,
|
||||
&idct8x8_10_add_12_sse2, 6225, VPX_BITS_12),
|
||||
make_tuple(&idct8x8_12,
|
||||
&idct8x8_64_add_12_sse2, 6225, VPX_BITS_12)));
|
||||
#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_SSSE3 && ARCH_X86_64 && !CONFIG_VP9_HIGHBITDEPTH && \
|
||||
!CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(SSSE3, FwdTrans8x8DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_ssse3,
|
||||
&vpx_idct8x8_64_add_sse2,
|
||||
0, VPX_BITS_8)));
|
||||
#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64 && \
|
||||
!CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSSE3, FwdTrans8x8DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct8x8_ssse3, &vpx_idct8x8_64_add_ssse3, 0,
|
||||
VPX_BITS_8)));
|
||||
#endif
|
||||
|
||||
#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(MSA, FwdTrans8x8DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_msa,
|
||||
&vpx_idct8x8_64_add_msa, 0,
|
||||
VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, FwdTrans8x8DCT,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_fdct8x8_msa, &vpx_idct8x8_64_add_msa, 0, VPX_BITS_8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, FwdTrans8x8HT,
|
||||
::testing::Values(
|
||||
@ -757,11 +788,4 @@ INSTANTIATE_TEST_CASE_P(
|
||||
make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 2, VPX_BITS_8),
|
||||
make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 3, VPX_BITS_8)));
|
||||
#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
|
||||
#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
INSTANTIATE_TEST_CASE_P(VSX, FwdTrans8x8DCT,
|
||||
::testing::Values(make_tuple(&vpx_fdct8x8_c,
|
||||
&vpx_idct8x8_64_add_vsx, 0,
|
||||
VPX_BITS_8)));
|
||||
#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
|
||||
} // namespace
|
||||
|
@ -13,11 +13,12 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class VP9FrameSizeTestsLarge : public ::libvpx_test::EncoderTest,
|
||||
public ::testing::Test {
|
||||
class VP9FrameSizeTestsLarge
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::testing::Test {
|
||||
protected:
|
||||
VP9FrameSizeTestsLarge()
|
||||
: EncoderTest(&::libvpx_test::kVP9), expected_res_(VPX_CODEC_OK) {}
|
||||
VP9FrameSizeTestsLarge() : EncoderTest(&::libvpx_test::kVP9),
|
||||
expected_res_(VPX_CODEC_OK) {}
|
||||
virtual ~VP9FrameSizeTestsLarge() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
@ -26,7 +27,7 @@ class VP9FrameSizeTestsLarge : public ::libvpx_test::EncoderTest,
|
||||
}
|
||||
|
||||
virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
|
||||
const libvpx_test::VideoSource & /*video*/,
|
||||
const libvpx_test::VideoSource& /*video*/,
|
||||
libvpx_test::Decoder *decoder) {
|
||||
EXPECT_EQ(expected_res_, res_dec) << decoder->DecodeError();
|
||||
return !::testing::Test::HasFailure();
|
||||
@ -66,13 +67,13 @@ TEST_F(VP9FrameSizeTestsLarge, ValidSizes) {
|
||||
expected_res_ = VPX_CODEC_OK;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
#else
|
||||
// This test produces a pretty large single frame allocation, (roughly
|
||||
// 25 megabits). The encoder allocates a good number of these frames
|
||||
// one for each lag in frames (for 2 pass), and then one for each possible
|
||||
// reference buffer (8) - we can end up with up to 30 buffers of roughly this
|
||||
// size or almost 1 gig of memory.
|
||||
// In total the allocations will exceed 2GiB which may cause a failure with
|
||||
// mingw + wine, use a smaller size in that case.
|
||||
// This test produces a pretty large single frame allocation, (roughly
|
||||
// 25 megabits). The encoder allocates a good number of these frames
|
||||
// one for each lag in frames (for 2 pass), and then one for each possible
|
||||
// reference buffer (8) - we can end up with up to 30 buffers of roughly this
|
||||
// size or almost 1 gig of memory.
|
||||
// In total the allocations will exceed 2GiB which may cause a failure with
|
||||
// mingw + wine, use a smaller size in that case.
|
||||
#if defined(_WIN32) && !defined(_WIN64) || defined(__OS2__)
|
||||
video.SetSize(4096, 3072);
|
||||
#else
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "vpx_ports/vpx_timer.h"
|
||||
|
||||
#include "test/acm_random.h"
|
||||
#include "test/register_state_check.h"
|
||||
@ -22,8 +21,20 @@ namespace {
|
||||
|
||||
using ::libvpx_test::ACMRandom;
|
||||
|
||||
typedef void (*HadamardFunc)(const int16_t *a, ptrdiff_t a_stride,
|
||||
tran_low_t *b);
|
||||
typedef void (*Hadamard8x8Func)(const int16_t *a, int a_stride,
|
||||
int16_t *b);
|
||||
|
||||
class HadamardTest : public ::testing::TestWithParam<Hadamard8x8Func> {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
h_func_ = GetParam();
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
}
|
||||
|
||||
protected:
|
||||
Hadamard8x8Func h_func_;
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
|
||||
void hadamard_loop(const int16_t *a, int a_stride, int16_t *out) {
|
||||
int16_t b[8];
|
||||
@ -48,95 +59,28 @@ void hadamard_loop(const int16_t *a, int a_stride, int16_t *out) {
|
||||
out[5] = c[3] - c[7];
|
||||
}
|
||||
|
||||
void reference_hadamard8x8(const int16_t *a, int a_stride, tran_low_t *b) {
|
||||
void reference_hadamard(const int16_t *a, int a_stride, int16_t *b) {
|
||||
int16_t buf[64];
|
||||
int16_t buf2[64];
|
||||
for (int i = 0; i < 8; ++i) hadamard_loop(a + i, a_stride, buf + i * 8);
|
||||
for (int i = 0; i < 8; ++i) hadamard_loop(buf + i, 8, buf2 + i * 8);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
hadamard_loop(a + i, a_stride, buf + i * 8);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; ++i) b[i] = (tran_low_t)buf2[i];
|
||||
}
|
||||
|
||||
void reference_hadamard16x16(const int16_t *a, int a_stride, tran_low_t *b) {
|
||||
/* The source is a 16x16 block. The destination is rearranged to 8x32.
|
||||
* Input is 9 bit. */
|
||||
reference_hadamard8x8(a + 0 + 0 * a_stride, a_stride, b + 0);
|
||||
reference_hadamard8x8(a + 8 + 0 * a_stride, a_stride, b + 64);
|
||||
reference_hadamard8x8(a + 0 + 8 * a_stride, a_stride, b + 128);
|
||||
reference_hadamard8x8(a + 8 + 8 * a_stride, a_stride, b + 192);
|
||||
|
||||
/* Overlay the 8x8 blocks and combine. */
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
/* 8x8 steps the range up to 15 bits. */
|
||||
const tran_low_t a0 = b[0];
|
||||
const tran_low_t a1 = b[64];
|
||||
const tran_low_t a2 = b[128];
|
||||
const tran_low_t a3 = b[192];
|
||||
|
||||
/* Prevent the result from escaping int16_t. */
|
||||
const tran_low_t b0 = (a0 + a1) >> 1;
|
||||
const tran_low_t b1 = (a0 - a1) >> 1;
|
||||
const tran_low_t b2 = (a2 + a3) >> 1;
|
||||
const tran_low_t b3 = (a2 - a3) >> 1;
|
||||
|
||||
/* Store a 16 bit value. */
|
||||
b[0] = b0 + b2;
|
||||
b[64] = b1 + b3;
|
||||
b[128] = b0 - b2;
|
||||
b[192] = b1 - b3;
|
||||
|
||||
++b;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
hadamard_loop(buf + i, 8, b + i * 8);
|
||||
}
|
||||
}
|
||||
|
||||
class HadamardTestBase : public ::testing::TestWithParam<HadamardFunc> {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
h_func_ = GetParam();
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
}
|
||||
|
||||
protected:
|
||||
HadamardFunc h_func_;
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
|
||||
void HadamardSpeedTest(const char *name, HadamardFunc const func,
|
||||
const int16_t *input, int stride, tran_low_t *output,
|
||||
int times) {
|
||||
int i;
|
||||
vpx_usec_timer timer;
|
||||
|
||||
vpx_usec_timer_start(&timer);
|
||||
for (i = 0; i < times; ++i) {
|
||||
func(input, stride, output);
|
||||
}
|
||||
vpx_usec_timer_mark(&timer);
|
||||
|
||||
const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
|
||||
printf("%s[%12d runs]: %d us\n", name, times, elapsed_time);
|
||||
}
|
||||
|
||||
class Hadamard8x8Test : public HadamardTestBase {};
|
||||
|
||||
void HadamardSpeedTest8x8(HadamardFunc const func, int times) {
|
||||
DECLARE_ALIGNED(16, int16_t, input[64]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output[64]);
|
||||
memset(input, 1, sizeof(input));
|
||||
HadamardSpeedTest("Hadamard8x8", func, input, 8, output, times);
|
||||
}
|
||||
|
||||
TEST_P(Hadamard8x8Test, CompareReferenceRandom) {
|
||||
TEST_P(HadamardTest, CompareReferenceRandom) {
|
||||
DECLARE_ALIGNED(16, int16_t, a[64]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, b[64]);
|
||||
tran_low_t b_ref[64];
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
DECLARE_ALIGNED(16, int16_t, b[64]);
|
||||
int16_t b_ref[64];
|
||||
for (int i = 0; i < 64; i++) {
|
||||
a[i] = rnd_.Rand9Signed();
|
||||
}
|
||||
memset(b, 0, sizeof(b));
|
||||
memset(b_ref, 0, sizeof(b_ref));
|
||||
|
||||
reference_hadamard8x8(a, 8, b_ref);
|
||||
reference_hadamard(a, 8, b_ref);
|
||||
ASM_REGISTER_STATE_CHECK(h_func_(a, 8, b));
|
||||
|
||||
// The order of the output is not important. Sort before checking.
|
||||
@ -145,11 +89,11 @@ TEST_P(Hadamard8x8Test, CompareReferenceRandom) {
|
||||
EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
|
||||
}
|
||||
|
||||
TEST_P(Hadamard8x8Test, VaryStride) {
|
||||
TEST_P(HadamardTest, VaryStride) {
|
||||
DECLARE_ALIGNED(16, int16_t, a[64 * 8]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, b[64]);
|
||||
tran_low_t b_ref[64];
|
||||
for (int i = 0; i < 64 * 8; ++i) {
|
||||
DECLARE_ALIGNED(16, int16_t, b[64]);
|
||||
int16_t b_ref[64];
|
||||
for (int i = 0; i < 64 * 8; i++) {
|
||||
a[i] = rnd_.Rand9Signed();
|
||||
}
|
||||
|
||||
@ -157,7 +101,7 @@ TEST_P(Hadamard8x8Test, VaryStride) {
|
||||
memset(b, 0, sizeof(b));
|
||||
memset(b_ref, 0, sizeof(b_ref));
|
||||
|
||||
reference_hadamard8x8(a, i, b_ref);
|
||||
reference_hadamard(a, i, b_ref);
|
||||
ASM_REGISTER_STATE_CHECK(h_func_(a, i, b));
|
||||
|
||||
// The order of the output is not important. Sort before checking.
|
||||
@ -167,127 +111,16 @@ TEST_P(Hadamard8x8Test, VaryStride) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Hadamard8x8Test, DISABLED_Speed) {
|
||||
HadamardSpeedTest8x8(h_func_, 10);
|
||||
HadamardSpeedTest8x8(h_func_, 10000);
|
||||
HadamardSpeedTest8x8(h_func_, 10000000);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, Hadamard8x8Test,
|
||||
INSTANTIATE_TEST_CASE_P(C, HadamardTest,
|
||||
::testing::Values(&vpx_hadamard_8x8_c));
|
||||
|
||||
#if HAVE_SSE2
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, Hadamard8x8Test,
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, HadamardTest,
|
||||
::testing::Values(&vpx_hadamard_8x8_sse2));
|
||||
#endif // HAVE_SSE2
|
||||
|
||||
#if HAVE_SSSE3 && ARCH_X86_64
|
||||
INSTANTIATE_TEST_CASE_P(SSSE3, Hadamard8x8Test,
|
||||
#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64
|
||||
INSTANTIATE_TEST_CASE_P(SSSE3, HadamardTest,
|
||||
::testing::Values(&vpx_hadamard_8x8_ssse3));
|
||||
#endif // HAVE_SSSE3 && ARCH_X86_64
|
||||
|
||||
#if HAVE_NEON
|
||||
INSTANTIATE_TEST_CASE_P(NEON, Hadamard8x8Test,
|
||||
::testing::Values(&vpx_hadamard_8x8_neon));
|
||||
#endif // HAVE_NEON
|
||||
|
||||
// TODO(jingning): Remove highbitdepth flag when the SIMD functions are
|
||||
// in place and turn on the unit test.
|
||||
#if !CONFIG_VP9_HIGHBITDEPTH
|
||||
#if HAVE_MSA
|
||||
INSTANTIATE_TEST_CASE_P(MSA, Hadamard8x8Test,
|
||||
::testing::Values(&vpx_hadamard_8x8_msa));
|
||||
#endif // HAVE_MSA
|
||||
#endif // !CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_VSX
|
||||
INSTANTIATE_TEST_CASE_P(VSX, Hadamard8x8Test,
|
||||
::testing::Values(&vpx_hadamard_8x8_vsx));
|
||||
#endif // HAVE_VSX
|
||||
|
||||
class Hadamard16x16Test : public HadamardTestBase {};
|
||||
|
||||
void HadamardSpeedTest16x16(HadamardFunc const func, int times) {
|
||||
DECLARE_ALIGNED(16, int16_t, input[256]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, output[256]);
|
||||
memset(input, 1, sizeof(input));
|
||||
HadamardSpeedTest("Hadamard16x16", func, input, 16, output, times);
|
||||
}
|
||||
|
||||
TEST_P(Hadamard16x16Test, CompareReferenceRandom) {
|
||||
DECLARE_ALIGNED(16, int16_t, a[16 * 16]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, b[16 * 16]);
|
||||
tran_low_t b_ref[16 * 16];
|
||||
for (int i = 0; i < 16 * 16; ++i) {
|
||||
a[i] = rnd_.Rand9Signed();
|
||||
}
|
||||
memset(b, 0, sizeof(b));
|
||||
memset(b_ref, 0, sizeof(b_ref));
|
||||
|
||||
reference_hadamard16x16(a, 16, b_ref);
|
||||
ASM_REGISTER_STATE_CHECK(h_func_(a, 16, b));
|
||||
|
||||
// The order of the output is not important. Sort before checking.
|
||||
std::sort(b, b + 16 * 16);
|
||||
std::sort(b_ref, b_ref + 16 * 16);
|
||||
EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
|
||||
}
|
||||
|
||||
TEST_P(Hadamard16x16Test, VaryStride) {
|
||||
DECLARE_ALIGNED(16, int16_t, a[16 * 16 * 8]);
|
||||
DECLARE_ALIGNED(16, tran_low_t, b[16 * 16]);
|
||||
tran_low_t b_ref[16 * 16];
|
||||
for (int i = 0; i < 16 * 16 * 8; ++i) {
|
||||
a[i] = rnd_.Rand9Signed();
|
||||
}
|
||||
|
||||
for (int i = 8; i < 64; i += 8) {
|
||||
memset(b, 0, sizeof(b));
|
||||
memset(b_ref, 0, sizeof(b_ref));
|
||||
|
||||
reference_hadamard16x16(a, i, b_ref);
|
||||
ASM_REGISTER_STATE_CHECK(h_func_(a, i, b));
|
||||
|
||||
// The order of the output is not important. Sort before checking.
|
||||
std::sort(b, b + 16 * 16);
|
||||
std::sort(b_ref, b_ref + 16 * 16);
|
||||
EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Hadamard16x16Test, DISABLED_Speed) {
|
||||
HadamardSpeedTest16x16(h_func_, 10);
|
||||
HadamardSpeedTest16x16(h_func_, 10000);
|
||||
HadamardSpeedTest16x16(h_func_, 10000000);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, Hadamard16x16Test,
|
||||
::testing::Values(&vpx_hadamard_16x16_c));
|
||||
|
||||
#if HAVE_SSE2
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, Hadamard16x16Test,
|
||||
::testing::Values(&vpx_hadamard_16x16_sse2));
|
||||
#endif // HAVE_SSE2
|
||||
|
||||
#if HAVE_AVX2
|
||||
INSTANTIATE_TEST_CASE_P(AVX2, Hadamard16x16Test,
|
||||
::testing::Values(&vpx_hadamard_16x16_avx2));
|
||||
#endif // HAVE_AVX2
|
||||
|
||||
#if HAVE_VSX
|
||||
INSTANTIATE_TEST_CASE_P(VSX, Hadamard16x16Test,
|
||||
::testing::Values(&vpx_hadamard_16x16_vsx));
|
||||
#endif // HAVE_VSX
|
||||
|
||||
#if HAVE_NEON
|
||||
INSTANTIATE_TEST_CASE_P(NEON, Hadamard16x16Test,
|
||||
::testing::Values(&vpx_hadamard_16x16_neon));
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if !CONFIG_VP9_HIGHBITDEPTH
|
||||
#if HAVE_MSA
|
||||
INSTANTIATE_TEST_CASE_P(MSA, Hadamard16x16Test,
|
||||
::testing::Values(&vpx_hadamard_16x16_msa));
|
||||
#endif // HAVE_MSA
|
||||
#endif // !CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64
|
||||
} // namespace
|
||||
|
@ -21,11 +21,14 @@ namespace libvpx_test {
|
||||
// so that we can do actual file encodes.
|
||||
class I420VideoSource : public YUVVideoSource {
|
||||
public:
|
||||
I420VideoSource(const std::string &file_name, unsigned int width,
|
||||
unsigned int height, int rate_numerator, int rate_denominator,
|
||||
I420VideoSource(const std::string &file_name,
|
||||
unsigned int width, unsigned int height,
|
||||
int rate_numerator, int rate_denominator,
|
||||
unsigned int start, int limit)
|
||||
: YUVVideoSource(file_name, VPX_IMG_FMT_I420, width, height,
|
||||
rate_numerator, rate_denominator, start, limit) {}
|
||||
: YUVVideoSource(file_name, VPX_IMG_FMT_I420,
|
||||
width, height,
|
||||
rate_numerator, rate_denominator,
|
||||
start, limit) {}
|
||||
};
|
||||
|
||||
} // namespace libvpx_test
|
||||
|
@ -17,21 +17,29 @@
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "test/acm_random.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_ports/msvc.h" // for round()
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
static int round(double x) {
|
||||
if (x < 0)
|
||||
return static_cast<int>(ceil(x - 0.5));
|
||||
else
|
||||
return static_cast<int>(floor(x + 0.5));
|
||||
}
|
||||
#endif
|
||||
|
||||
void reference_dct_1d(double input[8], double output[8]) {
|
||||
const double kPi = 3.141592653589793238462643383279502884;
|
||||
const double kInvSqrt2 = 0.707106781186547524400844362104;
|
||||
for (int k = 0; k < 8; k++) {
|
||||
output[k] = 0.0;
|
||||
for (int n = 0; n < 8; n++) {
|
||||
output[k] += input[n] * cos(kPi * (2 * n + 1) * k / 16.0);
|
||||
}
|
||||
if (k == 0) output[k] = output[k] * kInvSqrt2;
|
||||
for (int n = 0; n < 8; n++)
|
||||
output[k] += input[n]*cos(kPi*(2*n+1)*k/16.0);
|
||||
if (k == 0)
|
||||
output[k] = output[k]*kInvSqrt2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,19 +47,24 @@ void reference_dct_2d(int16_t input[64], double output[64]) {
|
||||
// First transform columns
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
double temp_in[8], temp_out[8];
|
||||
for (int j = 0; j < 8; ++j) temp_in[j] = input[j * 8 + i];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
temp_in[j] = input[j*8 + i];
|
||||
reference_dct_1d(temp_in, temp_out);
|
||||
for (int j = 0; j < 8; ++j) output[j * 8 + i] = temp_out[j];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
output[j*8 + i] = temp_out[j];
|
||||
}
|
||||
// Then transform rows
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
double temp_in[8], temp_out[8];
|
||||
for (int j = 0; j < 8; ++j) temp_in[j] = output[j + i * 8];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
temp_in[j] = output[j + i*8];
|
||||
reference_dct_1d(temp_in, temp_out);
|
||||
for (int j = 0; j < 8; ++j) output[j + i * 8] = temp_out[j];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
output[j + i*8] = temp_out[j];
|
||||
}
|
||||
// Scale by some magic number
|
||||
for (int i = 0; i < 64; ++i) output[i] *= 2;
|
||||
for (int i = 0; i < 64; ++i)
|
||||
output[i] *= 2;
|
||||
}
|
||||
|
||||
TEST(VP9Idct8x8Test, AccuracyCheck) {
|
||||
@ -68,18 +81,19 @@ TEST(VP9Idct8x8Test, AccuracyCheck) {
|
||||
dst[j] = rnd.Rand8();
|
||||
}
|
||||
// Initialize a test block with input range [-255, 255].
|
||||
for (int j = 0; j < 64; ++j) input[j] = src[j] - dst[j];
|
||||
for (int j = 0; j < 64; ++j)
|
||||
input[j] = src[j] - dst[j];
|
||||
|
||||
reference_dct_2d(input, output_r);
|
||||
for (int j = 0; j < 64; ++j) {
|
||||
coeff[j] = static_cast<tran_low_t>(round(output_r[j]));
|
||||
}
|
||||
for (int j = 0; j < 64; ++j)
|
||||
coeff[j] = round(output_r[j]);
|
||||
vpx_idct8x8_64_add_c(coeff, dst, 8);
|
||||
for (int j = 0; j < 64; ++j) {
|
||||
const int diff = dst[j] - src[j];
|
||||
const int error = diff * diff;
|
||||
EXPECT_GE(1, error) << "Error: 8x8 FDCT/IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
EXPECT_GE(1, error)
|
||||
<< "Error: 8x8 FDCT/IDCT has error " << error
|
||||
<< " at index " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "test/buffer.h"
|
||||
#include "test/clear_system_state.h"
|
||||
#include "test/register_state_check.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
@ -22,156 +21,101 @@ typedef void (*IdctFunc)(int16_t *input, unsigned char *pred_ptr,
|
||||
int pred_stride, unsigned char *dst_ptr,
|
||||
int dst_stride);
|
||||
namespace {
|
||||
|
||||
using libvpx_test::Buffer;
|
||||
|
||||
class IDCTTest : public ::testing::TestWithParam<IdctFunc> {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
int i;
|
||||
|
||||
UUT = GetParam();
|
||||
|
||||
input = new Buffer<int16_t>(4, 4, 0);
|
||||
ASSERT_TRUE(input != NULL);
|
||||
ASSERT_TRUE(input->Init());
|
||||
predict = new Buffer<uint8_t>(4, 4, 3);
|
||||
ASSERT_TRUE(predict != NULL);
|
||||
ASSERT_TRUE(predict->Init());
|
||||
output = new Buffer<uint8_t>(4, 4, 3);
|
||||
ASSERT_TRUE(output != NULL);
|
||||
ASSERT_TRUE(output->Init());
|
||||
memset(input, 0, sizeof(input));
|
||||
/* Set up guard blocks */
|
||||
for (i = 0; i < 256; i++) output[i] = ((i & 0xF) < 4 && (i < 64)) ? 0 : -1;
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
delete input;
|
||||
delete predict;
|
||||
delete output;
|
||||
libvpx_test::ClearSystemState();
|
||||
}
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
IdctFunc UUT;
|
||||
Buffer<int16_t> *input;
|
||||
Buffer<uint8_t> *predict;
|
||||
Buffer<uint8_t> *output;
|
||||
int16_t input[16];
|
||||
unsigned char output[256];
|
||||
unsigned char predict[256];
|
||||
};
|
||||
|
||||
TEST_P(IDCTTest, TestGuardBlocks) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
if ((i & 0xF) < 4 && i < 64)
|
||||
EXPECT_EQ(0, output[i]) << i;
|
||||
else
|
||||
EXPECT_EQ(255, output[i]);
|
||||
}
|
||||
|
||||
TEST_P(IDCTTest, TestAllZeros) {
|
||||
// When the input is '0' the output will be '0'.
|
||||
input->Set(0);
|
||||
predict->Set(0);
|
||||
output->Set(0);
|
||||
int i;
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
|
||||
predict->stride(), output->TopLeftPixel(),
|
||||
output->stride()));
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
|
||||
|
||||
ASSERT_TRUE(input->CheckValues(0));
|
||||
ASSERT_TRUE(input->CheckPadding());
|
||||
ASSERT_TRUE(output->CheckValues(0));
|
||||
ASSERT_TRUE(output->CheckPadding());
|
||||
for (i = 0; i < 256; i++)
|
||||
if ((i & 0xF) < 4 && i < 64)
|
||||
EXPECT_EQ(0, output[i]) << "i==" << i;
|
||||
else
|
||||
EXPECT_EQ(255, output[i]) << "i==" << i;
|
||||
}
|
||||
|
||||
TEST_P(IDCTTest, TestAllOnes) {
|
||||
input->Set(0);
|
||||
// When the first element is '4' it will fill the output buffer with '1'.
|
||||
input->TopLeftPixel()[0] = 4;
|
||||
predict->Set(0);
|
||||
output->Set(0);
|
||||
int i;
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
|
||||
predict->stride(), output->TopLeftPixel(),
|
||||
output->stride()));
|
||||
input[0] = 4;
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
|
||||
|
||||
ASSERT_TRUE(output->CheckValues(1));
|
||||
ASSERT_TRUE(output->CheckPadding());
|
||||
for (i = 0; i < 256; i++)
|
||||
if ((i & 0xF) < 4 && i < 64)
|
||||
EXPECT_EQ(1, output[i]) << "i==" << i;
|
||||
else
|
||||
EXPECT_EQ(255, output[i]) << "i==" << i;
|
||||
}
|
||||
|
||||
TEST_P(IDCTTest, TestAddOne) {
|
||||
// Set the transform output to '1' and make sure it gets added to the
|
||||
// prediction buffer.
|
||||
input->Set(0);
|
||||
input->TopLeftPixel()[0] = 4;
|
||||
output->Set(0);
|
||||
int i;
|
||||
|
||||
uint8_t *pred = predict->TopLeftPixel();
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
pred[y * predict->stride() + x] = y * 4 + x;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 256; i++) predict[i] = i;
|
||||
input[0] = 4;
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input, predict, 16, output, 16));
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
|
||||
predict->stride(), output->TopLeftPixel(),
|
||||
output->stride()));
|
||||
|
||||
uint8_t const *out = output->TopLeftPixel();
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
EXPECT_EQ(1 + y * 4 + x, out[y * output->stride() + x]);
|
||||
}
|
||||
}
|
||||
|
||||
if (HasFailure()) {
|
||||
output->DumpBuffer();
|
||||
}
|
||||
|
||||
ASSERT_TRUE(output->CheckPadding());
|
||||
for (i = 0; i < 256; i++)
|
||||
if ((i & 0xF) < 4 && i < 64)
|
||||
EXPECT_EQ(i + 1, output[i]) << "i==" << i;
|
||||
else
|
||||
EXPECT_EQ(255, output[i]) << "i==" << i;
|
||||
}
|
||||
|
||||
TEST_P(IDCTTest, TestWithData) {
|
||||
// Test a single known input.
|
||||
predict->Set(0);
|
||||
int i;
|
||||
|
||||
int16_t *in = input->TopLeftPixel();
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
in[y * input->stride() + x] = y * 4 + x;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 16; i++) input[i] = i;
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
|
||||
predict->stride(), output->TopLeftPixel(),
|
||||
output->stride()));
|
||||
ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
|
||||
|
||||
uint8_t *out = output->TopLeftPixel();
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
switch (y * 4 + x) {
|
||||
case 0: EXPECT_EQ(11, out[y * output->stride() + x]); break;
|
||||
case 2:
|
||||
case 5:
|
||||
case 8: EXPECT_EQ(3, out[y * output->stride() + x]); break;
|
||||
case 10: EXPECT_EQ(1, out[y * output->stride() + x]); break;
|
||||
default: EXPECT_EQ(0, out[y * output->stride() + x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HasFailure()) {
|
||||
output->DumpBuffer();
|
||||
}
|
||||
|
||||
ASSERT_TRUE(output->CheckPadding());
|
||||
for (i = 0; i < 256; i++)
|
||||
if ((i & 0xF) > 3 || i > 63)
|
||||
EXPECT_EQ(255, output[i]) << "i==" << i;
|
||||
else if (i == 0)
|
||||
EXPECT_EQ(11, output[i]) << "i==" << i;
|
||||
else if (i == 34)
|
||||
EXPECT_EQ(1, output[i]) << "i==" << i;
|
||||
else if (i == 2 || i == 17 || i == 32)
|
||||
EXPECT_EQ(3, output[i]) << "i==" << i;
|
||||
else
|
||||
EXPECT_EQ(0, output[i]) << "i==" << i;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, IDCTTest, ::testing::Values(vp8_short_idct4x4llm_c));
|
||||
|
||||
#if HAVE_NEON
|
||||
INSTANTIATE_TEST_CASE_P(NEON, IDCTTest,
|
||||
::testing::Values(vp8_short_idct4x4llm_neon));
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if HAVE_MMX
|
||||
INSTANTIATE_TEST_CASE_P(MMX, IDCTTest,
|
||||
::testing::Values(vp8_short_idct4x4llm_mmx));
|
||||
#endif // HAVE_MMX
|
||||
|
||||
#endif
|
||||
#if HAVE_MSA
|
||||
INSTANTIATE_TEST_CASE_P(MSA, IDCTTest,
|
||||
::testing::Values(vp8_short_idct4x4llm_msa));
|
||||
#endif // HAVE_MSA
|
||||
|
||||
#if HAVE_MMI
|
||||
INSTANTIATE_TEST_CASE_P(MMI, IDCTTest,
|
||||
::testing::Values(vp8_short_idct4x4llm_mmi));
|
||||
#endif // HAVE_MMI
|
||||
} // namespace
|
||||
#endif
|
||||
}
|
||||
|
@ -34,19 +34,21 @@ std::ostream &operator<<(std::ostream &os, const DecodeParam &dp) {
|
||||
return os << "threads: " << dp.threads << " file: " << dp.filename;
|
||||
}
|
||||
|
||||
class InvalidFileTest : public ::libvpx_test::DecoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<DecodeParam> {
|
||||
class InvalidFileTest
|
||||
: public ::libvpx_test::DecoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<DecodeParam> {
|
||||
protected:
|
||||
InvalidFileTest() : DecoderTest(GET_PARAM(0)), res_file_(NULL) {}
|
||||
|
||||
virtual ~InvalidFileTest() {
|
||||
if (res_file_ != NULL) fclose(res_file_);
|
||||
if (res_file_ != NULL)
|
||||
fclose(res_file_);
|
||||
}
|
||||
|
||||
void OpenResFile(const std::string &res_file_name_) {
|
||||
res_file_ = libvpx_test::OpenTestDataFile(res_file_name_);
|
||||
ASSERT_TRUE(res_file_ != NULL)
|
||||
<< "Result file open failed. Filename: " << res_file_name_;
|
||||
ASSERT_TRUE(res_file_ != NULL) << "Result file open failed. Filename: "
|
||||
<< res_file_name_;
|
||||
}
|
||||
|
||||
virtual bool HandleDecodeResult(
|
||||
@ -70,9 +72,8 @@ class InvalidFileTest : public ::libvpx_test::DecoderTest,
|
||||
EXPECT_TRUE(res_dec == expected_res_dec ||
|
||||
res_dec == VPX_CODEC_CORRUPT_FRAME)
|
||||
<< "Results don't match: frame number = " << video.frame_number()
|
||||
<< ". (" << decoder->DecodeError()
|
||||
<< "). Expected: " << expected_res_dec << " or "
|
||||
<< VPX_CODEC_CORRUPT_FRAME;
|
||||
<< ". (" << decoder->DecodeError() << "). Expected: "
|
||||
<< expected_res_dec << " or " << VPX_CODEC_CORRUPT_FRAME;
|
||||
} else {
|
||||
EXPECT_EQ(expected_res_dec, res_dec)
|
||||
<< "Results don't match: frame number = " << video.frame_number()
|
||||
@ -84,24 +85,23 @@ class InvalidFileTest : public ::libvpx_test::DecoderTest,
|
||||
|
||||
void RunTest() {
|
||||
const DecodeParam input = GET_PARAM(1);
|
||||
libvpx_test::CompressedVideoSource *video = NULL;
|
||||
vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
|
||||
cfg.threads = input.threads;
|
||||
const std::string filename = input.filename;
|
||||
|
||||
// Open compressed video file.
|
||||
testing::internal::scoped_ptr<libvpx_test::CompressedVideoSource> video;
|
||||
if (filename.substr(filename.length() - 3, 3) == "ivf") {
|
||||
video.reset(new libvpx_test::IVFVideoSource(filename));
|
||||
video = new libvpx_test::IVFVideoSource(filename);
|
||||
} else if (filename.substr(filename.length() - 4, 4) == "webm") {
|
||||
#if CONFIG_WEBM_IO
|
||||
video.reset(new libvpx_test::WebMVideoSource(filename));
|
||||
video = new libvpx_test::WebMVideoSource(filename);
|
||||
#else
|
||||
fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
|
||||
filename.c_str());
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
ASSERT_TRUE(video.get() != NULL);
|
||||
video->Init();
|
||||
|
||||
// Construct result file name. The file holds a list of expected integer
|
||||
@ -111,58 +111,37 @@ class InvalidFileTest : public ::libvpx_test::DecoderTest,
|
||||
OpenResFile(res_filename);
|
||||
|
||||
// Decode frame, and check the md5 matching.
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get(), cfg));
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(video, cfg));
|
||||
delete video;
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *res_file_;
|
||||
};
|
||||
|
||||
TEST_P(InvalidFileTest, ReturnCode) { RunTest(); }
|
||||
TEST_P(InvalidFileTest, ReturnCode) {
|
||||
RunTest();
|
||||
}
|
||||
|
||||
#if CONFIG_VP8_DECODER
|
||||
const DecodeParam kVP8InvalidFileTests[] = {
|
||||
{ 1, "invalid-bug-1443.ivf" },
|
||||
{ 1, "invalid-token-partition.ivf" },
|
||||
};
|
||||
|
||||
VP8_INSTANTIATE_TEST_CASE(InvalidFileTest,
|
||||
::testing::ValuesIn(kVP8InvalidFileTests));
|
||||
#endif // CONFIG_VP8_DECODER
|
||||
|
||||
#if CONFIG_VP9_DECODER
|
||||
const DecodeParam kVP9InvalidFileTests[] = {
|
||||
{ 1, "invalid-vp90-02-v2.webm" },
|
||||
{1, "invalid-vp90-02-v2.webm"},
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
{ 1, "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf" },
|
||||
{ 1,
|
||||
"invalid-vp90-2-21-resize_inter_320x180_5_3-4.webm.ivf.s45551_r01-05_b6-."
|
||||
"ivf" },
|
||||
{1, "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf"},
|
||||
#endif
|
||||
{ 1, "invalid-vp90-03-v3.webm" },
|
||||
{ 1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf" },
|
||||
{ 1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf" },
|
||||
// This file will cause a large allocation which is expected to fail in 32-bit
|
||||
// environments. Test x86 for coverage purposes as the allocation failure will
|
||||
// be in platform agnostic code.
|
||||
#if ARCH_X86
|
||||
{ 1, "invalid-vp90-2-00-quantizer-63.ivf.kf_65527x61446.ivf" },
|
||||
#endif
|
||||
{ 1, "invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf" },
|
||||
{ 1, "invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf" },
|
||||
{ 1, "invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf" },
|
||||
{ 1, "invalid-vp91-2-mixedrefcsp-444to420.ivf" },
|
||||
{ 1, "invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf" },
|
||||
{ 1, "invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf" },
|
||||
{ 1, "invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf" },
|
||||
{ 1,
|
||||
"invalid-vp90-2-10-show-existing-frame.webm.ivf.s180315_r01-05_b6-.ivf" },
|
||||
{ 1, "invalid-crbug-667044.webm" },
|
||||
{1, "invalid-vp90-03-v3.webm"},
|
||||
{1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf"},
|
||||
{1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf"},
|
||||
{1, "invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf"},
|
||||
{1, "invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf"},
|
||||
{1, "invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf"},
|
||||
{1, "invalid-vp91-2-mixedrefcsp-444to420.ivf"},
|
||||
{1, "invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf"},
|
||||
{1, "invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf"},
|
||||
{1, "invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf"},
|
||||
};
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(InvalidFileTest,
|
||||
::testing::ValuesIn(kVP9InvalidFileTests));
|
||||
#endif // CONFIG_VP9_DECODER
|
||||
|
||||
// This class will include test vectors that are expected to fail
|
||||
// peek. However they are still expected to have no fatal failures.
|
||||
@ -170,46 +149,34 @@ class InvalidFileInvalidPeekTest : public InvalidFileTest {
|
||||
protected:
|
||||
InvalidFileInvalidPeekTest() : InvalidFileTest() {}
|
||||
virtual void HandlePeekResult(libvpx_test::Decoder *const /*decoder*/,
|
||||
libvpx_test::CompressedVideoSource * /*video*/,
|
||||
libvpx_test::CompressedVideoSource* /*video*/,
|
||||
const vpx_codec_err_t /*res_peek*/) {}
|
||||
};
|
||||
|
||||
TEST_P(InvalidFileInvalidPeekTest, ReturnCode) { RunTest(); }
|
||||
TEST_P(InvalidFileInvalidPeekTest, ReturnCode) {
|
||||
RunTest();
|
||||
}
|
||||
|
||||
#if CONFIG_VP8_DECODER
|
||||
const DecodeParam kVP8InvalidPeekTests[] = {
|
||||
{ 1, "invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf" },
|
||||
};
|
||||
|
||||
VP8_INSTANTIATE_TEST_CASE(InvalidFileInvalidPeekTest,
|
||||
::testing::ValuesIn(kVP8InvalidPeekTests));
|
||||
#endif // CONFIG_VP8_DECODER
|
||||
|
||||
#if CONFIG_VP9_DECODER
|
||||
const DecodeParam kVP9InvalidFileInvalidPeekTests[] = {
|
||||
{ 1, "invalid-vp90-01-v3.webm" },
|
||||
{1, "invalid-vp90-01-v3.webm"},
|
||||
};
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(InvalidFileInvalidPeekTest,
|
||||
::testing::ValuesIn(kVP9InvalidFileInvalidPeekTests));
|
||||
|
||||
const DecodeParam kMultiThreadedVP9InvalidFileTests[] = {
|
||||
{ 4, "invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm" },
|
||||
{ 4,
|
||||
"invalid-"
|
||||
"vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf" },
|
||||
{ 4,
|
||||
"invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf" },
|
||||
{ 2, "invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf" },
|
||||
{ 4, "invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf" },
|
||||
{ 2, "invalid-crbug-629481.webm" },
|
||||
{4, "invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm"},
|
||||
{4, "invalid-"
|
||||
"vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf"},
|
||||
{4, "invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf"},
|
||||
{2, "invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf"},
|
||||
{4, "invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf"},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
VP9MultiThreaded, InvalidFileTest,
|
||||
::testing::Combine(
|
||||
::testing::Values(
|
||||
static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
|
||||
static_cast<const libvpx_test::CodecFactory*>(&libvpx_test::kVP9)),
|
||||
::testing::ValuesIn(kMultiThreadedVP9InvalidFileTests)));
|
||||
#endif // CONFIG_VP9_DECODER
|
||||
} // namespace
|
||||
|
@ -29,13 +29,19 @@ static unsigned int MemGetLe32(const uint8_t *mem) {
|
||||
class IVFVideoSource : public CompressedVideoSource {
|
||||
public:
|
||||
explicit IVFVideoSource(const std::string &file_name)
|
||||
: file_name_(file_name), input_file_(NULL), compressed_frame_buf_(NULL),
|
||||
frame_sz_(0), frame_(0), end_of_file_(false) {}
|
||||
: file_name_(file_name),
|
||||
input_file_(NULL),
|
||||
compressed_frame_buf_(NULL),
|
||||
frame_sz_(0),
|
||||
frame_(0),
|
||||
end_of_file_(false) {
|
||||
}
|
||||
|
||||
virtual ~IVFVideoSource() {
|
||||
delete[] compressed_frame_buf_;
|
||||
|
||||
if (input_file_) fclose(input_file_);
|
||||
if (input_file_)
|
||||
fclose(input_file_);
|
||||
}
|
||||
|
||||
virtual void Init() {
|
||||
@ -47,17 +53,16 @@ class IVFVideoSource : public CompressedVideoSource {
|
||||
|
||||
virtual void Begin() {
|
||||
input_file_ = OpenTestDataFile(file_name_);
|
||||
ASSERT_TRUE(input_file_ != NULL)
|
||||
<< "Input file open failed. Filename: " << file_name_;
|
||||
ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
|
||||
<< file_name_;
|
||||
|
||||
// Read file header
|
||||
uint8_t file_hdr[kIvfFileHdrSize];
|
||||
ASSERT_EQ(kIvfFileHdrSize, fread(file_hdr, 1, kIvfFileHdrSize, input_file_))
|
||||
<< "File header read failed.";
|
||||
// Check file header
|
||||
ASSERT_TRUE(file_hdr[0] == 'D' && file_hdr[1] == 'K' &&
|
||||
file_hdr[2] == 'I' && file_hdr[3] == 'F')
|
||||
<< "Input is not an IVF file.";
|
||||
ASSERT_TRUE(file_hdr[0] == 'D' && file_hdr[1] == 'K' && file_hdr[2] == 'I'
|
||||
&& file_hdr[3] == 'F') << "Input is not an IVF file.";
|
||||
|
||||
FillFrame();
|
||||
}
|
||||
@ -71,8 +76,8 @@ class IVFVideoSource : public CompressedVideoSource {
|
||||
ASSERT_TRUE(input_file_ != NULL);
|
||||
uint8_t frame_hdr[kIvfFrameHdrSize];
|
||||
// Check frame header and read a frame from input_file.
|
||||
if (fread(frame_hdr, 1, kIvfFrameHdrSize, input_file_) !=
|
||||
kIvfFrameHdrSize) {
|
||||
if (fread(frame_hdr, 1, kIvfFrameHdrSize, input_file_)
|
||||
!= kIvfFrameHdrSize) {
|
||||
end_of_file_ = true;
|
||||
} else {
|
||||
end_of_file_ = false;
|
||||
|
@ -17,9 +17,8 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class KeyframeTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
class KeyframeTest : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||
protected:
|
||||
KeyframeTest() : EncoderTest(GET_PARAM(0)) {}
|
||||
virtual ~KeyframeTest() {}
|
||||
@ -35,12 +34,10 @@ class KeyframeTest
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
if (kf_do_force_kf_) {
|
||||
if (kf_do_force_kf_)
|
||||
frame_flags_ = (video->frame() % 3) ? 0 : VPX_EFLAG_FORCE_KF;
|
||||
}
|
||||
if (set_cpu_used_ && video->frame() == 1) {
|
||||
if (set_cpu_used_ && video->frame() == 1)
|
||||
encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
@ -68,9 +65,8 @@ TEST_P(KeyframeTest, TestRandomVideoSource) {
|
||||
|
||||
// In realtime mode - auto placed keyframes are exceedingly rare, don't
|
||||
// bother with this check if(GetParam() > 0)
|
||||
if (GET_PARAM(1) > 0) {
|
||||
if (GET_PARAM(1) > 0)
|
||||
EXPECT_GT(kf_count_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyframeTest, TestDisableKeyframes) {
|
||||
@ -118,7 +114,8 @@ TEST_P(KeyframeTest, TestAutoKeyframe) {
|
||||
// may not produce a keyframe like we expect. This is necessary when running
|
||||
// on very slow environments (like Valgrind). The step -11 was determined
|
||||
// experimentally as the fastest mode that still throws the keyframe.
|
||||
if (deadline_ == VPX_DL_REALTIME) set_cpu_used_ = -11;
|
||||
if (deadline_ == VPX_DL_REALTIME)
|
||||
set_cpu_used_ = -11;
|
||||
|
||||
// This clip has a cut scene every 30 frames -> Frame 0, 30, 60, 90, 120.
|
||||
// I check only the first 40 frames to make sure there's a keyframe at frame
|
||||
@ -130,16 +127,15 @@ TEST_P(KeyframeTest, TestAutoKeyframe) {
|
||||
|
||||
// In realtime mode - auto placed keyframes are exceedingly rare, don't
|
||||
// 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 ";
|
||||
}
|
||||
|
||||
// Verify that keyframes match the file keyframes in the file.
|
||||
for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
|
||||
iter != kf_pts_list_.end(); ++iter) {
|
||||
if (deadline_ == VPX_DL_REALTIME && *iter > 0)
|
||||
EXPECT_EQ(0, (*iter - 1) % 30)
|
||||
<< "Unexpected keyframe at frame " << *iter;
|
||||
EXPECT_EQ(0, (*iter - 1) % 30) << "Unexpected keyframe at frame "
|
||||
<< *iter;
|
||||
else
|
||||
EXPECT_EQ(0, *iter % 30) << "Unexpected keyframe at frame " << *iter;
|
||||
}
|
||||
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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 "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"
|
||||
|
||||
namespace {
|
||||
class LevelTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
LevelTest()
|
||||
: EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
|
||||
cpu_used_(GET_PARAM(2)), min_gf_internal_(24), target_level_(0),
|
||||
level_(0) {}
|
||||
virtual ~LevelTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
InitializeConfig();
|
||||
SetMode(encoding_mode_);
|
||||
if (encoding_mode_ != ::libvpx_test::kRealTime) {
|
||||
cfg_.g_lag_in_frames = 25;
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
} else {
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
}
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 5;
|
||||
cfg_.rc_2pass_vbr_maxsection_pct = 2000;
|
||||
cfg_.rc_target_bitrate = 400;
|
||||
cfg_.rc_max_quantizer = 63;
|
||||
cfg_.rc_min_quantizer = 0;
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
if (video->frame() == 0) {
|
||||
encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
|
||||
encoder->Control(VP9E_SET_TARGET_LEVEL, target_level_);
|
||||
encoder->Control(VP9E_SET_MIN_GF_INTERVAL, min_gf_internal_);
|
||||
if (encoding_mode_ != ::libvpx_test::kRealTime) {
|
||||
encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
|
||||
encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
|
||||
encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
|
||||
encoder->Control(VP8E_SET_ARNR_TYPE, 3);
|
||||
}
|
||||
}
|
||||
encoder->Control(VP9E_GET_LEVEL, &level_);
|
||||
ASSERT_LE(level_, 51);
|
||||
ASSERT_GE(level_, 0);
|
||||
}
|
||||
|
||||
::libvpx_test::TestMode encoding_mode_;
|
||||
int cpu_used_;
|
||||
int min_gf_internal_;
|
||||
int target_level_;
|
||||
int level_;
|
||||
};
|
||||
|
||||
TEST_P(LevelTest, TestTargetLevel11Large) {
|
||||
ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
|
||||
60);
|
||||
target_level_ = 11;
|
||||
cfg_.rc_target_bitrate = 150;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
ASSERT_GE(target_level_, level_);
|
||||
}
|
||||
|
||||
TEST_P(LevelTest, TestTargetLevel20Large) {
|
||||
ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 60);
|
||||
target_level_ = 20;
|
||||
cfg_.rc_target_bitrate = 1200;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
ASSERT_GE(target_level_, level_);
|
||||
}
|
||||
|
||||
TEST_P(LevelTest, TestTargetLevel31Large) {
|
||||
ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
|
||||
::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, 30,
|
||||
1, 0, 60);
|
||||
target_level_ = 31;
|
||||
cfg_.rc_target_bitrate = 8000;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
ASSERT_GE(target_level_, level_);
|
||||
}
|
||||
|
||||
// Test for keeping level stats only
|
||||
TEST_P(LevelTest, TestTargetLevel0) {
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
|
||||
40);
|
||||
target_level_ = 0;
|
||||
min_gf_internal_ = 4;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
ASSERT_GE(11, level_);
|
||||
|
||||
cfg_.rc_target_bitrate = 1600;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
ASSERT_GE(20, level_);
|
||||
}
|
||||
|
||||
// Test for level control being turned off
|
||||
TEST_P(LevelTest, TestTargetLevel255) {
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
|
||||
30);
|
||||
target_level_ = 255;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
TEST_P(LevelTest, TestTargetLevelApi) {
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, 1);
|
||||
static const vpx_codec_iface_t *codec = &vpx_codec_vp9_cx_algo;
|
||||
vpx_codec_ctx_t enc;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(codec, &cfg, 0));
|
||||
cfg.rc_target_bitrate = 100;
|
||||
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, codec, &cfg, 0));
|
||||
for (int level = 0; level <= 256; ++level) {
|
||||
if (level == 10 || level == 11 || level == 20 || level == 21 ||
|
||||
level == 30 || level == 31 || level == 40 || level == 41 ||
|
||||
level == 50 || level == 51 || level == 52 || level == 60 ||
|
||||
level == 61 || level == 62 || level == 0 || level == 1 || level == 255)
|
||||
EXPECT_EQ(VPX_CODEC_OK,
|
||||
vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level));
|
||||
else
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
|
||||
vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level));
|
||||
}
|
||||
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc));
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(LevelTest,
|
||||
::testing::Values(::libvpx_test::kTwoPassGood,
|
||||
::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 9));
|
||||
} // namespace
|
678
test/lpf_8_test.cc
Normal file
678
test/lpf_8_test.cc
Normal file
@ -0,0 +1,678 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vpx_config.h"
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "test/acm_random.h"
|
||||
#include "test/clear_system_state.h"
|
||||
#include "test/register_state_check.h"
|
||||
#include "test/util.h"
|
||||
#include "vp9/common/vp9_entropy.h"
|
||||
#include "vp9/common/vp9_loopfilter.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
namespace {
|
||||
// Horizontally and Vertically need 32x32: 8 Coeffs preceeding filtered section
|
||||
// 16 Coefs within filtered section
|
||||
// 8 Coeffs following filtered section
|
||||
const int kNumCoeffs = 1024;
|
||||
|
||||
const int number_of_iterations = 10000;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
typedef void (*loop_op_t)(uint16_t *s, int p, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh,
|
||||
int bd);
|
||||
typedef void (*dual_loop_op_t)(uint16_t *s, int p, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0,
|
||||
const uint8_t *blimit1, const uint8_t *limit1,
|
||||
const uint8_t *thresh1, int bd);
|
||||
#else
|
||||
typedef void (*loop_op_t)(uint8_t *s, int p, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh);
|
||||
typedef void (*dual_loop_op_t)(uint8_t *s, int p, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0,
|
||||
const uint8_t *blimit1, const uint8_t *limit1,
|
||||
const uint8_t *thresh1);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
typedef std::tr1::tuple<loop_op_t, loop_op_t, int> loop8_param_t;
|
||||
typedef std::tr1::tuple<dual_loop_op_t, dual_loop_op_t, int> dualloop8_param_t;
|
||||
|
||||
class Loop8Test6Param : public ::testing::TestWithParam<loop8_param_t> {
|
||||
public:
|
||||
virtual ~Loop8Test6Param() {}
|
||||
virtual void SetUp() {
|
||||
loopfilter_op_ = GET_PARAM(0);
|
||||
ref_loopfilter_op_ = GET_PARAM(1);
|
||||
bit_depth_ = GET_PARAM(2);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
int bit_depth_;
|
||||
int mask_;
|
||||
loop_op_t loopfilter_op_;
|
||||
loop_op_t ref_loopfilter_op_;
|
||||
};
|
||||
|
||||
class Loop8Test9Param : public ::testing::TestWithParam<dualloop8_param_t> {
|
||||
public:
|
||||
virtual ~Loop8Test9Param() {}
|
||||
virtual void SetUp() {
|
||||
loopfilter_op_ = GET_PARAM(0);
|
||||
ref_loopfilter_op_ = GET_PARAM(1);
|
||||
bit_depth_ = GET_PARAM(2);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
int bit_depth_;
|
||||
int mask_;
|
||||
dual_loop_op_t loopfilter_op_;
|
||||
dual_loop_op_t ref_loopfilter_op_;
|
||||
};
|
||||
|
||||
TEST_P(Loop8Test6Param, OperationCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int32_t bd = bit_depth_;
|
||||
DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
|
||||
#else
|
||||
DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
|
||||
DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
|
||||
DECLARE_ALIGNED(16, const uint8_t, limit[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = rnd.Rand8();
|
||||
DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
int32_t p = kNumCoeffs/32;
|
||||
|
||||
uint16_t tmp_s[kNumCoeffs];
|
||||
int j = 0;
|
||||
while (j < kNumCoeffs) {
|
||||
uint8_t val = rnd.Rand8();
|
||||
if (val & 0x80) { // 50% chance to choose a new value.
|
||||
tmp_s[j] = rnd.Rand16();
|
||||
j++;
|
||||
} else { // 50% chance to repeat previous value in row X times
|
||||
int k = 0;
|
||||
while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
|
||||
if (j < 1) {
|
||||
tmp_s[j] = rnd.Rand16();
|
||||
} else if (val & 0x20) { // Increment by an value within the limit
|
||||
tmp_s[j] = (tmp_s[j - 1] + (*limit - 1));
|
||||
} else { // Decrement by an value within the limit
|
||||
tmp_s[j] = (tmp_s[j - 1] - (*limit - 1));
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < kNumCoeffs; j++) {
|
||||
if (i % 2) {
|
||||
s[j] = tmp_s[j] & mask_;
|
||||
} else {
|
||||
s[j] = tmp_s[p * (j % p) + j / p] & mask_;
|
||||
}
|
||||
ref_s[j] = s[j];
|
||||
}
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bd);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bd));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test6Param, C output doesn't match SSE2 "
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
TEST_P(Loop8Test6Param, ValueCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int32_t bd = bit_depth_;
|
||||
DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
|
||||
#else
|
||||
DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
|
||||
// NOTE: The code in vp9_loopfilter.c:update_sharpness computes mblim as a
|
||||
// function of sharpness_lvl and the loopfilter lvl as:
|
||||
// block_inside_limit = lvl >> ((sharpness_lvl > 0) + (sharpness_lvl > 4));
|
||||
// ...
|
||||
// memset(lfi->lfthr[lvl].mblim, (2 * (lvl + 2) + block_inside_limit),
|
||||
// SIMD_WIDTH);
|
||||
// This means that the largest value for mblim will occur when sharpness_lvl
|
||||
// is equal to 0, and lvl is equal to its greatest value (MAX_LOOP_FILTER).
|
||||
// In this case block_inside_limit will be equal to MAX_LOOP_FILTER and
|
||||
// therefore mblim will be equal to (2 * (lvl + 2) + block_inside_limit) =
|
||||
// 2 * (MAX_LOOP_FILTER + 2) + MAX_LOOP_FILTER = 3 * MAX_LOOP_FILTER + 4
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
|
||||
DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
|
||||
DECLARE_ALIGNED(16, const uint8_t, limit[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = rnd.Rand8();
|
||||
DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
int32_t p = kNumCoeffs / 32;
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
s[j] = rnd.Rand16() & mask_;
|
||||
ref_s[j] = s[j];
|
||||
}
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bd);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bd));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test6Param, C output doesn't match SSE2 "
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
TEST_P(Loop8Test9Param, OperationCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int32_t bd = bit_depth_;
|
||||
DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
|
||||
#else
|
||||
DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
|
||||
DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
|
||||
DECLARE_ALIGNED(16, const uint8_t, limit0[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = rnd.Rand8();
|
||||
DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
|
||||
DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
|
||||
DECLARE_ALIGNED(16, const uint8_t, limit1[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = rnd.Rand8();
|
||||
DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
int32_t p = kNumCoeffs / 32;
|
||||
uint16_t tmp_s[kNumCoeffs];
|
||||
int j = 0;
|
||||
const uint8_t limit = *limit0 < *limit1 ? *limit0 : *limit1;
|
||||
while (j < kNumCoeffs) {
|
||||
uint8_t val = rnd.Rand8();
|
||||
if (val & 0x80) { // 50% chance to choose a new value.
|
||||
tmp_s[j] = rnd.Rand16();
|
||||
j++;
|
||||
} else { // 50% chance to repeat previous value in row X times.
|
||||
int k = 0;
|
||||
while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
|
||||
if (j < 1) {
|
||||
tmp_s[j] = rnd.Rand16();
|
||||
} else if (val & 0x20) { // Increment by a value within the limit.
|
||||
tmp_s[j] = (tmp_s[j - 1] + (limit - 1));
|
||||
} else { // Decrement by an value within the limit.
|
||||
tmp_s[j] = (tmp_s[j - 1] - (limit - 1));
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < kNumCoeffs; j++) {
|
||||
if (i % 2) {
|
||||
s[j] = tmp_s[j] & mask_;
|
||||
} else {
|
||||
s[j] = tmp_s[p * (j % p) + j / p] & mask_;
|
||||
}
|
||||
ref_s[j] = s[j];
|
||||
}
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
|
||||
blimit1, limit1, thresh1, bd);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
|
||||
blimit1, limit1, thresh1, bd));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
|
||||
blimit1, limit1, thresh1);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
|
||||
blimit1, limit1, thresh1));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test9Param, C output doesn't match SSE2 "
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
TEST_P(Loop8Test9Param, ValueCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
|
||||
#else
|
||||
DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
|
||||
DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
|
||||
DECLARE_ALIGNED(16, const uint8_t, limit0[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = rnd.Rand8();
|
||||
DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
|
||||
DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
|
||||
DECLARE_ALIGNED(16, const uint8_t, limit1[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
tmp = rnd.Rand8();
|
||||
DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = {
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
|
||||
};
|
||||
int32_t p = kNumCoeffs / 32; // TODO(pdlf) can we have non-square here?
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
s[j] = rnd.Rand16() & mask_;
|
||||
ref_s[j] = s[j];
|
||||
}
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const int32_t bd = bit_depth_;
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
|
||||
blimit1, limit1, thresh1, bd);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
|
||||
thresh0, blimit1, limit1, thresh1, bd));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
|
||||
blimit1, limit1, thresh1);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
|
||||
blimit1, limit1, thresh1));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test9Param, C output doesn't match SSE2"
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
#if HAVE_MMX && CONFIG_USE_X86INC && !CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MMX, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_mmx,
|
||||
&vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_mmx,
|
||||
&vpx_lpf_vertical_4_c, 8)));
|
||||
#endif // HAVE_MMX
|
||||
|
||||
#if HAVE_SSE2
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_edge_8_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2,
|
||||
&vpx_highbd_lpf_horizontal_edge_16_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_edge_8_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2,
|
||||
&vpx_highbd_lpf_horizontal_edge_16_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_edge_8_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2,
|
||||
&vpx_highbd_lpf_horizontal_edge_16_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_8_sse2,
|
||||
&vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_8_sse2,
|
||||
&vpx_lpf_horizontal_edge_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_16_sse2,
|
||||
&vpx_lpf_horizontal_edge_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_sse2,
|
||||
&vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_sse2,
|
||||
&vpx_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dual_sse2,
|
||||
&vpx_lpf_vertical_16_dual_c, 8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif
|
||||
|
||||
#if HAVE_AVX2 && (!CONFIG_VP9_HIGHBITDEPTH)
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
AVX2, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_edge_8_avx2,
|
||||
&vpx_lpf_horizontal_edge_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_16_avx2,
|
||||
&vpx_lpf_horizontal_edge_16_c, 8)));
|
||||
#endif
|
||||
|
||||
#if HAVE_SSE2
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test9Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test9Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_sse2,
|
||||
&vpx_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_sse2,
|
||||
&vpx_lpf_vertical_8_dual_c, 8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif
|
||||
|
||||
#if HAVE_NEON
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
// No neon high bitdepth functions.
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
#if HAVE_NEON_ASM
|
||||
// Using #if inside the macro is unsupported on MSVS but the tests are not
|
||||
// currently built for MSVS with ARM and NEON.
|
||||
make_tuple(&vpx_lpf_horizontal_edge_8_neon,
|
||||
&vpx_lpf_horizontal_edge_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_16_neon,
|
||||
&vpx_lpf_horizontal_edge_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_neon,
|
||||
&vpx_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dual_neon,
|
||||
&vpx_lpf_vertical_16_dual_c, 8),
|
||||
#endif // HAVE_NEON_ASM
|
||||
make_tuple(&vpx_lpf_horizontal_8_neon,
|
||||
&vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_neon,
|
||||
&vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_4_neon,
|
||||
&vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_neon,
|
||||
&vpx_lpf_vertical_4_c, 8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Loop8Test9Param,
|
||||
::testing::Values(
|
||||
#if HAVE_NEON_ASM
|
||||
make_tuple(&vpx_lpf_horizontal_8_dual_neon,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_neon,
|
||||
&vpx_lpf_vertical_8_dual_c, 8),
|
||||
#endif // HAVE_NEON_ASM
|
||||
make_tuple(&vpx_lpf_horizontal_4_dual_neon,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_neon,
|
||||
&vpx_lpf_vertical_4_dual_c, 8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
DSPR2, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_dspr2,
|
||||
&vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dspr2,
|
||||
&vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_8,
|
||||
&vpx_lpf_horizontal_edge_8, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_16,
|
||||
&vpx_lpf_horizontal_edge_16, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dspr2,
|
||||
&vpx_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dspr2,
|
||||
&vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dspr2,
|
||||
&vpx_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dual_dspr2,
|
||||
&vpx_lpf_vertical_16_dual_c, 8)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
DSPR2, Loop8Test9Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_dual_dspr2,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dual_dspr2,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_dspr2,
|
||||
&vpx_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_dspr2,
|
||||
&vpx_lpf_vertical_8_dual_c, 8)));
|
||||
#endif // HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_msa,
|
||||
&vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_msa,
|
||||
&vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_8_msa,
|
||||
&vpx_lpf_horizontal_edge_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_edge_16_msa,
|
||||
&vpx_lpf_horizontal_edge_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_msa,
|
||||
&vpx_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_msa,
|
||||
&vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_msa,
|
||||
&vpx_lpf_vertical_16_c, 8)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Loop8Test9Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_dual_msa,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dual_msa,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_msa,
|
||||
&vpx_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_msa,
|
||||
&vpx_lpf_vertical_8_dual_c, 8)));
|
||||
#endif // HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
|
||||
|
||||
} // namespace
|
684
test/lpf_test.cc
684
test/lpf_test.cc
@ -1,684 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vpx_config.h"
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "test/acm_random.h"
|
||||
#include "test/clear_system_state.h"
|
||||
#include "test/register_state_check.h"
|
||||
#include "test/util.h"
|
||||
#include "vp9/common/vp9_entropy.h"
|
||||
#include "vp9/common/vp9_loopfilter.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
namespace {
|
||||
// Horizontally and Vertically need 32x32: 8 Coeffs preceeding filtered section
|
||||
// 16 Coefs within filtered section
|
||||
// 8 Coeffs following filtered section
|
||||
const int kNumCoeffs = 1024;
|
||||
|
||||
const int number_of_iterations = 10000;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
typedef uint16_t Pixel;
|
||||
#define PIXEL_WIDTH 16
|
||||
|
||||
typedef void (*loop_op_t)(Pixel *s, int p, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh, int bd);
|
||||
typedef void (*dual_loop_op_t)(Pixel *s, int p, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0,
|
||||
const uint8_t *blimit1, const uint8_t *limit1,
|
||||
const uint8_t *thresh1, int bd);
|
||||
#else
|
||||
typedef uint8_t Pixel;
|
||||
#define PIXEL_WIDTH 8
|
||||
|
||||
typedef void (*loop_op_t)(Pixel *s, int p, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh);
|
||||
typedef void (*dual_loop_op_t)(Pixel *s, int p, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0,
|
||||
const uint8_t *blimit1, const uint8_t *limit1,
|
||||
const uint8_t *thresh1);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
typedef ::testing::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;
|
||||
|
||||
void InitInput(Pixel *s, Pixel *ref_s, ACMRandom *rnd, const uint8_t limit,
|
||||
const int mask, const int32_t p, const int i) {
|
||||
uint16_t tmp_s[kNumCoeffs];
|
||||
|
||||
for (int j = 0; j < kNumCoeffs;) {
|
||||
const uint8_t val = rnd->Rand8();
|
||||
if (val & 0x80) { // 50% chance to choose a new value.
|
||||
tmp_s[j] = rnd->Rand16();
|
||||
j++;
|
||||
} else { // 50% chance to repeat previous value in row X times.
|
||||
int k = 0;
|
||||
while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
|
||||
if (j < 1) {
|
||||
tmp_s[j] = rnd->Rand16();
|
||||
} else if (val & 0x20) { // Increment by a value within the limit.
|
||||
tmp_s[j] = tmp_s[j - 1] + (limit - 1);
|
||||
} else { // Decrement by a value within the limit.
|
||||
tmp_s[j] = tmp_s[j - 1] - (limit - 1);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs;) {
|
||||
const uint8_t val = rnd->Rand8();
|
||||
if (val & 0x80) {
|
||||
j++;
|
||||
} else { // 50% chance to repeat previous value in column X times.
|
||||
int k = 0;
|
||||
while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
|
||||
if (j < 1) {
|
||||
tmp_s[j] = rnd->Rand16();
|
||||
} else if (val & 0x20) { // Increment by a value within the limit.
|
||||
tmp_s[(j % 32) * 32 + j / 32] =
|
||||
tmp_s[((j - 1) % 32) * 32 + (j - 1) / 32] + (limit - 1);
|
||||
} else { // Decrement by a value within the limit.
|
||||
tmp_s[(j % 32) * 32 + j / 32] =
|
||||
tmp_s[((j - 1) % 32) * 32 + (j - 1) / 32] - (limit - 1);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; j++) {
|
||||
if (i % 2) {
|
||||
s[j] = tmp_s[j] & mask;
|
||||
} else {
|
||||
s[j] = tmp_s[p * (j % p) + j / p] & mask;
|
||||
}
|
||||
ref_s[j] = s[j];
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
public:
|
||||
virtual ~Loop8Test6Param() {}
|
||||
virtual void SetUp() {
|
||||
loopfilter_op_ = GET_PARAM(0);
|
||||
ref_loopfilter_op_ = GET_PARAM(1);
|
||||
bit_depth_ = GET_PARAM(2);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
int bit_depth_;
|
||||
int mask_;
|
||||
loop_op_t loopfilter_op_;
|
||||
loop_op_t ref_loopfilter_op_;
|
||||
};
|
||||
|
||||
class Loop8Test9Param : public ::testing::TestWithParam<dualloop8_param_t> {
|
||||
public:
|
||||
virtual ~Loop8Test9Param() {}
|
||||
virtual void SetUp() {
|
||||
loopfilter_op_ = GET_PARAM(0);
|
||||
ref_loopfilter_op_ = GET_PARAM(1);
|
||||
bit_depth_ = GET_PARAM(2);
|
||||
mask_ = (1 << bit_depth_) - 1;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
int bit_depth_;
|
||||
int mask_;
|
||||
dual_loop_op_t loopfilter_op_;
|
||||
dual_loop_op_t ref_loopfilter_op_;
|
||||
};
|
||||
|
||||
TEST_P(Loop8Test6Param, OperationCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
const int32_t p = kNumCoeffs / 32;
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = GetOuterThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetInnerThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetHevThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
InitInput(s, ref_s, &rnd, *limit, mask_, p, i);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test6Param, C output doesn't match SSE2 "
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
TEST_P(Loop8Test6Param, ValueCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
|
||||
// NOTE: The code in vp9_loopfilter.c:update_sharpness computes mblim as a
|
||||
// function of sharpness_lvl and the loopfilter lvl as:
|
||||
// block_inside_limit = lvl >> ((sharpness_lvl > 0) + (sharpness_lvl > 4));
|
||||
// ...
|
||||
// memset(lfi->lfthr[lvl].mblim, (2 * (lvl + 2) + block_inside_limit),
|
||||
// SIMD_WIDTH);
|
||||
// This means that the largest value for mblim will occur when sharpness_lvl
|
||||
// is equal to 0, and lvl is equal to its greatest value (MAX_LOOP_FILTER).
|
||||
// In this case block_inside_limit will be equal to MAX_LOOP_FILTER and
|
||||
// therefore mblim will be equal to (2 * (lvl + 2) + block_inside_limit) =
|
||||
// 2 * (MAX_LOOP_FILTER + 2) + MAX_LOOP_FILTER = 3 * MAX_LOOP_FILTER + 4
|
||||
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = GetOuterThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetInnerThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetHevThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
int32_t p = kNumCoeffs / 32;
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
s[j] = rnd.Rand16() & mask_;
|
||||
ref_s[j] = s[j];
|
||||
}
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test6Param, C output doesn't match SSE2 "
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
TEST_P(Loop8Test9Param, OperationCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = GetOuterThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetInnerThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetHevThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetOuterThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetInnerThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetHevThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
int32_t p = kNumCoeffs / 32;
|
||||
const uint8_t limit = *limit0 < *limit1 ? *limit0 : *limit1;
|
||||
InitInput(s, ref_s, &rnd, limit, mask_, p, i);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
|
||||
limit1, thresh1, bit_depth_);
|
||||
ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
|
||||
thresh0, blimit1, limit1, thresh1,
|
||||
bit_depth_));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
|
||||
limit1, thresh1);
|
||||
ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
|
||||
thresh0, blimit1, limit1, thresh1));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test9Param, C output doesn't match SSE2 "
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
TEST_P(Loop8Test9Param, ValueCheck) {
|
||||
ACMRandom rnd(ACMRandom::DeterministicSeed());
|
||||
const int count_test_block = number_of_iterations;
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
|
||||
DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
|
||||
int err_count_total = 0;
|
||||
int first_failure = -1;
|
||||
for (int i = 0; i < count_test_block; ++i) {
|
||||
int err_count = 0;
|
||||
uint8_t tmp = GetOuterThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetInnerThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetHevThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetOuterThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetInnerThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
tmp = GetHevThresh(&rnd);
|
||||
DECLARE_ALIGNED(16, const uint8_t,
|
||||
thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
|
||||
tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
|
||||
int32_t p = kNumCoeffs / 32; // TODO(pdlf) can we have non-square here?
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
s[j] = rnd.Rand16() & mask_;
|
||||
ref_s[j] = s[j];
|
||||
}
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
|
||||
limit1, thresh1, bit_depth_);
|
||||
ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
|
||||
thresh0, blimit1, limit1, thresh1,
|
||||
bit_depth_));
|
||||
#else
|
||||
ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
|
||||
limit1, thresh1);
|
||||
ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
|
||||
thresh0, blimit1, limit1, thresh1));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
for (int j = 0; j < kNumCoeffs; ++j) {
|
||||
err_count += ref_s[j] != s[j];
|
||||
}
|
||||
if (err_count && !err_count_total) {
|
||||
first_failure = i;
|
||||
}
|
||||
err_count_total += err_count;
|
||||
}
|
||||
EXPECT_EQ(0, err_count_total)
|
||||
<< "Error: Loop8Test9Param, C output doesn't match SSE2"
|
||||
"loopfilter output. "
|
||||
<< "First failed at test case " << first_failure;
|
||||
}
|
||||
|
||||
using ::testing::make_tuple;
|
||||
|
||||
#if HAVE_SSE2
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test6Param,
|
||||
::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
|
||||
&vpx_highbd_lpf_horizontal_16_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_16_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
|
||||
&vpx_highbd_lpf_horizontal_16_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_16_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
|
||||
&vpx_highbd_lpf_horizontal_16_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_16_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_sse2, &vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_sse2, &vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_sse2, &vpx_lpf_horizontal_16_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_dual_sse2,
|
||||
&vpx_lpf_horizontal_16_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_sse2, &vpx_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_sse2, &vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_sse2, &vpx_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dual_sse2, &vpx_lpf_vertical_16_dual_c,
|
||||
8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif
|
||||
|
||||
#if HAVE_AVX2 && (!CONFIG_VP9_HIGHBITDEPTH)
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
AVX2, Loop8Test6Param,
|
||||
::testing::Values(make_tuple(&vpx_lpf_horizontal_16_avx2,
|
||||
&vpx_lpf_horizontal_16_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_dual_avx2,
|
||||
&vpx_lpf_horizontal_16_dual_c, 8)));
|
||||
#endif
|
||||
|
||||
#if HAVE_SSE2
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test9Param,
|
||||
::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SSE2, Loop8Test9Param,
|
||||
::testing::Values(make_tuple(&vpx_lpf_horizontal_4_dual_sse2,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dual_sse2,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_sse2,
|
||||
&vpx_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_sse2,
|
||||
&vpx_lpf_vertical_8_dual_c, 8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif
|
||||
|
||||
#if HAVE_NEON
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Loop8Test6Param,
|
||||
::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_neon,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_neon,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_neon,
|
||||
&vpx_highbd_lpf_horizontal_4_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_neon,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_neon,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_neon,
|
||||
&vpx_highbd_lpf_horizontal_8_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_neon,
|
||||
&vpx_highbd_lpf_horizontal_16_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_neon,
|
||||
&vpx_highbd_lpf_horizontal_16_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_neon,
|
||||
&vpx_highbd_lpf_horizontal_16_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_16_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_16_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_16_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_16_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_neon,
|
||||
&vpx_highbd_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_neon,
|
||||
&vpx_highbd_lpf_vertical_4_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_neon,
|
||||
&vpx_highbd_lpf_vertical_4_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_neon,
|
||||
&vpx_highbd_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_neon,
|
||||
&vpx_highbd_lpf_vertical_8_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_neon,
|
||||
&vpx_highbd_lpf_vertical_8_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_neon,
|
||||
&vpx_highbd_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_neon,
|
||||
&vpx_highbd_lpf_vertical_16_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_neon,
|
||||
&vpx_highbd_lpf_vertical_16_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_16_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_16_dual_c, 12)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Loop8Test9Param,
|
||||
::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_4_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_4_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_horizontal_8_dual_neon,
|
||||
&vpx_highbd_lpf_horizontal_8_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_4_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_4_dual_c, 12),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 8),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 10),
|
||||
make_tuple(&vpx_highbd_lpf_vertical_8_dual_neon,
|
||||
&vpx_highbd_lpf_vertical_8_dual_c, 12)));
|
||||
#else
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_16_neon, &vpx_lpf_horizontal_16_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_dual_neon,
|
||||
&vpx_lpf_horizontal_16_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_neon, &vpx_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dual_neon, &vpx_lpf_vertical_16_dual_c,
|
||||
8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_neon, &vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_neon, &vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_4_neon, &vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_neon, &vpx_lpf_vertical_4_c, 8)));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
NEON, Loop8Test9Param,
|
||||
::testing::Values(make_tuple(&vpx_lpf_horizontal_8_dual_neon,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_neon,
|
||||
&vpx_lpf_vertical_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_4_dual_neon,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_neon,
|
||||
&vpx_lpf_vertical_4_dual_c, 8)));
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // HAVE_NEON
|
||||
|
||||
#if HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
DSPR2, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_dspr2, &vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dspr2, &vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_dspr2, &vpx_lpf_horizontal_16_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_dual_dspr2,
|
||||
&vpx_lpf_horizontal_16_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dspr2, &vpx_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dspr2, &vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dspr2, &vpx_lpf_vertical_16_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_dual_dspr2, &vpx_lpf_vertical_16_dual_c,
|
||||
8)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
DSPR2, Loop8Test9Param,
|
||||
::testing::Values(make_tuple(&vpx_lpf_horizontal_4_dual_dspr2,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dual_dspr2,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_dspr2,
|
||||
&vpx_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_dspr2,
|
||||
&vpx_lpf_vertical_8_dual_c, 8)));
|
||||
#endif // HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Loop8Test6Param,
|
||||
::testing::Values(
|
||||
make_tuple(&vpx_lpf_horizontal_4_msa, &vpx_lpf_horizontal_4_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_msa, &vpx_lpf_horizontal_8_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_msa, &vpx_lpf_horizontal_16_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_16_dual_msa,
|
||||
&vpx_lpf_horizontal_16_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_msa, &vpx_lpf_vertical_4_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_msa, &vpx_lpf_vertical_8_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_16_msa, &vpx_lpf_vertical_16_c, 8)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
MSA, Loop8Test9Param,
|
||||
::testing::Values(make_tuple(&vpx_lpf_horizontal_4_dual_msa,
|
||||
&vpx_lpf_horizontal_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_horizontal_8_dual_msa,
|
||||
&vpx_lpf_horizontal_8_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_4_dual_msa,
|
||||
&vpx_lpf_vertical_4_dual_c, 8),
|
||||
make_tuple(&vpx_lpf_vertical_8_dual_msa,
|
||||
&vpx_lpf_vertical_8_dual_c, 8)));
|
||||
#endif // HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
|
||||
|
||||
} // namespace
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user