Compare commits
1 Commits
mandarindu
...
mcw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
313e5b9292 |
@@ -1,97 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Google
|
||||
# Generated with clang-format 4.0.1
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlinesLeft: true
|
||||
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
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
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
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
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
|
||||
...
|
||||
|
||||
73
.gitignore
vendored
73
.gitignore
vendored
@@ -1,19 +1,15 @@
|
||||
*.S
|
||||
*.a
|
||||
*.asm.s
|
||||
*.d
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.o
|
||||
*~
|
||||
.cproject
|
||||
.project
|
||||
.settings
|
||||
/*.ivf
|
||||
/*.ivf.md5
|
||||
/*-*.mk
|
||||
/*.asm
|
||||
/*.doxy
|
||||
/*.ivf
|
||||
/*.ivf.md5
|
||||
/.bins
|
||||
/.deps
|
||||
/.docs
|
||||
@@ -22,47 +18,58 @@
|
||||
/Makefile
|
||||
/config.log
|
||||
/config.mk
|
||||
/decode_to_md5
|
||||
/decode_to_md5.c
|
||||
/decode_to_md5.dox
|
||||
/decode_with_drops
|
||||
/decode_with_drops.c
|
||||
/decode_with_drops.dox
|
||||
/docs/
|
||||
/doxyfile
|
||||
/examples/*.dox
|
||||
/examples/decode_to_md5
|
||||
/examples/decode_with_drops
|
||||
/examples/decode_with_partial_drops
|
||||
/examples/example_xma
|
||||
/examples/postproc
|
||||
/examples/resize_util
|
||||
/examples/set_maps
|
||||
/examples/simple_decoder
|
||||
/examples/simple_encoder
|
||||
/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/vpx_temporal_svc_encoder
|
||||
/error_resilient
|
||||
/error_resilient.c
|
||||
/error_resilient.dox
|
||||
/force_keyframe
|
||||
/force_keyframe.c
|
||||
/force_keyframe.dox
|
||||
/ivfdec
|
||||
/ivfdec.dox
|
||||
/ivfenc
|
||||
/ivfenc.dox
|
||||
/libvpx.so*
|
||||
/libvpx.ver
|
||||
/obj_int_extract
|
||||
/postproc
|
||||
/postproc.c
|
||||
/postproc.dox
|
||||
/samples.dox
|
||||
/test_intra_pred_speed
|
||||
/simple_decoder
|
||||
/simple_decoder.c
|
||||
/simple_decoder.dox
|
||||
/simple_encoder
|
||||
/simple_encoder.c
|
||||
/simple_encoder.dox
|
||||
/test_libvpx
|
||||
/tools.dox
|
||||
/tools/*.dox
|
||||
/tools/tiny_ssim
|
||||
/twopass_encoder
|
||||
/twopass_encoder.c
|
||||
/twopass_encoder.dox
|
||||
/vp8_api1_migration.dox
|
||||
/vp[89x]_rtcd.h
|
||||
/vp8_scalable_patterns
|
||||
/vp8_scalable_patterns.dox
|
||||
/vp8_set_maps
|
||||
/vp8_set_maps.c
|
||||
/vp8_set_maps.dox
|
||||
/vp8cx_set_ref
|
||||
/vp8cx_set_ref.c
|
||||
/vp8cx_set_ref.dox
|
||||
/vpx.pc
|
||||
/vpx_config.c
|
||||
/vpx_config.h
|
||||
/vpx_dsp_rtcd.h
|
||||
/vpx_scale_rtcd.h
|
||||
/vpx_rtcd.h
|
||||
/vpx_version.h
|
||||
/vpxdec
|
||||
/vpxdec.dox
|
||||
/vpxenc
|
||||
/vpxenc.dox
|
||||
TAGS
|
||||
.cproject
|
||||
.project
|
||||
.settings
|
||||
|
||||
40
.mailmap
40
.mailmap
@@ -1,42 +1,18 @@
|
||||
Adrian Grange <agrange@google.com>
|
||||
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>
|
||||
Hangyu Kuang <hkuang@google.com>
|
||||
Hui Su <huisu@google.com>
|
||||
Jacky Chen <jackychen@google.com>
|
||||
Jim Bankoski <jimbankoski@google.com>
|
||||
John Koleszar <jkoleszar@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>
|
||||
Johann Koenig <johannkoenig@google.com> <johannkoenig@dhcp-172-19-7-52.mtv.corp.google.com>
|
||||
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>
|
||||
Sami Pietilä <samipietila@google.com>
|
||||
Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com>
|
||||
Timothy B. Terriberry <tterribe@xiph.org> Tim Terriberry <tterriberry@mozilla.com>
|
||||
Tom Finegan <tomfinegan@google.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>
|
||||
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>
|
||||
Alpha Lam <hclam@google.com> <hclam@chromium.org>
|
||||
Deb Mukherjee <debargha@google.com>
|
||||
Yaowu Xu <yaowu@google.com> <yaowu@xuyaowu.com>
|
||||
Yaowu Xu <yaowu@google.com> <Yaowu Xu>
|
||||
|
||||
76
AUTHORS
76
AUTHORS
@@ -4,12 +4,9 @@
|
||||
Aaron Watry <awatry@gmail.com>
|
||||
Abo Talib Mahfoodh <ab.mahfoodh@gmail.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>
|
||||
Alex Converse <alex.converse@gmail.com>
|
||||
Alexis Ballier <aballier@gentoo.org>
|
||||
Alok Ahuja <waveletcoeff@gmail.com>
|
||||
Alpha Lam <hclam@google.com>
|
||||
@@ -17,80 +14,44 @@ 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>
|
||||
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>
|
||||
Ed Baker <edward.baker@intel.com>
|
||||
Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
Erik Niemeyer <erik.a.niemeyer@intel.com>
|
||||
Erik Niemeyer <erik.a.niemeyer@gmail.com>
|
||||
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>
|
||||
James Berry <jamesberry@google.com>
|
||||
James Yu <james.yu@linaro.org>
|
||||
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>
|
||||
Johann Koenig <johannkoenig@google.com>
|
||||
John Koleszar <jkoleszar@google.com>
|
||||
Johnny Klonaris <google@jawknee.com>
|
||||
John Stark <jhnstrk@gmail.com>
|
||||
Joshua Bleecher Snyder <josh@treelinelabs.com>
|
||||
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,67 +65,36 @@ 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>
|
||||
Patrik Westin <patrik.westin@gmail.com>
|
||||
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>
|
||||
Ronald S. Bultje <rbultje@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>
|
||||
Tao Bai <michaelbai@chromium.org>
|
||||
Tero Rintaluoma <teror@google.com>
|
||||
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
|
||||
The Xiph.Org Foundation
|
||||
|
||||
111
CHANGELOG
111
CHANGELOG
@@ -1,114 +1,3 @@
|
||||
2017-01-04 v1.7.0 "Mandarin Duck"
|
||||
This release focused on high bit depth performance (10/12 bit) and vp9
|
||||
encoding improvements.
|
||||
|
||||
- Upgrading:
|
||||
This release is ABI incompatible due to new vp9 encoder features.
|
||||
|
||||
Frame parallel decoding for vp9 has been removed.
|
||||
|
||||
- Enhancements:
|
||||
vp9 encoding supports additional threads with --row-mt. This can be greater
|
||||
than the number of tiles.
|
||||
|
||||
Two new vp9 encoder options have been added:
|
||||
--corpus-complexity
|
||||
--tune-content=film
|
||||
|
||||
Additional tooling for respecting the vp9 "level" profiles has been added.
|
||||
|
||||
- Bug fixes:
|
||||
A variety of fuzzing issues.
|
||||
vp8 threading fix for ARM.
|
||||
Codec control VP9_SET_SKIP_LOOP_FILTER fixed.
|
||||
Reject invalid multi resolution configurations.
|
||||
|
||||
2017-01-09 v1.6.1 "Long Tailed Duck"
|
||||
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.
|
||||
|
||||
2015-11-09 v1.5.0 "Javan Whistling Duck"
|
||||
This release improves upon the VP9 encoder and speeds up the encoding and
|
||||
decoding processes.
|
||||
|
||||
- Upgrading:
|
||||
This release is ABI incompatible with 1.4.0. It drops deprecated VP8
|
||||
controls and adds a variety of VP9 controls for testing.
|
||||
|
||||
The vpxenc utility now prefers VP9 by default.
|
||||
|
||||
- Enhancements:
|
||||
Faster VP9 encoding and decoding
|
||||
Smaller library size by combining functions used by VP8 and VP9
|
||||
|
||||
- Bug Fixes:
|
||||
A variety of fuzzing issues
|
||||
|
||||
2015-04-03 v1.4.0 "Indian Runner Duck"
|
||||
This release includes significant improvements to the VP9 codec.
|
||||
|
||||
- Upgrading:
|
||||
This release is ABI incompatible with 1.3.0. It drops the compatibility
|
||||
layer, requiring VPX_IMG_FMT_* instead of IMG_FMT_*, and adds several codec
|
||||
controls for VP9.
|
||||
|
||||
- Enhancements:
|
||||
Faster VP9 encoding and decoding
|
||||
Multithreaded VP9 decoding (tile and frame-based)
|
||||
Multithreaded VP9 encoding - on by default
|
||||
YUV 4:2:2 and 4:4:4 support in VP9
|
||||
10 and 12bit support in VP9
|
||||
64bit ARM support by replacing ARM assembly with intrinsics
|
||||
|
||||
- Bug Fixes:
|
||||
Fixes a VP9 bitstream issue in Profile 1. This only affected non-YUV 4:2:0
|
||||
files.
|
||||
|
||||
- Known Issues:
|
||||
Frame Parallel decoding fails for segmented and non-420 files.
|
||||
|
||||
2013-11-15 v1.3.0 "Forest"
|
||||
This release introduces the VP9 codec in a backward-compatible way.
|
||||
All existing users of VP8 can continue to use the library without
|
||||
|
||||
39
PATENTS
39
PATENTS
@@ -1,23 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
------------------------------------
|
||||
|
||||
"These implementations" means the copyrightable works that implement the WebM
|
||||
codecs distributed by Google as part of the WebM Project.
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the WebM Project.
|
||||
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
|
||||
royalty-free, irrevocable (except as stated in this section) patent license to
|
||||
make, have made, use, offer to sell, sell, import, transfer, and otherwise
|
||||
run, modify and propagate the contents of these implementations of WebM, where
|
||||
such license applies only to those patent claims, both currently owned by
|
||||
Google and acquired in the future, licensable by Google that are necessarily
|
||||
infringed by these implementations of WebM. This grant does not include claims
|
||||
that would be infringed only as a consequence of further modification of these
|
||||
implementations. If you or your agent or exclusive licensee institute or order
|
||||
or agree to the institution of patent litigation or any other patent
|
||||
enforcement activity against any entity (including a cross-claim or
|
||||
counterclaim in a lawsuit) alleging that any of these implementations of WebM
|
||||
or any code incorporated within any of these implementations of WebM
|
||||
constitute direct or contributory patent infringement, or inducement of
|
||||
patent infringement, then any patent rights granted to you under this License
|
||||
for these implementations of WebM shall terminate as of the date such
|
||||
litigation is filed.
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer, and otherwise run, modify and propagate the contents of this
|
||||
implementation of VP8, where such license applies only to those patent
|
||||
claims, both currently owned by Google and acquired in the future,
|
||||
licensable by Google that are necessarily infringed by this
|
||||
implementation of VP8. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of VP8 or any code incorporated within this
|
||||
implementation of VP8 constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of VP8
|
||||
shall terminate as of the date such litigation is filed.
|
||||
|
||||
90
README
90
README
@@ -1,4 +1,5 @@
|
||||
README - 24 January 2018
|
||||
vpx Multi-Format Codec SDK
|
||||
README - 1 August 2013
|
||||
|
||||
Welcome to the WebM VP8/VP9 Codec SDK!
|
||||
|
||||
@@ -11,20 +12,22 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
|
||||
* 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[4] and sha1sum.
|
||||
* Building the documentation requires PHP[3] and Doxygen[4]. If you do not
|
||||
have these packages, you must pass --disable-install-docs to the
|
||||
configure script.
|
||||
* Downloading the data for the unit tests requires curl[5] 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[5]. These requirements are optional if not running the unit
|
||||
source[6]. These requirements are optional if not running the unit
|
||||
tests.
|
||||
|
||||
[1]: http://www.tortall.net/projects/yasm
|
||||
[2]: http://www.cygwin.com
|
||||
[3]: http://www.doxygen.org
|
||||
[4]: http://curl.haxx.se
|
||||
[5]: http://www.microbrew.org/tools/md5sha1sum/
|
||||
[3]: http://php.net
|
||||
[4]: http://www.doxygen.org
|
||||
[5]: http://curl.haxx.se
|
||||
[6]: http://www.microbrew.org/tools/md5sha1sum/
|
||||
|
||||
2. Out-of-tree builds
|
||||
Out of tree builds are a supported method of building the application. For
|
||||
@@ -47,9 +50,14 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
--help output of the configure script. As of this writing, the list of
|
||||
available targets is:
|
||||
|
||||
arm64-android-gcc
|
||||
arm64-darwin-gcc
|
||||
arm64-linux-gcc
|
||||
armv5te-android-gcc
|
||||
armv5te-linux-rvct
|
||||
armv5te-linux-gcc
|
||||
armv5te-none-rvct
|
||||
armv6-darwin-gcc
|
||||
armv6-linux-rvct
|
||||
armv6-linux-gcc
|
||||
armv6-none-rvct
|
||||
armv7-android-gcc
|
||||
armv7-darwin-gcc
|
||||
armv7-linux-rvct
|
||||
@@ -57,14 +65,13 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
armv7-none-rvct
|
||||
armv7-win32-vs11
|
||||
armv7-win32-vs12
|
||||
armv7-win32-vs14
|
||||
armv7-win32-vs15
|
||||
armv7s-darwin-gcc
|
||||
armv8-linux-gcc
|
||||
mips32-linux-gcc
|
||||
mips64-linux-gcc
|
||||
ppc32-darwin8-gcc
|
||||
ppc32-darwin9-gcc
|
||||
ppc32-linux-gcc
|
||||
ppc64-darwin8-gcc
|
||||
ppc64-darwin9-gcc
|
||||
ppc64-linux-gcc
|
||||
ppc64le-linux-gcc
|
||||
sparc-solaris-gcc
|
||||
x86-android-gcc
|
||||
x86-darwin8-gcc
|
||||
@@ -75,39 +82,37 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
x86-darwin11-gcc
|
||||
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
|
||||
x86_64-darwin11-gcc
|
||||
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
|
||||
universal-darwin8-gcc
|
||||
universal-darwin9-gcc
|
||||
universal-darwin10-gcc
|
||||
universal-darwin11-gcc
|
||||
universal-darwin12-gcc
|
||||
universal-darwin13-gcc
|
||||
generic-gnu
|
||||
|
||||
The generic-gnu target, in conjunction with the CROSS environment variable,
|
||||
@@ -128,30 +133,7 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
This defaults to config.log. This should give a good indication of what went
|
||||
wrong. If not, contact us for support.
|
||||
|
||||
VP8/VP9 TEST VECTORS:
|
||||
The test vectors can be downloaded and verified using the build system after
|
||||
running configure. To specify an alternate directory the
|
||||
LIBVPX_TEST_DATA_PATH environment variable can be used.
|
||||
|
||||
$ ./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.
|
||||
|
||||
|
||||
37
README_RS
Normal file
37
README_RS
Normal file
@@ -0,0 +1,37 @@
|
||||
Welcome to read this page!
|
||||
|
||||
How to run renderscript in VP9 decode
|
||||
|
||||
1. Compile RenderScript Kernel(We use zero copy this version,
|
||||
if ndk rs module don't support this,
|
||||
it can't pass compile)
|
||||
Because RenderScript need g++, but VP9 use gcc.
|
||||
So we need to compile rs alone as a so library. Then VP9 project load/use it.
|
||||
RS code is in vp9/common/kernel/rs/, there is a compile.sh in that folder,
|
||||
We can use sh to compile rs kernel.(need NDK-r9b or higher, we need to config ndk in path).
|
||||
If compile success, it will gen:
|
||||
vp9_rs_packing.so(vp9/common/kernel/rs/)
|
||||
librs.inter_rs.so(vp9/common/kernel/rs/obj/)
|
||||
libstlport_shared.so(vp9/common/kernel/rs/obj/)
|
||||
|
||||
2. Compile VP9 project
|
||||
Just Compile it normally.
|
||||
|
||||
3. Run vpxdec with RenderScript(We use zero copy this version,
|
||||
if system RS module don't support this,
|
||||
it won't work)
|
||||
[1]: push vp9_rs_packing.so to /data/local/tmp/(or /vendor/lib, /system/lib,
|
||||
need adb remount)
|
||||
[2]: push librs.inter_rs.so to /data/local/tmp/(or /vendor/lib, /system/lib,
|
||||
need adb remount)
|
||||
[3]: push libstlport_shared.so to /data/local/tmp/(or /vendor/lib, /system/lib,
|
||||
need adb remount)
|
||||
[4]: push vpxdec to /data/local/tmp
|
||||
[5]: adb shell (as root)
|
||||
[6]: cd /data/local/tmp (on device)
|
||||
[7]: export RSENABLE=1 (on device, if not, it won't use RS)
|
||||
[8]: export QCTENABLE=1 (on device, enable qct kernel)
|
||||
[9]: export OPENABLE=1 (on device, enable optimized kernel, dependence on system and driver)
|
||||
[10]:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/local/tmp (on device,
|
||||
if we push .so file to /data/local/tmp, we need set this)
|
||||
[11]:run vpxdec normally(on device)
|
||||
131
args.c
131
args.c
@@ -8,13 +8,15 @@
|
||||
* 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"
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__
|
||||
extern void die(const char *fmt, ...) __attribute__((noreturn));
|
||||
@@ -22,36 +24,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 +72,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 +82,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 +99,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 +111,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 +129,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);
|
||||
}
|
||||
|
||||
36
args.h
36
args.h
@@ -8,42 +8,35 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ARGS_H_
|
||||
#define ARGS_H_
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
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);
|
||||
@@ -54,10 +47,5 @@ char **argv_dup(int argc, const char **argv);
|
||||
unsigned int arg_parse_uint(const struct arg *arg);
|
||||
int arg_parse_int(const struct arg *arg);
|
||||
struct vpx_rational arg_parse_rational(const struct arg *arg);
|
||||
int arg_parse_enum(const struct arg *arg);
|
||||
int arg_parse_enum_or_int(const struct arg *arg);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // ARGS_H_
|
||||
|
||||
14
build/arm-msvs/obj_int_extract.bat
Normal file
14
build/arm-msvs/obj_int_extract.bat
Normal file
@@ -0,0 +1,14 @@
|
||||
REM Copyright (c) 2013 The WebM project authors. All Rights Reserved.
|
||||
REM
|
||||
REM Use of this source code is governed by a BSD-style license
|
||||
REM that can be found in the LICENSE file in the root of the source
|
||||
REM tree. An additional intellectual property rights grant can be found
|
||||
REM in the file PATENTS. All contributing project authors may
|
||||
REM be found in the AUTHORS file in the root of the source tree.
|
||||
echo on
|
||||
|
||||
cl /I "./" /I "%1" /nologo /c /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP "%1/vp8/encoder/vp8_asm_enc_offsets.c"
|
||||
obj_int_extract.exe rvds "vp8_asm_enc_offsets.obj" > "vp8_asm_enc_offsets.asm"
|
||||
|
||||
cl /I "./" /I "%1" /nologo /c /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP "%1/vpx_scale/vpx_scale_asm_offsets.c"
|
||||
obj_int_extract.exe rvds "vpx_scale_asm_offsets.obj" > "vpx_scale_asm_offsets.asm"
|
||||
@@ -29,61 +29,36 @@
|
||||
# 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.
|
||||
# Configuring with --disable-runtime-cpu-detect will assume presence of NEON.
|
||||
# Configuring with --disable-runtime-cpu-detect --disable-neon \
|
||||
# --disable-neon-asm
|
||||
# will remove any NEON dependency.
|
||||
# Configuring with --disable-runtime-cpu-detect --disable-neon will remove any
|
||||
# NEON dependency.
|
||||
|
||||
# To change to building armeabi, run ./libvpx/configure again, but with
|
||||
# --target=arm5te-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.
|
||||
# Makefiles created by the libvpx configure process
|
||||
# This will need to be fixed to handle x86.
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
include $(CONFIG_DIR)libs-armv7-android-gcc.mk
|
||||
LOCAL_ARM_MODE := arm
|
||||
else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
|
||||
include $(CONFIG_DIR)libs-arm64-android-gcc.mk
|
||||
LOCAL_ARM_MODE := arm
|
||||
else ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
include $(CONFIG_DIR)libs-x86-android-gcc.mk
|
||||
else ifeq ($(TARGET_ARCH_ABI),x86_64)
|
||||
include $(CONFIG_DIR)libs-x86_64-android-gcc.mk
|
||||
else ifeq ($(TARGET_ARCH_ABI),mips)
|
||||
include $(CONFIG_DIR)libs-mips-android-gcc.mk
|
||||
else
|
||||
$(error Not a supported TARGET_ARCH_ABI: $(TARGET_ARCH_ABI))
|
||||
include $(CONFIG_DIR)libs-armv5te-android-gcc.mk
|
||||
endif
|
||||
|
||||
# Rule that is normally in Makefile created by libvpx
|
||||
@@ -97,17 +72,57 @@ SRC_PATH_BARE := $(LIBVPX_PATH)
|
||||
# Include the list of files to be built
|
||||
include $(LIBVPX_PATH)/libs.mk
|
||||
|
||||
# Optimise the code. May want to revisit this setting in the future.
|
||||
# Want arm, not thumb, optimized
|
||||
LOCAL_ARM_MODE := arm
|
||||
LOCAL_CFLAGS := -O3
|
||||
|
||||
# For x86, include the source code in the search path so it will find files
|
||||
# like x86inc.asm and x86_abi_support.asm
|
||||
LOCAL_ASMFLAGS := -I$(LIBVPX_PATH)
|
||||
# -----------------------------------------------------------------------------
|
||||
# Template : asm_offsets_template
|
||||
# Arguments : 1: assembly offsets file to be created
|
||||
# 2: c file to base assembly offsets on
|
||||
# Returns : None
|
||||
# Usage : $(eval $(call asm_offsets_template,<asmfile>, <srcfile>
|
||||
# Rationale : Create offsets at compile time using for structures that are
|
||||
# defined in c, but used in assembly functions.
|
||||
# -----------------------------------------------------------------------------
|
||||
define asm_offsets_template
|
||||
|
||||
.PRECIOUS: %.asm.S
|
||||
$(ASM_CNV_PATH)/libvpx/%.asm.S: $(LIBVPX_PATH)/%.asm
|
||||
$(qexec)mkdir -p $(dir $@)
|
||||
$(qexec)$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@
|
||||
_SRC:=$(2)
|
||||
_OBJ:=$(ASM_CNV_PATH)/$$(notdir $(2)).S
|
||||
|
||||
_FLAGS = $$($$(my)CFLAGS) \
|
||||
$$(call get-src-file-target-cflags,$(2)) \
|
||||
$$(call host-c-includes,$$(LOCAL_C_INCLUDES) $$(CONFIG_DIR)) \
|
||||
$$(LOCAL_CFLAGS) \
|
||||
$$(NDK_APP_CFLAGS) \
|
||||
$$(call host-c-includes,$$($(my)C_INCLUDES)) \
|
||||
-DINLINE_ASM \
|
||||
-S \
|
||||
|
||||
_TEXT = "Compile $$(call get-src-file-text,$(2))"
|
||||
_CC = $$(TARGET_CC)
|
||||
|
||||
$$(eval $$(call ev-build-file))
|
||||
|
||||
$(1) : $$(_OBJ) $(2)
|
||||
@mkdir -p $$(dir $$@)
|
||||
@grep $(OFFSET_PATTERN) $$< | tr -d '\#' | $(CONFIG_DIR)$(ASM_CONVERSION) > $$@
|
||||
endef
|
||||
|
||||
# Use ads2gas script to convert from RVCT format to GAS format. This passes
|
||||
# puts the processed file under $(ASM_CNV_PATH). Local clean rule
|
||||
# to handle removing these
|
||||
ifeq ($(CONFIG_VP8_ENCODER), yes)
|
||||
ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/vp8_asm_enc_offsets.asm
|
||||
endif
|
||||
ifeq ($(HAVE_NEON), yes)
|
||||
ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/vpx_scale_asm_offsets.asm
|
||||
endif
|
||||
|
||||
.PRECIOUS: %.asm.s
|
||||
$(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm $(ASM_CNV_OFFSETS_DEPEND)
|
||||
@mkdir -p $(dir $@)
|
||||
@$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@
|
||||
|
||||
# For building *_rtcd.h, which have rules in libs.mk
|
||||
TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
|
||||
@@ -127,102 +142,75 @@ LOCAL_NEON_SRCS_C = $(filter %_neon.c, $(CODEC_SRCS_C))
|
||||
LOCAL_CODEC_SRCS_C = $(filter-out vpx_config.c %_neon.c, $(CODEC_SRCS_C))
|
||||
|
||||
LOCAL_SRC_FILES += $(foreach file, $(LOCAL_CODEC_SRCS_C), libvpx/$(file))
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file).neon)
|
||||
else # If there are neon sources then we are building for arm64 and do not need to specify .neon
|
||||
LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file))
|
||||
endif
|
||||
LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file).neon)
|
||||
|
||||
# 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:
|
||||
|
||||
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 = $(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_ARM))
|
||||
CODEC_SRCS_ASM_ALL = $(filter %.asm.s, $(CODEC_SRCS_UNIQUE))
|
||||
CODEC_SRCS_ASM = $(foreach v, \
|
||||
$(CODEC_SRCS_ASM_ALL), \
|
||||
$(if $(findstring neon,$(v)),,$(v)))
|
||||
CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.s, \
|
||||
$(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
|
||||
$(CODEC_SRCS_ASM))
|
||||
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),\
|
||||
$(CODEC_SRCS_ASM_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
|
||||
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
|
||||
LOCAL_STATIC_LIBRARIES := cpufeatures
|
||||
endif
|
||||
|
||||
# Add a dependency to force generation of the RTCD files.
|
||||
define rtcd_dep_template
|
||||
rtcd_dep_template_SRCS := $(addprefix $(LOCAL_PATH)/, $(LOCAL_SRC_FILES))
|
||||
rtcd_dep_template_SRCS := $$(rtcd_dep_template_SRCS:.neon=)
|
||||
ifeq ($(CONFIG_VP8), yes)
|
||||
$$(rtcd_dep_template_SRCS): vp8_rtcd.h
|
||||
$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vp8_rtcd.h
|
||||
endif
|
||||
ifeq ($(CONFIG_VP9), yes)
|
||||
$$(rtcd_dep_template_SRCS): vp9_rtcd.h
|
||||
$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vp9_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)),)
|
||||
$$(rtcd_dep_template_SRCS): vpx_config.asm
|
||||
endif
|
||||
endef
|
||||
|
||||
$(eval $(call rtcd_dep_template))
|
||||
$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vpx_scale_rtcd.h
|
||||
|
||||
.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) $(patsubst %.asm, %.*, $(ASM_CNV_OFFSETS_DEPEND))
|
||||
@$(RM) -r $(ASM_CNV_PATH)
|
||||
@$(RM) $(CLEAN-OBJS)
|
||||
|
||||
ifeq ($(ENABLE_SHARED),1)
|
||||
LOCAL_CFLAGS += -fPIC
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
else
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
ifeq ($(HAVE_NEON), yes)
|
||||
$(eval $(call asm_offsets_template,\
|
||||
$(ASM_CNV_PATH)/vpx_scale_asm_offsets.asm, \
|
||||
$(LIBVPX_PATH)/vpx_scale/vpx_scale_asm_offsets.c))
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_VP8_ENCODER), yes)
|
||||
$(eval $(call asm_offsets_template,\
|
||||
$(ASM_CNV_PATH)/vp8_asm_enc_offsets.asm, \
|
||||
$(LIBVPX_PATH)/vp8/encoder/vp8_asm_enc_offsets.c))
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
|
||||
$(call import-module,android/cpufeatures)
|
||||
$(call import-module,cpufeatures)
|
||||
endif
|
||||
|
||||
@@ -19,14 +19,10 @@ ifeq ($(target),)
|
||||
done
|
||||
all: .DEFAULT
|
||||
clean:: .DEFAULT
|
||||
exampletest: .DEFAULT
|
||||
install:: .DEFAULT
|
||||
test:: .DEFAULT
|
||||
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.
|
||||
@@ -56,12 +52,17 @@ dist:
|
||||
| sed -e 's/MD5(\(.*\))= \([0-9a-f]\{32\}\)/\2 \1/' \
|
||||
> md5sums.txt;\
|
||||
fi
|
||||
|
||||
|
||||
endif
|
||||
|
||||
# Since we invoke make recursively for multiple targets we need to include the
|
||||
# .mk file for the correct target, but only when $(target) is non-empty.
|
||||
ifneq ($(target),)
|
||||
include $(target)-$(TOOLCHAIN).mk
|
||||
# Normally, we want to build the filename from the target and the toolchain.
|
||||
# This disambiguates from the $(target).mk file that exists in the source tree.
|
||||
# However, the toolchain is part of the target in universal builds, so we
|
||||
# don't want to include TOOLCHAIN in that case. FAT_ARCHS is used to test
|
||||
# if we're in the universal case.
|
||||
include $(target)$(if $(FAT_ARCHS),,-$(TOOLCHAIN)).mk
|
||||
endif
|
||||
BUILD_ROOT?=.
|
||||
VPATH=$(SRC_PATH_BARE)
|
||||
@@ -90,41 +91,19 @@ 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
|
||||
distclean: clean
|
||||
if [ -z "$(target)" ]; then \
|
||||
rm -f Makefile; \
|
||||
rm -f config.log config.mk; \
|
||||
rm -f vpx_config.[hc] vpx_config.asm; \
|
||||
else \
|
||||
rm -f $(target)-$(TOOLCHAIN).mk; \
|
||||
fi
|
||||
|
||||
.PHONY: dist
|
||||
dist:
|
||||
.PHONY: exampletest
|
||||
exampletest:
|
||||
.PHONY: install
|
||||
install::
|
||||
.PHONY: test
|
||||
test::
|
||||
.PHONY: testdata
|
||||
testdata::
|
||||
.PHONY: utiltest
|
||||
utiltest:
|
||||
.PHONY: test-no-data-check exampletest-no-data-check utiltest-no-data-check
|
||||
test-no-data-check::
|
||||
exampletest-no-data-check utiltest-no-data-check:
|
||||
|
||||
# Force to realign stack always on OS/2
|
||||
ifeq ($(TOOLCHAIN), x86-os2-gcc)
|
||||
CFLAGS += -mstackrealign
|
||||
endif
|
||||
|
||||
# x86[_64]
|
||||
# Add compiler flags for intrinsic files
|
||||
$(BUILD_PFX)%_mmx.c.d: CFLAGS += -mmmx
|
||||
$(BUILD_PFX)%_mmx.c.o: CFLAGS += -mmmx
|
||||
$(BUILD_PFX)%_sse2.c.d: CFLAGS += -msse2
|
||||
@@ -139,12 +118,6 @@ $(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)%.c.d: %.c
|
||||
$(if $(quiet),@echo " [DEP] $@")
|
||||
@@ -153,7 +126,6 @@ $(BUILD_PFX)%.c.d: %.c
|
||||
|
||||
$(BUILD_PFX)%.c.o: %.c
|
||||
$(if $(quiet),@echo " [CC] $@")
|
||||
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
|
||||
$(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILD_PFX)%.cc.d: %.cc
|
||||
@@ -163,17 +135,6 @@ $(BUILD_PFX)%.cc.d: %.cc
|
||||
|
||||
$(BUILD_PFX)%.cc.o: %.cc
|
||||
$(if $(quiet),@echo " [CXX] $@")
|
||||
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
|
||||
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILD_PFX)%.cpp.d: %.cpp
|
||||
$(if $(quiet),@echo " [DEP] $@")
|
||||
$(qexec)mkdir -p $(dir $@)
|
||||
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
|
||||
|
||||
$(BUILD_PFX)%.cpp.o: %.cpp
|
||||
$(if $(quiet),@echo " [CXX] $@")
|
||||
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
|
||||
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILD_PFX)%.asm.d: %.asm
|
||||
@@ -184,29 +145,26 @@ $(BUILD_PFX)%.asm.d: %.asm
|
||||
|
||||
$(BUILD_PFX)%.asm.o: %.asm
|
||||
$(if $(quiet),@echo " [AS] $@")
|
||||
$(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 $@ $<
|
||||
|
||||
.PRECIOUS: %.c.S
|
||||
%.c.S: CFLAGS += -DINLINE_ASM
|
||||
$(BUILD_PFX)%.c.S: %.c
|
||||
$(if $(quiet),@echo " [GEN] $@")
|
||||
$(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) <$< >$@
|
||||
@@ -215,13 +173,13 @@ $(BUILD_PFX)%.asm.S: %.asm
|
||||
# the copy implementation
|
||||
HAVE_GNU_STRIP := $(if $(CONFIG_DEBUG),,$(HAVE_GNU_STRIP))
|
||||
ifeq ($(HAVE_GNU_STRIP),yes)
|
||||
# Older binutils strip global symbols not needed for relocation processing
|
||||
# when given --strip-unneeded. Using nm and awk to identify globals and
|
||||
# keep them caused command line length issues under mingw and segfaults in
|
||||
# test_libvpx were observed under OS/2: simply use --strip-debug.
|
||||
# Older binutils strip global sybols not needed for relocation processing
|
||||
# when given --strip-unneeded. Use nm and awk to identify globals and
|
||||
# keep them.
|
||||
%.a: %_g.a
|
||||
$(if $(quiet),@echo " [STRIP] $@ < $<")
|
||||
$(qexec)$(STRIP) --strip-debug \
|
||||
$(qexec)$(STRIP) --strip-unneeded \
|
||||
`$(NM) $< | grep ' [A-TV-Z] ' | awk '{print "-K"$$3'}`\
|
||||
-o $@ $<
|
||||
else
|
||||
%.a: %_g.a
|
||||
@@ -229,6 +187,14 @@ else
|
||||
$(qexec)cp $< $@
|
||||
endif
|
||||
|
||||
#
|
||||
# Rule to extract assembly constants from C sources
|
||||
#
|
||||
obj_int_extract: build/make/obj_int_extract.c
|
||||
$(if $(quiet),@echo " [HOSTCC] $@")
|
||||
$(qexec)$(HOSTCC) -I. -I$(SRC_PATH_BARE) -o $@ $<
|
||||
CLEAN-OBJS += obj_int_extract
|
||||
|
||||
#
|
||||
# Utility functions
|
||||
#
|
||||
@@ -242,7 +208,7 @@ cond_enabled=$(if $(filter yes,$($(1))), $(call enabled,$(2)))
|
||||
|
||||
find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
|
||||
find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
|
||||
obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o .cpp=.cpp.o
|
||||
obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o
|
||||
objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
|
||||
|
||||
install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
|
||||
@@ -290,7 +256,7 @@ define archive_template
|
||||
# for creating them.
|
||||
$(1):
|
||||
$(if $(quiet),@echo " [AR] $$@")
|
||||
$(qexec)$$(AR) $$(ARFLAGS) $$@ $$^
|
||||
$(qexec)$$(AR) $$(ARFLAGS) $$@ $$?
|
||||
endef
|
||||
|
||||
define so_template
|
||||
@@ -320,15 +286,18 @@ $(1):
|
||||
$$(filter %.o,$$^) $$(extralibs)
|
||||
endef
|
||||
|
||||
define dll_template
|
||||
# Not using a pattern rule here because we don't want to generate empty
|
||||
# archives when they are listed as a dependency in files not responsible
|
||||
# for creating them.
|
||||
$(1):
|
||||
$(if $(quiet),@echo " [LD] $$@")
|
||||
$(qexec)$$(LD) -Zdll $$(LDFLAGS) \
|
||||
-o $$@ \
|
||||
$$(filter %.o,$$^) $$(extralibs) $$(EXPORTS_FILE)
|
||||
|
||||
|
||||
define lipo_lib_template
|
||||
$(1): $(addsuffix /$(1),$(FAT_ARCHS))
|
||||
$(if $(quiet),@echo " [LIPO] $$@")
|
||||
$(qexec)libtool -static -o $$@ $$?
|
||||
endef
|
||||
|
||||
define lipo_bin_template
|
||||
$(1): $(addsuffix /$(1),$(FAT_ARCHS))
|
||||
$(if $(quiet),@echo " [LIPO] $$@")
|
||||
$(qexec)lipo -output $$@ -create $$?
|
||||
endef
|
||||
|
||||
|
||||
@@ -338,15 +307,10 @@ endef
|
||||
ifneq ($(target),)
|
||||
include $(SRC_PATH_BARE)/$(target:-$(TOOLCHAIN)=).mk
|
||||
endif
|
||||
|
||||
skip_deps := $(filter %clean,$(MAKECMDGOALS))
|
||||
skip_deps += $(findstring testdata,$(MAKECMDGOALS))
|
||||
ifeq ($(strip $(skip_deps)),)
|
||||
ifeq ($(CONFIG_DEPENDENCY_TRACKING),yes)
|
||||
# Older versions of make don't like -include directives with no arguments
|
||||
ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),)
|
||||
-include $(filter %.d,$(OBJS-yes:.o=.d))
|
||||
endif
|
||||
ifeq ($(filter clean,$(MAKECMDGOALS)),)
|
||||
# Older versions of make don't like -include directives with no arguments
|
||||
ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),)
|
||||
-include $(filter %.d,$(OBJS-yes:.o=.d))
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -387,9 +351,8 @@ LIBS=$(call enabled,LIBS)
|
||||
.libs: $(LIBS)
|
||||
@touch $@
|
||||
$(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib))))
|
||||
$(foreach lib,$(filter %so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR).$(SO_VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib))))
|
||||
$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dylib,$(LIBS)),$(eval $(call dl_template,$(lib))))
|
||||
$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dll,$(LIBS)),$(eval $(call dll_template,$(lib))))
|
||||
$(foreach lib,$(filter %so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib))))
|
||||
$(foreach lib,$(filter %$(VERSION_MAJOR).dylib,$(LIBS)),$(eval $(call dl_template,$(lib))))
|
||||
|
||||
INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS)
|
||||
ifeq ($(MAKECMDGOALS),dist)
|
||||
@@ -425,10 +388,14 @@ 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
|
||||
DIST-SRCS-$(CONFIG_MSVS) += build/x86-msvs/obj_int_extract.bat
|
||||
DIST-SRCS-$(CONFIG_MSVS) += build/arm-msvs/obj_int_extract.bat
|
||||
DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
|
||||
# Include obj_int_extract if we use offsets from *_asm_*_offsets
|
||||
DIST-SRCS-$(ARCH_ARM)$(ARCH_X86)$(ARCH_X86_64) += build/make/obj_int_extract.c
|
||||
DIST-SRCS-$(ARCH_ARM) += build/make/ads2gas.pl
|
||||
DIST-SRCS-$(ARCH_ARM) += build/make/ads2gas_apple.pl
|
||||
DIST-SRCS-$(ARCH_ARM) += build/make/ads2armasm_ms.pl
|
||||
@@ -455,5 +422,3 @@ all: $(BUILD_TARGETS)
|
||||
install:: $(INSTALL_TARGETS)
|
||||
dist: $(INSTALL_TARGETS)
|
||||
test::
|
||||
|
||||
.SUFFIXES: # Delete default suffix rules
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env perl
|
||||
#!/usr/bin/perl
|
||||
##
|
||||
## Copyright (c) 2013 The WebM project authors. All Rights Reserved.
|
||||
##
|
||||
@@ -32,7 +32,6 @@ while (<STDIN>)
|
||||
|
||||
s/ldrneb/ldrbne/i;
|
||||
s/ldrneh/ldrhne/i;
|
||||
s/^(\s*)ENDP.*/$&\n$1ALIGN 4/;
|
||||
|
||||
print;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env perl
|
||||
#!/usr/bin/perl
|
||||
##
|
||||
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
##
|
||||
@@ -138,6 +138,14 @@ 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
|
||||
s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
|
||||
|
||||
@@ -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";
|
||||
@@ -69,16 +75,16 @@ while (<STDIN>)
|
||||
s/:SHR:/ >> /g;
|
||||
|
||||
# Convert ELSE to .else
|
||||
s/\bELSE\b/.else/g;
|
||||
s/ELSE/.else/g;
|
||||
|
||||
# Convert ENDIF to .endif
|
||||
s/\bENDIF\b/.endif/g;
|
||||
s/ENDIF/.endif/g;
|
||||
|
||||
# Convert ELSEIF to .elseif
|
||||
s/\bELSEIF\b/.elseif/g;
|
||||
s/ELSEIF/.elseif/g;
|
||||
|
||||
# Convert LTORG to .ltorg
|
||||
s/\bLTORG\b/.ltorg/g;
|
||||
s/LTORG/.ltorg/g;
|
||||
|
||||
# Convert IF :DEF:to .if
|
||||
# gcc doesn't have the ability to do a conditional
|
||||
@@ -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/;
|
||||
@@ -146,7 +164,7 @@ while (<STDIN>)
|
||||
s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
|
||||
|
||||
# ALIGN directive
|
||||
s/\bALIGN\b/.balign/g;
|
||||
s/ALIGN/.balign/g;
|
||||
|
||||
# Strip ARM
|
||||
s/\sARM/@ ARM/g;
|
||||
@@ -166,7 +184,7 @@ while (<STDIN>)
|
||||
s/(.*)EQU(.*)/.set $1, $2/;
|
||||
|
||||
# Begin macro definition
|
||||
if (/\bMACRO\b/)
|
||||
if (/MACRO/)
|
||||
{
|
||||
# Process next line down, which will be the macro definition
|
||||
$_ = <STDIN>;
|
||||
@@ -197,8 +215,21 @@ while (<STDIN>)
|
||||
|
||||
# For macros, use \ to reference formal params
|
||||
# s/\$/\\/g; # End macro definition
|
||||
s/\bMEND\b/.endm/; # No need to tell it where to stop assembling
|
||||
s/MEND/.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;
|
||||
}
|
||||
|
||||
1976
build/make/configure.sh
Normal file → Executable file
1976
build/make/configure.sh
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
592
build/make/gen_msvs_proj.sh
Executable file
592
build/make/gen_msvs_proj.sh
Executable file
@@ -0,0 +1,592 @@
|
||||
#!/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")
|
||||
EOL=$'\n'
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "${self_basename}: $@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
die_unknown(){
|
||||
echo "Unknown option \"$1\"." >&2
|
||||
echo "See ${self_basename} --help for available options." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
generate_uuid() {
|
||||
local hex="0123456789ABCDEF"
|
||||
local i
|
||||
local uuid=""
|
||||
local j
|
||||
#93995380-89BD-4b04-88EB-625FBE52EBFB
|
||||
for ((i=0; i<32; i++)); do
|
||||
(( j = $RANDOM % 16 ))
|
||||
uuid="${uuid}${hex:$j:1}"
|
||||
done
|
||||
echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
|
||||
}
|
||||
|
||||
indent1=" "
|
||||
indent=""
|
||||
indent_push() {
|
||||
indent="${indent}${indent1}"
|
||||
}
|
||||
indent_pop() {
|
||||
indent="${indent%${indent1}}"
|
||||
}
|
||||
|
||||
tag_attributes() {
|
||||
for opt in "$@"; do
|
||||
optval="${opt#*=}"
|
||||
[ -n "${optval}" ] ||
|
||||
die "Missing attribute value in '$opt' while generating $tag tag"
|
||||
echo "${indent}${opt%%=*}=\"${optval}\""
|
||||
done
|
||||
}
|
||||
|
||||
open_tag() {
|
||||
local tag=$1
|
||||
shift
|
||||
if [ $# -ne 0 ]; then
|
||||
echo "${indent}<${tag}"
|
||||
indent_push
|
||||
tag_attributes "$@"
|
||||
echo "${indent}>"
|
||||
else
|
||||
echo "${indent}<${tag}>"
|
||||
indent_push
|
||||
fi
|
||||
}
|
||||
|
||||
close_tag() {
|
||||
local tag=$1
|
||||
indent_pop
|
||||
echo "${indent}</${tag}>"
|
||||
}
|
||||
|
||||
tag() {
|
||||
local tag=$1
|
||||
shift
|
||||
if [ $# -ne 0 ]; then
|
||||
echo "${indent}<${tag}"
|
||||
indent_push
|
||||
tag_attributes "$@"
|
||||
indent_pop
|
||||
echo "${indent}/>"
|
||||
else
|
||||
echo "${indent}<${tag}/>"
|
||||
fi
|
||||
}
|
||||
|
||||
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/^[\./]\+//g' -e 's,/,_,g')
|
||||
open_tag File RelativePath="./$f"
|
||||
|
||||
if [ "$pat" == "asm" ] && $asm_use_custom_step; then
|
||||
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" ] ; 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="$optval"
|
||||
;;
|
||||
--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%/}"
|
||||
incs="${incs}${incs:+;}"${opt##-I}""
|
||||
yasmincs="${yasmincs} ${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
|
||||
libdirs="${libdirs}${libdirs:+;}"${opt##-L}""
|
||||
libdirs="${libdirs}${libdirs:+;}"${opt##-L}/\$(PlatformName)/\$(ConfigurationName)""
|
||||
libdirs="${libdirs}${libdirs:+;}"${opt##-L}/\$(PlatformName)""
|
||||
fi
|
||||
;;
|
||||
-l*) libs="${libs}${libs:+ }${opt##-l}.lib"
|
||||
;;
|
||||
-*) die_unknown $opt
|
||||
;;
|
||||
*)
|
||||
file_list[${#file_list[@]}]="$opt"
|
||||
case "$opt" in
|
||||
*.asm) uses_asm=true
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
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 \$(PlatformName) ${yasmincs} "\$(InputPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} "\$(InputPath)""
|
||||
;;
|
||||
x86*)
|
||||
platforms[0]="Win32"
|
||||
asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} "\$(InputPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${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
|
||||
obj_int_extract)
|
||||
tag Tool \
|
||||
Name="VCCLCompilerTool" \
|
||||
Optimization="0" \
|
||||
AdditionalIncludeDirectories="$incs" \
|
||||
PreprocessorDefinitions="WIN32;DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
|
||||
RuntimeLibrary="$debug_runtime" \
|
||||
WarningLevel="3" \
|
||||
DebugInformationFormat="1" \
|
||||
$warn_64bit \
|
||||
;;
|
||||
vpx)
|
||||
tag Tool \
|
||||
Name="VCPreBuildEventTool" \
|
||||
CommandLine="call obj_int_extract.bat $src_path_bare" \
|
||||
|
||||
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
|
||||
obj_int_extract)
|
||||
tag Tool \
|
||||
Name="VCLinkerTool" \
|
||||
OutputFile="${name}.exe" \
|
||||
GenerateDebugInformation="true" \
|
||||
;;
|
||||
*)
|
||||
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
|
||||
obj_int_extract)
|
||||
tag Tool \
|
||||
Name="VCCLCompilerTool" \
|
||||
Optimization="2" \
|
||||
FavorSizeorSpeed="1" \
|
||||
AdditionalIncludeDirectories="$incs" \
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
|
||||
RuntimeLibrary="$release_runtime" \
|
||||
UsePrecompiledHeader="0" \
|
||||
WarningLevel="3" \
|
||||
DebugInformationFormat="0" \
|
||||
$warn_64bit \
|
||||
;;
|
||||
vpx)
|
||||
tag Tool \
|
||||
Name="VCPreBuildEventTool" \
|
||||
CommandLine="call obj_int_extract.bat $src_path_bare" \
|
||||
|
||||
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
|
||||
obj_int_extract)
|
||||
tag Tool \
|
||||
Name="VCLinkerTool" \
|
||||
OutputFile="${name}.exe" \
|
||||
GenerateDebugInformation="true" \
|
||||
;;
|
||||
*)
|
||||
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;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>
|
||||
-->
|
||||
@@ -19,13 +19,13 @@ show_help() {
|
||||
cat <<EOF
|
||||
Usage: ${self_basename} [options] file1 [file2 ...]
|
||||
|
||||
This script generates a Visual Studio solution file from a list of project
|
||||
This script generates a Visual Studio 2005 solution file from a list of project
|
||||
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) 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)
|
||||
;;
|
||||
*) 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,15 @@ case "${vs_ver:-10}" in
|
||||
12) sln_vers="12.00"
|
||||
sln_vers_str="Visual Studio 2013"
|
||||
;;
|
||||
14) sln_vers="12.00"
|
||||
sln_vers_str="Visual Studio 2015"
|
||||
esac
|
||||
case "${vs_ver:-8}" in
|
||||
[789])
|
||||
sfx=vcproj
|
||||
;;
|
||||
15) sln_vers="12.00"
|
||||
sln_vers_str="Visual Studio 2017"
|
||||
10|11|12)
|
||||
sfx=vcxproj
|
||||
;;
|
||||
esac
|
||||
sfx=vcxproj
|
||||
|
||||
for f in "${file_list[@]}"; do
|
||||
parse_project $f
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
## 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
|
||||
EOL=$'\n'
|
||||
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
@@ -28,13 +28,12 @@ Options:
|
||||
--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)
|
||||
--enable-werror Treat warnings as errors (/WX)
|
||||
--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 (10,11,12,14,15) of visual studio to generate for
|
||||
--ver=version Version (10,11,12) 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
|
||||
@@ -44,6 +43,82 @@ EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "${self_basename}: $@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
die_unknown(){
|
||||
echo "Unknown option \"$1\"." >&2
|
||||
echo "See ${self_basename} --help for available options." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
generate_uuid() {
|
||||
local hex="0123456789ABCDEF"
|
||||
local i
|
||||
local uuid=""
|
||||
local j
|
||||
#93995380-89BD-4b04-88EB-625FBE52EBFB
|
||||
for ((i=0; i<32; i++)); do
|
||||
(( j = $RANDOM % 16 ))
|
||||
uuid="${uuid}${hex:$j:1}"
|
||||
done
|
||||
echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
|
||||
}
|
||||
|
||||
indent1=" "
|
||||
indent=""
|
||||
indent_push() {
|
||||
indent="${indent}${indent1}"
|
||||
}
|
||||
indent_pop() {
|
||||
indent="${indent%${indent1}}"
|
||||
}
|
||||
|
||||
tag_attributes() {
|
||||
for opt in "$@"; do
|
||||
optval="${opt#*=}"
|
||||
[ -n "${optval}" ] ||
|
||||
die "Missing attribute value in '$opt' while generating $tag tag"
|
||||
echo "${indent}${opt%%=*}=\"${optval}\""
|
||||
done
|
||||
}
|
||||
|
||||
open_tag() {
|
||||
local tag=$1
|
||||
shift
|
||||
if [ $# -ne 0 ]; then
|
||||
echo "${indent}<${tag}"
|
||||
indent_push
|
||||
tag_attributes "$@"
|
||||
echo "${indent}>"
|
||||
else
|
||||
echo "${indent}<${tag}>"
|
||||
indent_push
|
||||
fi
|
||||
}
|
||||
|
||||
close_tag() {
|
||||
local tag=$1
|
||||
indent_pop
|
||||
echo "${indent}</${tag}>"
|
||||
}
|
||||
|
||||
tag() {
|
||||
local tag=$1
|
||||
shift
|
||||
if [ $# -ne 0 ]; then
|
||||
echo "${indent}<${tag}"
|
||||
indent_push
|
||||
tag_attributes "$@"
|
||||
indent_pop
|
||||
echo "${indent}/>"
|
||||
else
|
||||
echo "${indent}<${tag}/>"
|
||||
fi
|
||||
}
|
||||
|
||||
tag_content() {
|
||||
local tag=$1
|
||||
local content=$2
|
||||
@@ -78,17 +153,11 @@ generate_filter() {
|
||||
if [ "${f##*.}" == "$pat" ]; then
|
||||
unset file_list[i]
|
||||
|
||||
objf=$(echo ${f%.*}.obj \
|
||||
| sed -e "s,$src_path_bare,," \
|
||||
-e 's/^[\./]\+//g' -e 's,[:/ ],_,g')
|
||||
objf=$(echo ${f%.*}.obj | sed -e 's/^[\./]\+//g' -e 's,/,_,g')
|
||||
|
||||
if ([ "$pat" == "asm" ] || [ "$pat" == "s" ] || [ "$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.
|
||||
objf=${objf%.obj}_asm.obj
|
||||
if ([ "$pat" == "asm" ] || [ "$pat" == "s" ]) && $asm_use_custom_step; then
|
||||
open_tag CustomBuild \
|
||||
Include="$f"
|
||||
Include=".\\$f"
|
||||
for plat in "${platforms[@]}"; do
|
||||
for cfg in Debug Release; do
|
||||
tag_content Message "Assembling %(Filename)%(Extension)" \
|
||||
@@ -100,20 +169,15 @@ generate_filter() {
|
||||
done
|
||||
done
|
||||
close_tag CustomBuild
|
||||
elif [ "$pat" == "c" ] || \
|
||||
[ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then
|
||||
elif [ "$pat" == "c" ] || [ "$pat" == "cc" ] ; then
|
||||
open_tag ClCompile \
|
||||
Include="$f"
|
||||
Include=".\\$f"
|
||||
# Separate file names with Condition?
|
||||
tag_content ObjectFileName "\$(IntDir)$objf"
|
||||
# Check for AVX and turn it on to avoid warnings.
|
||||
if [[ $f =~ avx.?\.c$ ]]; then
|
||||
tag_content AdditionalOptions "/arch:AVX"
|
||||
fi
|
||||
close_tag ClCompile
|
||||
elif [ "$pat" == "h" ] ; then
|
||||
tag ClInclude \
|
||||
Include="$f"
|
||||
Include=".\\$f"
|
||||
elif [ "$pat" == "vcxproj" ] ; then
|
||||
open_tag ProjectReference \
|
||||
Include="$f"
|
||||
@@ -123,7 +187,7 @@ generate_filter() {
|
||||
close_tag ProjectReference
|
||||
else
|
||||
tag None \
|
||||
Include="$f"
|
||||
Include=".\\$f"
|
||||
fi
|
||||
|
||||
break
|
||||
@@ -157,42 +221,34 @@ for opt in "$@"; do
|
||||
;;
|
||||
--lib) proj_kind="lib"
|
||||
;;
|
||||
--src-path-bare=*)
|
||||
src_path_bare=$(fix_path "$optval")
|
||||
src_path_bare=${src_path_bare%/}
|
||||
--src-path-bare=*) src_path_bare="$optval"
|
||||
;;
|
||||
--static-crt) use_static_runtime=true
|
||||
;;
|
||||
--enable-werror) werror=true
|
||||
;;
|
||||
--ver=*)
|
||||
vs_ver="$optval"
|
||||
case "$optval" in
|
||||
10|11|12|14|15)
|
||||
10|11|12)
|
||||
;;
|
||||
*) 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}""
|
||||
incs="${incs}${incs:+;}${opt##-I}"
|
||||
yasmincs="${yasmincs} ${opt}"
|
||||
;;
|
||||
-D*) defines="${defines}${defines:+;}${opt##-D}"
|
||||
;;
|
||||
-L*) # fudge . to $(OutDir)
|
||||
if [ "${opt##-L}" == "." ]; then
|
||||
libdirs="${libdirs}${libdirs:+;}"\$(OutDir)""
|
||||
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)/\$(Configuration)""
|
||||
libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)""
|
||||
libdirs="${libdirs}${libdirs:+;}${opt##-L}"
|
||||
libdirs="${libdirs}${libdirs:+;}${opt##-L}/\$(PlatformName)/\$(Configuration)"
|
||||
libdirs="${libdirs}${libdirs:+;}${opt##-L}/\$(PlatformName)"
|
||||
fi
|
||||
;;
|
||||
-l*) libs="${libs}${libs:+ }${opt##-l}.lib"
|
||||
@@ -200,25 +256,20 @@ for opt in "$@"; do
|
||||
-*) die_unknown $opt
|
||||
;;
|
||||
*)
|
||||
# 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
|
||||
;;
|
||||
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:-11}" in
|
||||
10|11|12|14|15)
|
||||
10|11|12)
|
||||
asm_use_custom_step=$uses_asm
|
||||
;;
|
||||
esac
|
||||
@@ -253,18 +304,24 @@ libs=${libs// /;}
|
||||
case "$target" in
|
||||
x86_64*)
|
||||
platforms[0]="x64"
|
||||
asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} "%(FullPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} "%(FullPath)""
|
||||
asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} "%(FullPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} "%(FullPath)""
|
||||
;;
|
||||
x86*)
|
||||
platforms[0]="Win32"
|
||||
asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} "%(FullPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} "%(FullPath)""
|
||||
asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} "%(FullPath)""
|
||||
asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} "%(FullPath)""
|
||||
;;
|
||||
arm*)
|
||||
platforms[0]="ARM"
|
||||
asm_Debug_cmdline="armasm -nologo -oldit "%(FullPath)""
|
||||
asm_Release_cmdline="armasm -nologo -oldit "%(FullPath)""
|
||||
asm_Debug_cmdline="armasm -nologo "%(FullPath)""
|
||||
asm_Release_cmdline="armasm -nologo "%(FullPath)""
|
||||
if [ "$name" = "obj_int_extract" ]; then
|
||||
# We don't want to build this tool for the target architecture,
|
||||
# but for an architecture we can run locally during the build.
|
||||
platforms[0]="Win32"
|
||||
else
|
||||
platforms[0]="ARM"
|
||||
fi
|
||||
;;
|
||||
*) die "Unsupported target $target!"
|
||||
;;
|
||||
@@ -295,18 +352,6 @@ generate_vcxproj() {
|
||||
tag_content ProjectGuid "{${guid}}"
|
||||
tag_content RootNamespace ${name}
|
||||
tag_content Keyword ManagedCProj
|
||||
if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then
|
||||
tag_content AppContainerApplication true
|
||||
# The application type can be one of "Windows Store",
|
||||
# "Windows Phone" or "Windows Phone Silverlight". The
|
||||
# actual value doesn't matter from the libvpx point of view,
|
||||
# since a static library built for one works on the others.
|
||||
# The PlatformToolset field needs to be set in sync with this;
|
||||
# for Windows Store and Windows Phone Silverlight it should be
|
||||
# v120 while it should be v120_wp81 if the type is Windows Phone.
|
||||
tag_content ApplicationType "Windows Store"
|
||||
tag_content ApplicationTypeRevision 8.1
|
||||
fi
|
||||
close_tag PropertyGroup
|
||||
|
||||
tag Import \
|
||||
@@ -339,16 +384,18 @@ generate_vcxproj() {
|
||||
fi
|
||||
fi
|
||||
if [ "$vs_ver" = "12" ]; then
|
||||
# Setting a PlatformToolset indicating windows phone isn't
|
||||
# enough to build code for arm with MSVC 2013, one strictly
|
||||
# has to enable AppContainerApplication as well.
|
||||
tag_content PlatformToolset v120
|
||||
fi
|
||||
if [ "$vs_ver" = "14" ]; then
|
||||
tag_content PlatformToolset v140
|
||||
fi
|
||||
if [ "$vs_ver" = "15" ]; then
|
||||
tag_content PlatformToolset v141
|
||||
if [ "$plat" = "ARM" ]; then
|
||||
# Setting the wp80 toolchain automatically sets the
|
||||
# WINAPI_FAMILY define, which is required for building
|
||||
# code for arm with the windows headers. Alternatively,
|
||||
# one could add AppContainerApplication=true in the Globals
|
||||
# section and add PrecompiledHeader=NotUsing and
|
||||
# CompileAsWinRT=false in ClCompile and SubSystem=Console
|
||||
# in Link.
|
||||
tag_content PlatformToolset v120_wp80
|
||||
else
|
||||
tag_content PlatformToolset v120
|
||||
fi
|
||||
fi
|
||||
tag_content CharacterSet Unicode
|
||||
if [ "$config" = "Release" ]; then
|
||||
@@ -379,14 +426,6 @@ generate_vcxproj() {
|
||||
Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
|
||||
tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\"
|
||||
tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\"
|
||||
if [ "$proj_kind" == "lib" ]; then
|
||||
if [ "$config" == "Debug" ]; then
|
||||
config_suffix=d
|
||||
else
|
||||
config_suffix=""
|
||||
fi
|
||||
tag_content TargetName "${name}${lib_sfx}${config_suffix}"
|
||||
fi
|
||||
close_tag PropertyGroup
|
||||
done
|
||||
done
|
||||
@@ -395,49 +434,58 @@ generate_vcxproj() {
|
||||
for config in Debug Release; do
|
||||
open_tag ItemDefinitionGroup \
|
||||
Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
|
||||
if [ "$name" == "vpx" ]; then
|
||||
hostplat=$plat
|
||||
if [ "$hostplat" == "ARM" ]; then
|
||||
hostplat=Win32
|
||||
fi
|
||||
if [ "$name" = "vpx" ]; then
|
||||
open_tag PreBuildEvent
|
||||
tag_content Command "call obj_int_extract.bat $src_path_bare"
|
||||
close_tag PreBuildEvent
|
||||
fi
|
||||
open_tag ClCompile
|
||||
if [ "$config" = "Debug" ]; then
|
||||
opt=Disabled
|
||||
runtime=$debug_runtime
|
||||
curlibs=$debug_libs
|
||||
debug=_DEBUG
|
||||
confsuffix=d
|
||||
case "$name" in
|
||||
obj_int_extract)
|
||||
debug=DEBUG
|
||||
;;
|
||||
*)
|
||||
debug=_DEBUG
|
||||
;;
|
||||
esac
|
||||
else
|
||||
opt=MaxSpeed
|
||||
runtime=$release_runtime
|
||||
curlibs=$libs
|
||||
confsuffix=""
|
||||
tag_content FavorSizeOrSpeed Speed
|
||||
debug=NDEBUG
|
||||
fi
|
||||
extradefines=";$defines"
|
||||
case "$name" in
|
||||
obj_int_extract)
|
||||
extradefines=";_CONSOLE"
|
||||
;;
|
||||
*)
|
||||
extradefines=";$defines"
|
||||
;;
|
||||
esac
|
||||
tag_content Optimization $opt
|
||||
tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)"
|
||||
tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)"
|
||||
tag_content RuntimeLibrary $runtime
|
||||
tag_content WarningLevel Level3
|
||||
if ${werror:-false}; then
|
||||
tag_content TreatWarningAsError true
|
||||
fi
|
||||
if [ $vs_ver -ge 11 ]; then
|
||||
# We need to override the defaults for these settings
|
||||
# if AppContainerApplication is set.
|
||||
tag_content CompileAsWinRT false
|
||||
tag_content PrecompiledHeader NotUsing
|
||||
tag_content SDLCheck false
|
||||
fi
|
||||
# DebugInformationFormat
|
||||
close_tag ClCompile
|
||||
case "$proj_kind" in
|
||||
exe)
|
||||
open_tag Link
|
||||
if [ "$name" = "obj_int_extract" ]; then
|
||||
tag_content OutputFile "${name}.exe"
|
||||
else
|
||||
tag_content AdditionalDependencies "$curlibs"
|
||||
tag_content AdditionalLibraryDirectories "$libdirs;%(AdditionalLibraryDirectories)"
|
||||
fi
|
||||
tag_content GenerateDebugInformation true
|
||||
# Console is the default normally, but if
|
||||
# AppContainerApplication is set, we need to override it.
|
||||
tag_content SubSystem Console
|
||||
close_tag Link
|
||||
;;
|
||||
dll)
|
||||
@@ -447,6 +495,9 @@ generate_vcxproj() {
|
||||
close_tag Link
|
||||
;;
|
||||
lib)
|
||||
open_tag Lib
|
||||
tag_content OutputFile "\$(OutDir)${name}${lib_sfx}${confsuffix}.lib"
|
||||
close_tag Lib
|
||||
;;
|
||||
esac
|
||||
close_tag ItemDefinitionGroup
|
||||
@@ -455,7 +506,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;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>
|
||||
@@ -1,383 +0,0 @@
|
||||
#!/bin/sh
|
||||
##
|
||||
## Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
##
|
||||
## Use of this source code is governed by a BSD-style license
|
||||
## that can be found in the LICENSE file in the root of the source
|
||||
## tree. An additional intellectual property rights grant can be found
|
||||
## in the file PATENTS. All contributing project authors may
|
||||
## be found in the AUTHORS file in the root of the source tree.
|
||||
##
|
||||
##
|
||||
## This script generates 'VPX.framework'. An iOS app can encode and decode VPx
|
||||
## video by including 'VPX.framework'.
|
||||
##
|
||||
## Run iosbuild.sh to create 'VPX.framework' in the current directory.
|
||||
##
|
||||
set -e
|
||||
devnull='> /dev/null 2>&1'
|
||||
|
||||
BUILD_ROOT="_iosbuild"
|
||||
CONFIGURE_ARGS="--disable-docs
|
||||
--disable-examples
|
||||
--disable-libyuv
|
||||
--disable-unit-tests"
|
||||
DIST_DIR="_dist"
|
||||
FRAMEWORK_DIR="VPX.framework"
|
||||
FRAMEWORK_LIB="VPX.framework/VPX"
|
||||
HEADER_DIR="${FRAMEWORK_DIR}/Headers/vpx"
|
||||
SCRIPT_DIR=$(dirname "$0")
|
||||
LIBVPX_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd)
|
||||
LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
|
||||
ORIG_PWD="$(pwd)"
|
||||
ARM_TARGETS="arm64-darwin-gcc
|
||||
armv7-darwin-gcc
|
||||
armv7s-darwin-gcc"
|
||||
SIM_TARGETS="x86-iphonesimulator-gcc
|
||||
x86_64-iphonesimulator-gcc"
|
||||
OSX_TARGETS="x86-darwin16-gcc
|
||||
x86_64-darwin16-gcc"
|
||||
TARGETS="${ARM_TARGETS} ${SIM_TARGETS}"
|
||||
|
||||
# Configures for the target specified by $1, and invokes make with the dist
|
||||
# target using $DIST_DIR as the distribution output directory.
|
||||
build_target() {
|
||||
local target="$1"
|
||||
local old_pwd="$(pwd)"
|
||||
local target_specific_flags=""
|
||||
|
||||
vlog "***Building target: ${target}***"
|
||||
|
||||
case "${target}" in
|
||||
x86-*)
|
||||
target_specific_flags="--enable-pic"
|
||||
vlog "Enabled PIC for ${target}"
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir "${target}"
|
||||
cd "${target}"
|
||||
eval "${LIBVPX_SOURCE_DIR}/configure" --target="${target}" \
|
||||
${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \
|
||||
${devnull}
|
||||
export DIST_DIR
|
||||
eval make dist ${devnull}
|
||||
cd "${old_pwd}"
|
||||
|
||||
vlog "***Done building target: ${target}***"
|
||||
}
|
||||
|
||||
# Returns the preprocessor symbol for the target specified by $1.
|
||||
target_to_preproc_symbol() {
|
||||
target="$1"
|
||||
case "${target}" in
|
||||
arm64-*)
|
||||
echo "__aarch64__"
|
||||
;;
|
||||
armv7-*)
|
||||
echo "__ARM_ARCH_7A__"
|
||||
;;
|
||||
armv7s-*)
|
||||
echo "__ARM_ARCH_7S__"
|
||||
;;
|
||||
x86-*)
|
||||
echo "__i386__"
|
||||
;;
|
||||
x86_64-*)
|
||||
echo "__x86_64__"
|
||||
;;
|
||||
*)
|
||||
echo "#error ${target} unknown/unsupported"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Create a vpx_config.h shim that, based on preprocessor settings for the
|
||||
# current target CPU, includes the real vpx_config.h for the current target.
|
||||
# $1 is the list of targets.
|
||||
create_vpx_framework_config_shim() {
|
||||
local targets="$1"
|
||||
local config_file="${HEADER_DIR}/vpx_config.h"
|
||||
local preproc_symbol=""
|
||||
local target=""
|
||||
local include_guard="VPX_FRAMEWORK_HEADERS_VPX_VPX_CONFIG_H_"
|
||||
|
||||
local file_header="/*
|
||||
* Copyright (c) $(date +%Y) 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.
|
||||
*/
|
||||
|
||||
/* GENERATED FILE: DO NOT EDIT! */
|
||||
|
||||
#ifndef ${include_guard}
|
||||
#define ${include_guard}
|
||||
|
||||
#if defined"
|
||||
|
||||
printf "%s" "${file_header}" > "${config_file}"
|
||||
for target in ${targets}; do
|
||||
preproc_symbol=$(target_to_preproc_symbol "${target}")
|
||||
printf " ${preproc_symbol}\n" >> "${config_file}"
|
||||
printf "#define VPX_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}"
|
||||
printf "#include \"VPX/vpx/${target}/vpx_config.h\"\n" >> "${config_file}"
|
||||
printf "#elif defined" >> "${config_file}"
|
||||
mkdir "${HEADER_DIR}/${target}"
|
||||
cp -p "${BUILD_ROOT}/${target}/vpx_config.h" "${HEADER_DIR}/${target}"
|
||||
done
|
||||
|
||||
# Consume the last line of output from the loop: We don't want it.
|
||||
sed -i '' -e '$d' "${config_file}"
|
||||
|
||||
printf "#endif\n\n" >> "${config_file}"
|
||||
printf "#endif // ${include_guard}" >> "${config_file}"
|
||||
}
|
||||
|
||||
# Verifies that $FRAMEWORK_LIB fat library contains requested builds.
|
||||
verify_framework_targets() {
|
||||
local requested_cpus=""
|
||||
local cpu=""
|
||||
|
||||
# Extract CPU from full target name.
|
||||
for target; do
|
||||
cpu="${target%%-*}"
|
||||
if [ "${cpu}" = "x86" ]; then
|
||||
# lipo -info outputs i386 for libvpx x86 targets.
|
||||
cpu="i386"
|
||||
fi
|
||||
requested_cpus="${requested_cpus}${cpu} "
|
||||
done
|
||||
|
||||
# Get target CPUs present in framework library.
|
||||
local targets_built=$(${LIPO} -info ${FRAMEWORK_LIB})
|
||||
|
||||
# $LIPO -info outputs a string like the following:
|
||||
# Architectures in the fat file: $FRAMEWORK_LIB <architectures>
|
||||
# Capture only the architecture strings.
|
||||
targets_built=${targets_built##*: }
|
||||
|
||||
# Sort CPU strings to make the next step a simple string compare.
|
||||
local actual=$(echo ${targets_built} | tr " " "\n" | sort | tr "\n" " ")
|
||||
local requested=$(echo ${requested_cpus} | tr " " "\n" | sort | tr "\n" " ")
|
||||
|
||||
vlog "Requested ${FRAMEWORK_LIB} CPUs: ${requested}"
|
||||
vlog "Actual ${FRAMEWORK_LIB} CPUs: ${actual}"
|
||||
|
||||
if [ "${requested}" != "${actual}" ]; then
|
||||
elog "Actual ${FRAMEWORK_LIB} targets do not match requested target list."
|
||||
elog " Requested target CPUs: ${requested}"
|
||||
elog " Actual target CPUs: ${actual}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Configures and builds each target specified by $1, and then builds
|
||||
# VPX.framework.
|
||||
build_framework() {
|
||||
local lib_list=""
|
||||
local targets="$1"
|
||||
local target=""
|
||||
local target_dist_dir=""
|
||||
|
||||
# Clean up from previous build(s).
|
||||
rm -rf "${BUILD_ROOT}" "${FRAMEWORK_DIR}"
|
||||
|
||||
# Create output dirs.
|
||||
mkdir -p "${BUILD_ROOT}"
|
||||
mkdir -p "${HEADER_DIR}"
|
||||
|
||||
cd "${BUILD_ROOT}"
|
||||
|
||||
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}"
|
||||
done
|
||||
|
||||
cd "${ORIG_PWD}"
|
||||
|
||||
# The basic libvpx API includes are all the same; just grab the most recent
|
||||
# set.
|
||||
cp -p "${target_dist_dir}"/include/vpx/* "${HEADER_DIR}"
|
||||
|
||||
# Build the fat library.
|
||||
${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/VPX
|
||||
|
||||
# Create the vpx_config.h shim that allows usage of vpx_config.h from
|
||||
# within VPX.framework.
|
||||
create_vpx_framework_config_shim "${targets}"
|
||||
|
||||
# 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}
|
||||
|
||||
vlog "Created fat library ${FRAMEWORK_LIB} containing:"
|
||||
for lib in ${lib_list}; do
|
||||
vlog " $(echo ${lib} | awk -F / '{print $2, $NF}')"
|
||||
done
|
||||
}
|
||||
|
||||
# Trap function. Cleans up the subtree used to build all targets contained in
|
||||
# $TARGETS.
|
||||
cleanup() {
|
||||
local readonly res=$?
|
||||
cd "${ORIG_PWD}"
|
||||
|
||||
if [ $res -ne 0 ]; then
|
||||
elog "build exited with error ($res)"
|
||||
fi
|
||||
|
||||
if [ "${PRESERVE_BUILD_OUTPUT}" != "yes" ]; then
|
||||
rm -rf "${BUILD_ROOT}"
|
||||
fi
|
||||
}
|
||||
|
||||
print_list() {
|
||||
local indent="$1"
|
||||
shift
|
||||
local list="$@"
|
||||
for entry in ${list}; do
|
||||
echo "${indent}${entry}"
|
||||
done
|
||||
}
|
||||
|
||||
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
|
||||
and x86_64. Allows linking to framework when builds target MacOSX
|
||||
instead of iOS.
|
||||
--preserve-build-output: Do not delete the build directory.
|
||||
--show-build-output: Show output from each library build.
|
||||
--targets <targets>: Override default target list. Defaults:
|
||||
$(print_list " " ${TARGETS})
|
||||
--test-link: Confirms all targets can be linked. Functionally identical to
|
||||
passing --enable-examples via --extra-configure-args.
|
||||
--verbose: Output information about the environment and each stage of the
|
||||
build.
|
||||
EOF
|
||||
}
|
||||
|
||||
elog() {
|
||||
echo "${0##*/} failed because: $@" 1>&2
|
||||
}
|
||||
|
||||
vlog() {
|
||||
if [ "${VERBOSE}" = "yes" ]; then
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
# Parse the command line.
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
--extra-configure-args)
|
||||
EXTRA_CONFIGURE_ARGS="$2"
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
iosbuild_usage
|
||||
exit
|
||||
;;
|
||||
--enable-shared)
|
||||
ENABLE_SHARED=yes
|
||||
;;
|
||||
--preserve-build-output)
|
||||
PRESERVE_BUILD_OUTPUT=yes
|
||||
;;
|
||||
--show-build-output)
|
||||
devnull=
|
||||
;;
|
||||
--test-link)
|
||||
EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples"
|
||||
;;
|
||||
--targets)
|
||||
TARGETS="$2"
|
||||
shift
|
||||
;;
|
||||
--macosx)
|
||||
TARGETS="${ARM_TARGETS} ${OSX_TARGETS}"
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=yes
|
||||
;;
|
||||
*)
|
||||
iosbuild_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
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}
|
||||
DIST_DIR=${DIST_DIR}
|
||||
CONFIGURE_ARGS=${CONFIGURE_ARGS}
|
||||
EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS}
|
||||
FRAMEWORK_DIR=${FRAMEWORK_DIR}
|
||||
FRAMEWORK_LIB=${FRAMEWORK_LIB}
|
||||
HEADER_DIR=${HEADER_DIR}
|
||||
LIBVPX_SOURCE_DIR=${LIBVPX_SOURCE_DIR}
|
||||
LIPO=${LIPO}
|
||||
MAKEFLAGS=${MAKEFLAGS}
|
||||
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
|
||||
|
||||
build_framework "${TARGETS}"
|
||||
echo "Successfully built '${FRAMEWORK_DIR}' for:"
|
||||
print_list "" ${TARGETS}
|
||||
@@ -1,114 +0,0 @@
|
||||
#!/bin/bash
|
||||
##
|
||||
## 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.
|
||||
##
|
||||
|
||||
if [ "$(uname -o 2>/dev/null)" = "Cygwin" ] \
|
||||
&& cygpath --help >/dev/null 2>&1; then
|
||||
FIXPATH='cygpath -m'
|
||||
else
|
||||
FIXPATH='echo_path'
|
||||
fi
|
||||
|
||||
die() {
|
||||
echo "${self_basename}: $@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
die_unknown(){
|
||||
echo "Unknown option \"$1\"." >&2
|
||||
echo "See ${self_basename} --help for available options." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo_path() {
|
||||
for path; do
|
||||
echo "$path"
|
||||
done
|
||||
}
|
||||
|
||||
# Output one, possibly changed based on the system, path per line.
|
||||
fix_path() {
|
||||
$FIXPATH "$@"
|
||||
}
|
||||
|
||||
# Corrects the paths in file_list in one pass for efficiency.
|
||||
# $1 is the name of the array to be modified.
|
||||
fix_file_list() {
|
||||
declare -n array_ref=$1
|
||||
files=$(fix_path "${array_ref[@]}")
|
||||
local IFS=$'\n'
|
||||
array_ref=($files)
|
||||
}
|
||||
|
||||
generate_uuid() {
|
||||
local hex="0123456789ABCDEF"
|
||||
local i
|
||||
local uuid=""
|
||||
local j
|
||||
#93995380-89BD-4b04-88EB-625FBE52EBFB
|
||||
for ((i=0; i<32; i++)); do
|
||||
(( j = $RANDOM % 16 ))
|
||||
uuid="${uuid}${hex:$j:1}"
|
||||
done
|
||||
echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
|
||||
}
|
||||
|
||||
indent1=" "
|
||||
indent=""
|
||||
indent_push() {
|
||||
indent="${indent}${indent1}"
|
||||
}
|
||||
indent_pop() {
|
||||
indent="${indent%${indent1}}"
|
||||
}
|
||||
|
||||
tag_attributes() {
|
||||
for opt in "$@"; do
|
||||
optval="${opt#*=}"
|
||||
[ -n "${optval}" ] ||
|
||||
die "Missing attribute value in '$opt' while generating $tag tag"
|
||||
echo "${indent}${opt%%=*}=\"${optval}\""
|
||||
done
|
||||
}
|
||||
|
||||
open_tag() {
|
||||
local tag=$1
|
||||
shift
|
||||
if [ $# -ne 0 ]; then
|
||||
echo "${indent}<${tag}"
|
||||
indent_push
|
||||
tag_attributes "$@"
|
||||
echo "${indent}>"
|
||||
else
|
||||
echo "${indent}<${tag}>"
|
||||
indent_push
|
||||
fi
|
||||
}
|
||||
|
||||
close_tag() {
|
||||
local tag=$1
|
||||
indent_pop
|
||||
echo "${indent}</${tag}>"
|
||||
}
|
||||
|
||||
tag() {
|
||||
local tag=$1
|
||||
shift
|
||||
if [ $# -ne 0 ]; then
|
||||
echo "${indent}<${tag}"
|
||||
indent_push
|
||||
tag_attributes "$@"
|
||||
indent_pop
|
||||
echo "${indent}/>"
|
||||
else
|
||||
echo "${indent}<${tag}/>"
|
||||
fi
|
||||
}
|
||||
|
||||
827
build/make/obj_int_extract.c
Normal file
827
build/make/obj_int_extract.c
Normal file
@@ -0,0 +1,827 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vpx_config.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
|
||||
typedef enum {
|
||||
OUTPUT_FMT_PLAIN,
|
||||
OUTPUT_FMT_RVDS,
|
||||
OUTPUT_FMT_GAS,
|
||||
} output_fmt_t;
|
||||
|
||||
int log_msg(const char *fmt, ...) {
|
||||
int res;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
res = vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__
|
||||
#if defined(__MACH__)
|
||||
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/nlist.h>
|
||||
|
||||
int print_macho_equ(output_fmt_t mode, uint8_t* name, int val) {
|
||||
switch (mode) {
|
||||
case OUTPUT_FMT_RVDS:
|
||||
printf("%-40s EQU %5d\n", name, val);
|
||||
return 0;
|
||||
case OUTPUT_FMT_GAS:
|
||||
printf(".set %-40s, %5d\n", name, val);
|
||||
return 0;
|
||||
default:
|
||||
log_msg("Unsupported mode: %d", mode);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int parse_macho(uint8_t *base_buf, size_t sz, output_fmt_t mode) {
|
||||
int i, j;
|
||||
struct mach_header header;
|
||||
uint8_t *buf = base_buf;
|
||||
int base_data_section = 0;
|
||||
int bits = 0;
|
||||
|
||||
/* We can read in mach_header for 32 and 64 bit architectures
|
||||
* because it's identical to mach_header_64 except for the last
|
||||
* element (uint32_t reserved), which we don't use. Then, when
|
||||
* we know which architecture we're looking at, increment buf
|
||||
* appropriately.
|
||||
*/
|
||||
memcpy(&header, buf, sizeof(struct mach_header));
|
||||
|
||||
if (header.magic == MH_MAGIC) {
|
||||
if (header.cputype == CPU_TYPE_ARM
|
||||
|| header.cputype == CPU_TYPE_X86) {
|
||||
bits = 32;
|
||||
buf += sizeof(struct mach_header);
|
||||
} else {
|
||||
log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_[ARM|X86].\n");
|
||||
goto bail;
|
||||
}
|
||||
} else if (header.magic == MH_MAGIC_64) {
|
||||
if (header.cputype == CPU_TYPE_X86_64) {
|
||||
bits = 64;
|
||||
buf += sizeof(struct mach_header_64);
|
||||
} else {
|
||||
log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_X86_64.\n");
|
||||
goto bail;
|
||||
}
|
||||
} else {
|
||||
log_msg("Bad magic number for object file. 0x%x or 0x%x expected, 0x%x found.\n",
|
||||
MH_MAGIC, MH_MAGIC_64, header.magic);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (header.filetype != MH_OBJECT) {
|
||||
log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
for (i = 0; i < header.ncmds; i++) {
|
||||
struct load_command lc;
|
||||
|
||||
memcpy(&lc, buf, sizeof(struct load_command));
|
||||
|
||||
if (lc.cmd == LC_SEGMENT) {
|
||||
uint8_t *seg_buf = buf;
|
||||
struct section s;
|
||||
struct segment_command seg_c;
|
||||
|
||||
memcpy(&seg_c, seg_buf, sizeof(struct segment_command));
|
||||
seg_buf += sizeof(struct segment_command);
|
||||
|
||||
/* Although each section is given it's own offset, nlist.n_value
|
||||
* references the offset of the first section. This isn't
|
||||
* apparent without debug information because the offset of the
|
||||
* data section is the same as the first section. However, with
|
||||
* debug sections mixed in, the offset of the debug section
|
||||
* increases but n_value still references the first section.
|
||||
*/
|
||||
if (seg_c.nsects < 1) {
|
||||
log_msg("Not enough sections\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
memcpy(&s, seg_buf, sizeof(struct section));
|
||||
base_data_section = s.offset;
|
||||
} else if (lc.cmd == LC_SEGMENT_64) {
|
||||
uint8_t *seg_buf = buf;
|
||||
struct section_64 s;
|
||||
struct segment_command_64 seg_c;
|
||||
|
||||
memcpy(&seg_c, seg_buf, sizeof(struct segment_command_64));
|
||||
seg_buf += sizeof(struct segment_command_64);
|
||||
|
||||
/* Explanation in LG_SEGMENT */
|
||||
if (seg_c.nsects < 1) {
|
||||
log_msg("Not enough sections\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
memcpy(&s, seg_buf, sizeof(struct section_64));
|
||||
base_data_section = s.offset;
|
||||
} else if (lc.cmd == LC_SYMTAB) {
|
||||
if (base_data_section != 0) {
|
||||
struct symtab_command sc;
|
||||
uint8_t *sym_buf = base_buf;
|
||||
uint8_t *str_buf = base_buf;
|
||||
|
||||
memcpy(&sc, buf, sizeof(struct symtab_command));
|
||||
|
||||
if (sc.cmdsize != sizeof(struct symtab_command)) {
|
||||
log_msg("Can't find symbol table!\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
sym_buf += sc.symoff;
|
||||
str_buf += sc.stroff;
|
||||
|
||||
for (j = 0; j < sc.nsyms; j++) {
|
||||
/* Location of string is cacluated each time from the
|
||||
* start of the string buffer. On darwin the symbols
|
||||
* are prefixed by "_", so we bump the pointer by 1.
|
||||
* The target value is defined as an int in *_asm_*_offsets.c,
|
||||
* which is 4 bytes on all targets we currently use.
|
||||
*/
|
||||
if (bits == 32) {
|
||||
struct nlist nl;
|
||||
int val;
|
||||
|
||||
memcpy(&nl, sym_buf, sizeof(struct nlist));
|
||||
sym_buf += sizeof(struct nlist);
|
||||
|
||||
memcpy(&val, base_buf + base_data_section + nl.n_value,
|
||||
sizeof(val));
|
||||
print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
|
||||
} else { /* if (bits == 64) */
|
||||
struct nlist_64 nl;
|
||||
int val;
|
||||
|
||||
memcpy(&nl, sym_buf, sizeof(struct nlist_64));
|
||||
sym_buf += sizeof(struct nlist_64);
|
||||
|
||||
memcpy(&val, base_buf + base_data_section + nl.n_value,
|
||||
sizeof(val));
|
||||
print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf += lc.cmdsize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
bail:
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
#elif defined(__ELF__)
|
||||
#include "elf.h"
|
||||
|
||||
#define COPY_STRUCT(dst, buf, ofst, sz) do {\
|
||||
if(ofst + sizeof((*(dst))) > sz) goto bail;\
|
||||
memcpy(dst, buf+ofst, sizeof((*(dst))));\
|
||||
} while(0)
|
||||
|
||||
#define ENDIAN_ASSIGN(val, memb) do {\
|
||||
if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
|
||||
(val) = (memb);\
|
||||
} while(0)
|
||||
|
||||
#define ENDIAN_ASSIGN_IN_PLACE(memb) do {\
|
||||
ENDIAN_ASSIGN(memb, memb);\
|
||||
} while(0)
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buf; /* Buffer containing ELF data */
|
||||
size_t sz; /* Buffer size */
|
||||
int le_data; /* Data is little-endian */
|
||||
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||
int bits; /* 32 or 64 */
|
||||
Elf32_Ehdr hdr32;
|
||||
Elf64_Ehdr hdr64;
|
||||
} elf_obj_t;
|
||||
|
||||
int parse_elf_header(elf_obj_t *elf) {
|
||||
int res;
|
||||
/* Verify ELF Magic numbers */
|
||||
COPY_STRUCT(&elf->e_ident, elf->buf, 0, elf->sz);
|
||||
res = elf->e_ident[EI_MAG0] == ELFMAG0;
|
||||
res &= elf->e_ident[EI_MAG1] == ELFMAG1;
|
||||
res &= elf->e_ident[EI_MAG2] == ELFMAG2;
|
||||
res &= elf->e_ident[EI_MAG3] == ELFMAG3;
|
||||
res &= elf->e_ident[EI_CLASS] == ELFCLASS32
|
||||
|| elf->e_ident[EI_CLASS] == ELFCLASS64;
|
||||
res &= elf->e_ident[EI_DATA] == ELFDATA2LSB;
|
||||
|
||||
if (!res) goto bail;
|
||||
|
||||
elf->le_data = elf->e_ident[EI_DATA] == ELFDATA2LSB;
|
||||
|
||||
/* Read in relevant values */
|
||||
if (elf->e_ident[EI_CLASS] == ELFCLASS32) {
|
||||
elf->bits = 32;
|
||||
COPY_STRUCT(&elf->hdr32, elf->buf, 0, elf->sz);
|
||||
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_type);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_machine);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_version);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_entry);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phoff);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shoff);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_flags);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_ehsize);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phentsize);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phnum);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shentsize);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shnum);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shstrndx);
|
||||
} else { /* if (elf->e_ident[EI_CLASS] == ELFCLASS64) */
|
||||
elf->bits = 64;
|
||||
COPY_STRUCT(&elf->hdr64, elf->buf, 0, elf->sz);
|
||||
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_type);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_machine);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_version);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_entry);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phoff);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shoff);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_flags);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_ehsize);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phentsize);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phnum);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shentsize);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shnum);
|
||||
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shstrndx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
bail:
|
||||
log_msg("Failed to parse ELF file header");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_elf_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr32, Elf64_Shdr *hdr64) {
|
||||
if (hdr32) {
|
||||
if (idx >= elf->hdr32.e_shnum)
|
||||
goto bail;
|
||||
|
||||
COPY_STRUCT(hdr32, elf->buf, elf->hdr32.e_shoff + idx * elf->hdr32.e_shentsize,
|
||||
elf->sz);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_name);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_type);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_flags);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addr);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_offset);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_size);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_link);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_info);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addralign);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_entsize);
|
||||
} else { /* if (hdr64) */
|
||||
if (idx >= elf->hdr64.e_shnum)
|
||||
goto bail;
|
||||
|
||||
COPY_STRUCT(hdr64, elf->buf, elf->hdr64.e_shoff + idx * elf->hdr64.e_shentsize,
|
||||
elf->sz);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_name);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_type);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_flags);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addr);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_offset);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_size);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_link);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_info);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addralign);
|
||||
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_entsize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
bail:
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) {
|
||||
if (elf->bits == 32) {
|
||||
Elf32_Shdr shdr;
|
||||
|
||||
if (parse_elf_section(elf, s_idx, &shdr, NULL)) {
|
||||
log_msg("Failed to parse ELF string table: section %d, index %d\n",
|
||||
s_idx, idx);
|
||||
return "";
|
||||
}
|
||||
|
||||
return (char *)(elf->buf + shdr.sh_offset + idx);
|
||||
} else { /* if (elf->bits == 64) */
|
||||
Elf64_Shdr shdr;
|
||||
|
||||
if (parse_elf_section(elf, s_idx, NULL, &shdr)) {
|
||||
log_msg("Failed to parse ELF string table: section %d, index %d\n",
|
||||
s_idx, idx);
|
||||
return "";
|
||||
}
|
||||
|
||||
return (char *)(elf->buf + shdr.sh_offset + idx);
|
||||
}
|
||||
}
|
||||
|
||||
int parse_elf_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym32, Elf64_Sym *sym64) {
|
||||
if (sym32) {
|
||||
COPY_STRUCT(sym32, elf->buf, ofst, elf->sz);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym32->st_name);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym32->st_value);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym32->st_size);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym32->st_info);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym32->st_other);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym32->st_shndx);
|
||||
} else { /* if (sym64) */
|
||||
COPY_STRUCT(sym64, elf->buf, ofst, elf->sz);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym64->st_name);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym64->st_value);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym64->st_size);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym64->st_info);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym64->st_other);
|
||||
ENDIAN_ASSIGN_IN_PLACE(sym64->st_shndx);
|
||||
}
|
||||
return 0;
|
||||
bail:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_elf(uint8_t *buf, size_t sz, output_fmt_t mode) {
|
||||
elf_obj_t elf;
|
||||
unsigned int ofst;
|
||||
int i;
|
||||
Elf32_Off strtab_off32;
|
||||
Elf64_Off strtab_off64; /* save String Table offset for later use */
|
||||
|
||||
memset(&elf, 0, sizeof(elf));
|
||||
elf.buf = buf;
|
||||
elf.sz = sz;
|
||||
|
||||
/* Parse Header */
|
||||
if (parse_elf_header(&elf))
|
||||
goto bail;
|
||||
|
||||
if (elf.bits == 32) {
|
||||
Elf32_Shdr shdr;
|
||||
for (i = 0; i < elf.hdr32.e_shnum; i++) {
|
||||
parse_elf_section(&elf, i, &shdr, NULL);
|
||||
|
||||
if (shdr.sh_type == SHT_STRTAB) {
|
||||
char strtsb_name[128];
|
||||
|
||||
strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
|
||||
|
||||
if (!(strcmp(strtsb_name, ".shstrtab"))) {
|
||||
/* log_msg("found section: %s\n", strtsb_name); */
|
||||
strtab_off32 = shdr.sh_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { /* if (elf.bits == 64) */
|
||||
Elf64_Shdr shdr;
|
||||
for (i = 0; i < elf.hdr64.e_shnum; i++) {
|
||||
parse_elf_section(&elf, i, NULL, &shdr);
|
||||
|
||||
if (shdr.sh_type == SHT_STRTAB) {
|
||||
char strtsb_name[128];
|
||||
|
||||
strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
|
||||
|
||||
if (!(strcmp(strtsb_name, ".shstrtab"))) {
|
||||
/* log_msg("found section: %s\n", strtsb_name); */
|
||||
strtab_off64 = shdr.sh_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse all Symbol Tables */
|
||||
if (elf.bits == 32) {
|
||||
Elf32_Shdr shdr;
|
||||
for (i = 0; i < elf.hdr32.e_shnum; i++) {
|
||||
parse_elf_section(&elf, i, &shdr, NULL);
|
||||
|
||||
if (shdr.sh_type == SHT_SYMTAB) {
|
||||
for (ofst = shdr.sh_offset;
|
||||
ofst < shdr.sh_offset + shdr.sh_size;
|
||||
ofst += shdr.sh_entsize) {
|
||||
Elf32_Sym sym;
|
||||
|
||||
parse_elf_symbol(&elf, ofst, &sym, NULL);
|
||||
|
||||
/* For all OBJECTS (data objects), extract the value from the
|
||||
* proper data segment.
|
||||
*/
|
||||
/* if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
|
||||
log_msg("found data object %s\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name));
|
||||
*/
|
||||
|
||||
if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
|
||||
&& sym.st_size == 4) {
|
||||
Elf32_Shdr dhdr;
|
||||
int val = 0;
|
||||
char section_name[128];
|
||||
|
||||
parse_elf_section(&elf, sym.st_shndx, &dhdr, NULL);
|
||||
|
||||
/* For explanition - refer to _MSC_VER version of code */
|
||||
strcpy(section_name, (char *)(elf.buf + strtab_off32 + dhdr.sh_name));
|
||||
/* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
|
||||
|
||||
if (strcmp(section_name, ".bss")) {
|
||||
if (sizeof(val) != sym.st_size) {
|
||||
/* The target value is declared as an int in
|
||||
* *_asm_*_offsets.c, which is 4 bytes on all
|
||||
* targets we currently use. Complain loudly if
|
||||
* this is not true.
|
||||
*/
|
||||
log_msg("Symbol size is wrong\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
memcpy(&val,
|
||||
elf.buf + dhdr.sh_offset + sym.st_value,
|
||||
sym.st_size);
|
||||
}
|
||||
|
||||
if (!elf.le_data) {
|
||||
log_msg("Big Endian data not supported yet!\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case OUTPUT_FMT_RVDS:
|
||||
printf("%-40s EQU %5d\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name),
|
||||
val);
|
||||
break;
|
||||
case OUTPUT_FMT_GAS:
|
||||
printf(".equ %-40s, %5d\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name),
|
||||
val);
|
||||
break;
|
||||
default:
|
||||
printf("%s = %d\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name),
|
||||
val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { /* if (elf.bits == 64) */
|
||||
Elf64_Shdr shdr;
|
||||
for (i = 0; i < elf.hdr64.e_shnum; i++) {
|
||||
parse_elf_section(&elf, i, NULL, &shdr);
|
||||
|
||||
if (shdr.sh_type == SHT_SYMTAB) {
|
||||
for (ofst = shdr.sh_offset;
|
||||
ofst < shdr.sh_offset + shdr.sh_size;
|
||||
ofst += shdr.sh_entsize) {
|
||||
Elf64_Sym sym;
|
||||
|
||||
parse_elf_symbol(&elf, ofst, NULL, &sym);
|
||||
|
||||
/* For all OBJECTS (data objects), extract the value from the
|
||||
* proper data segment.
|
||||
*/
|
||||
/* if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
|
||||
log_msg("found data object %s\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name));
|
||||
*/
|
||||
|
||||
if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT
|
||||
&& sym.st_size == 4) {
|
||||
Elf64_Shdr dhdr;
|
||||
int val = 0;
|
||||
char section_name[128];
|
||||
|
||||
parse_elf_section(&elf, sym.st_shndx, NULL, &dhdr);
|
||||
|
||||
/* For explanition - refer to _MSC_VER version of code */
|
||||
strcpy(section_name, (char *)(elf.buf + strtab_off64 + dhdr.sh_name));
|
||||
/* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
|
||||
|
||||
if ((strcmp(section_name, ".bss"))) {
|
||||
if (sizeof(val) != sym.st_size) {
|
||||
/* The target value is declared as an int in
|
||||
* *_asm_*_offsets.c, which is 4 bytes on all
|
||||
* targets we currently use. Complain loudly if
|
||||
* this is not true.
|
||||
*/
|
||||
log_msg("Symbol size is wrong\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
memcpy(&val,
|
||||
elf.buf + dhdr.sh_offset + sym.st_value,
|
||||
sym.st_size);
|
||||
}
|
||||
|
||||
if (!elf.le_data) {
|
||||
log_msg("Big Endian data not supported yet!\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case OUTPUT_FMT_RVDS:
|
||||
printf("%-40s EQU %5d\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name),
|
||||
val);
|
||||
break;
|
||||
case OUTPUT_FMT_GAS:
|
||||
printf(".equ %-40s, %5d\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name),
|
||||
val);
|
||||
break;
|
||||
default:
|
||||
printf("%s = %d\n",
|
||||
parse_elf_string_table(&elf,
|
||||
shdr.sh_link,
|
||||
sym.st_name),
|
||||
val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == OUTPUT_FMT_RVDS)
|
||||
printf(" END\n");
|
||||
|
||||
return 0;
|
||||
bail:
|
||||
log_msg("Parse error: File does not appear to be valid ELF32 or ELF64\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* defined(__GNUC__) && __GNUC__ */
|
||||
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
/* See "Microsoft Portable Executable and Common Object File Format Specification"
|
||||
for reference.
|
||||
*/
|
||||
#define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 )
|
||||
#define get_le16(x) ((*(x)) | (*(x+1)) << 8)
|
||||
|
||||
int parse_coff(uint8_t *buf, size_t sz) {
|
||||
unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
|
||||
unsigned int sectionrawdata_ptr;
|
||||
unsigned int i;
|
||||
uint8_t *ptr;
|
||||
uint32_t symoffset;
|
||||
|
||||
char **sectionlist; // this array holds all section names in their correct order.
|
||||
// it is used to check if the symbol is in .bss or .rdata section.
|
||||
|
||||
nsections = get_le16(buf + 2);
|
||||
symtab_ptr = get_le32(buf + 8);
|
||||
symtab_sz = get_le32(buf + 12);
|
||||
strtab_ptr = symtab_ptr + symtab_sz * 18;
|
||||
|
||||
if (nsections > 96) {
|
||||
log_msg("Too many sections\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sectionlist = malloc(nsections * sizeof(sectionlist));
|
||||
|
||||
if (sectionlist == NULL) {
|
||||
log_msg("Allocating first level of section list failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
|
||||
|
||||
/*
|
||||
The size of optional header is always zero for an obj file. So, the section header
|
||||
follows the file header immediately.
|
||||
*/
|
||||
|
||||
ptr = buf + 20; // section header
|
||||
|
||||
for (i = 0; i < nsections; i++) {
|
||||
char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
strncpy(sectionname, ptr, 8);
|
||||
// log_msg("COFF: Parsing section %s\n",sectionname);
|
||||
|
||||
sectionlist[i] = malloc(strlen(sectionname) + 1);
|
||||
|
||||
if (sectionlist[i] == NULL) {
|
||||
log_msg("Allocating storage for %s failed\n", sectionname);
|
||||
goto bail;
|
||||
}
|
||||
strcpy(sectionlist[i], sectionname);
|
||||
|
||||
if (!strcmp(sectionname, ".rdata")) sectionrawdata_ptr = get_le32(ptr + 20);
|
||||
|
||||
ptr += 40;
|
||||
}
|
||||
|
||||
// log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
|
||||
// log_msg("COFF: raw data pointer ofset for section .rdata is %u\n", sectionrawdata_ptr);
|
||||
|
||||
/* The compiler puts the data with non-zero offset in .rdata section, but puts the data with
|
||||
zero offset in .bss section. So, if the data in in .bss section, set offset=0.
|
||||
Note from Wiki: In an object module compiled from C, the bss section contains
|
||||
the local variables (but not functions) that were declared with the static keyword,
|
||||
except for those with non-zero initial values. (In C, static variables are initialized
|
||||
to zero by default.) It also contains the non-local (both extern and static) variables
|
||||
that are also initialized to zero (either explicitly or by default).
|
||||
*/
|
||||
// move to symbol table
|
||||
/* COFF symbol table:
|
||||
offset field
|
||||
0 Name(*)
|
||||
8 Value
|
||||
12 SectionNumber
|
||||
14 Type
|
||||
16 StorageClass
|
||||
17 NumberOfAuxSymbols
|
||||
*/
|
||||
ptr = buf + symtab_ptr;
|
||||
|
||||
for (i = 0; i < symtab_sz; i++) {
|
||||
int16_t section = get_le16(ptr + 12); // section number
|
||||
|
||||
if (section > 0 && ptr[16] == 2) {
|
||||
// if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
|
||||
|
||||
if (get_le32(ptr)) {
|
||||
char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
strncpy(name, ptr, 8);
|
||||
// log_msg("COFF: Parsing symbol %s\n",name);
|
||||
/* The 64bit Windows compiler doesn't prefix with an _.
|
||||
* Check what's there, and bump if necessary
|
||||
*/
|
||||
if (name[0] == '_')
|
||||
printf("%-40s EQU ", name + 1);
|
||||
else
|
||||
printf("%-40s EQU ", name);
|
||||
} else {
|
||||
// log_msg("COFF: Parsing symbol %s\n",
|
||||
// buf + strtab_ptr + get_le32(ptr+4));
|
||||
if ((buf + strtab_ptr + get_le32(ptr + 4))[0] == '_')
|
||||
printf("%-40s EQU ",
|
||||
buf + strtab_ptr + get_le32(ptr + 4) + 1);
|
||||
else
|
||||
printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
|
||||
}
|
||||
|
||||
if (!(strcmp(sectionlist[section - 1], ".bss"))) {
|
||||
symoffset = 0;
|
||||
} else {
|
||||
symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
|
||||
}
|
||||
|
||||
// log_msg(" Section: %d\n",section);
|
||||
// log_msg(" Class: %d\n",ptr[16]);
|
||||
// log_msg(" Address: %u\n",get_le32(ptr+8));
|
||||
// log_msg(" Offset: %u\n", symoffset);
|
||||
|
||||
printf("%5d\n", symoffset);
|
||||
}
|
||||
|
||||
ptr += 18;
|
||||
}
|
||||
|
||||
printf(" END\n");
|
||||
|
||||
for (i = 0; i < nsections; i++) {
|
||||
free(sectionlist[i]);
|
||||
}
|
||||
|
||||
free(sectionlist);
|
||||
|
||||
return 0;
|
||||
bail:
|
||||
|
||||
for (i = 0; i < nsections; i++) {
|
||||
free(sectionlist[i]);
|
||||
}
|
||||
|
||||
free(sectionlist);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) */
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
output_fmt_t mode = OUTPUT_FMT_PLAIN;
|
||||
const char *f;
|
||||
uint8_t *file_buf;
|
||||
int res;
|
||||
FILE *fp;
|
||||
long int file_size;
|
||||
|
||||
if (argc < 2 || argc > 3) {
|
||||
fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
|
||||
fprintf(stderr, " <obj file>\tobject file to parse\n");
|
||||
fprintf(stderr, "Output Formats:\n");
|
||||
fprintf(stderr, " gas - compatible with GNU assembler\n");
|
||||
fprintf(stderr, " rvds - compatible with armasm\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
f = argv[2];
|
||||
|
||||
if (!strcmp(argv[1], "rvds"))
|
||||
mode = OUTPUT_FMT_RVDS;
|
||||
else if (!strcmp(argv[1], "gas"))
|
||||
mode = OUTPUT_FMT_GAS;
|
||||
else
|
||||
f = argv[1];
|
||||
|
||||
fp = fopen(f, "rb");
|
||||
|
||||
if (!fp) {
|
||||
perror("Unable to open file");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (fseek(fp, 0, SEEK_END)) {
|
||||
perror("stat");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
file_size = ftell(fp);
|
||||
file_buf = malloc(file_size);
|
||||
|
||||
if (!file_buf) {
|
||||
perror("malloc");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
rewind(fp);
|
||||
|
||||
if (fread(file_buf, sizeof(char), file_size, fp) != file_size) {
|
||||
perror("read");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (fclose(fp)) {
|
||||
perror("close");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__
|
||||
#if defined(__MACH__)
|
||||
res = parse_macho(file_buf, file_size, mode);
|
||||
#elif defined(__ELF__)
|
||||
res = parse_elf(file_buf, file_size, mode);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
res = parse_coff(file_buf, file_size);
|
||||
#endif
|
||||
|
||||
free(file_buf);
|
||||
|
||||
if (!res)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
bail:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,468 +0,0 @@
|
||||
#!/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;
|
||||
use Getopt::Long;
|
||||
Getopt::Long::Configure("auto_help") if $Getopt::Long::VERSION > 2.32;
|
||||
|
||||
my %ALL_FUNCS = ();
|
||||
my @ALL_ARCHS;
|
||||
my @ALL_FORWARD_DECLS;
|
||||
my @REQUIRES;
|
||||
|
||||
my %opts = ();
|
||||
my %disabled = ();
|
||||
my %required = ();
|
||||
|
||||
my @argv;
|
||||
foreach (@ARGV) {
|
||||
$disabled{$1} = 1, next if /--disable-(.*)/;
|
||||
$required{$1} = 1, next if /--require-(.*)/;
|
||||
push @argv, $_;
|
||||
}
|
||||
|
||||
# NB: use GetOptions() instead of GetOptionsFromArray() for compatibility.
|
||||
@ARGV = @argv;
|
||||
GetOptions(
|
||||
\%opts,
|
||||
'arch=s',
|
||||
'sym=s',
|
||||
'config=s',
|
||||
);
|
||||
|
||||
foreach my $opt (qw/arch config/) {
|
||||
if (!defined($opts{$opt})) {
|
||||
warn "--$opt is required!\n";
|
||||
Getopt::Long::HelpMessage('-exit' => 1);
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $defs_file (@ARGV) {
|
||||
if (!-f $defs_file) {
|
||||
warn "$defs_file: $!\n";
|
||||
Getopt::Long::HelpMessage('-exit' => 1);
|
||||
}
|
||||
}
|
||||
|
||||
open CONFIG_FILE, $opts{config} or
|
||||
die "Error opening config file '$opts{config}': $!\n";
|
||||
|
||||
my %config = ();
|
||||
while (<CONFIG_FILE>) {
|
||||
next if !/^(?:CONFIG_|HAVE_)/;
|
||||
chomp;
|
||||
my @pair = split /=/;
|
||||
$config{$pair[0]} = $pair[1];
|
||||
}
|
||||
close CONFIG_FILE;
|
||||
|
||||
#
|
||||
# Routines for the RTCD DSL to call
|
||||
#
|
||||
sub vpx_config($) {
|
||||
return (defined $config{$_[0]}) ? $config{$_[0]} : "";
|
||||
}
|
||||
|
||||
sub specialize {
|
||||
my $fn=$_[0];
|
||||
shift;
|
||||
foreach my $opt (@_) {
|
||||
eval "\$${fn}_${opt}=${fn}_${opt}";
|
||||
}
|
||||
}
|
||||
|
||||
sub add_proto {
|
||||
my $fn = splice(@_, -2, 1);
|
||||
$ALL_FUNCS{$fn} = \@_;
|
||||
specialize $fn, "c";
|
||||
}
|
||||
|
||||
sub require {
|
||||
foreach my $fn (keys %ALL_FUNCS) {
|
||||
foreach my $opt (@_) {
|
||||
my $ofn = eval "\$${fn}_${opt}";
|
||||
next if !$ofn;
|
||||
|
||||
# if we already have a default, then we can disable it, as we know
|
||||
# we can do better.
|
||||
my $best = eval "\$${fn}_default";
|
||||
if ($best) {
|
||||
my $best_ofn = eval "\$${best}";
|
||||
if ($best_ofn && "$best_ofn" ne "$ofn") {
|
||||
eval "\$${best}_link = 'false'";
|
||||
}
|
||||
}
|
||||
eval "\$${fn}_default=${fn}_${opt}";
|
||||
eval "\$${fn}_${opt}_link='true'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub forward_decls {
|
||||
push @ALL_FORWARD_DECLS, @_;
|
||||
}
|
||||
|
||||
#
|
||||
# Include the user's directives
|
||||
#
|
||||
foreach my $f (@ARGV) {
|
||||
open FILE, "<", $f or die "cannot open $f: $!\n";
|
||||
my $contents = join('', <FILE>);
|
||||
close FILE;
|
||||
eval $contents or warn "eval failed: $@\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Process the directives according to the command line
|
||||
#
|
||||
sub process_forward_decls() {
|
||||
foreach (@ALL_FORWARD_DECLS) {
|
||||
$_->();
|
||||
}
|
||||
}
|
||||
|
||||
sub determine_indirection {
|
||||
vpx_config("CONFIG_RUNTIME_CPU_DETECT") eq "yes" or &require(@ALL_ARCHS);
|
||||
foreach my $fn (keys %ALL_FUNCS) {
|
||||
my $n = "";
|
||||
my @val = @{$ALL_FUNCS{$fn}};
|
||||
my $args = pop @val;
|
||||
my $rtyp = "@val";
|
||||
my $dfn = eval "\$${fn}_default";
|
||||
$dfn = eval "\$${dfn}";
|
||||
foreach my $opt (@_) {
|
||||
my $ofn = eval "\$${fn}_${opt}";
|
||||
next if !$ofn;
|
||||
my $link = eval "\$${fn}_${opt}_link";
|
||||
next if $link && $link eq "false";
|
||||
$n .= "x";
|
||||
}
|
||||
if ($n eq "x") {
|
||||
eval "\$${fn}_indirect = 'false'";
|
||||
} else {
|
||||
eval "\$${fn}_indirect = 'true'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub declare_function_pointers {
|
||||
foreach my $fn (sort keys %ALL_FUNCS) {
|
||||
my @val = @{$ALL_FUNCS{$fn}};
|
||||
my $args = pop @val;
|
||||
my $rtyp = "@val";
|
||||
my $dfn = eval "\$${fn}_default";
|
||||
$dfn = eval "\$${dfn}";
|
||||
foreach my $opt (@_) {
|
||||
my $ofn = eval "\$${fn}_${opt}";
|
||||
next if !$ofn;
|
||||
print "$rtyp ${ofn}($args);\n";
|
||||
}
|
||||
if (eval "\$${fn}_indirect" eq "false") {
|
||||
print "#define ${fn} ${dfn}\n";
|
||||
} else {
|
||||
print "RTCD_EXTERN $rtyp (*${fn})($args);\n";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub set_function_pointers {
|
||||
foreach my $fn (sort keys %ALL_FUNCS) {
|
||||
my @val = @{$ALL_FUNCS{$fn}};
|
||||
my $args = pop @val;
|
||||
my $rtyp = "@val";
|
||||
my $dfn = eval "\$${fn}_default";
|
||||
$dfn = eval "\$${dfn}";
|
||||
if (eval "\$${fn}_indirect" eq "true") {
|
||||
print " $fn = $dfn;\n";
|
||||
foreach my $opt (@_) {
|
||||
my $ofn = eval "\$${fn}_${opt}";
|
||||
next if !$ofn;
|
||||
next if "$ofn" eq "$dfn";
|
||||
my $link = eval "\$${fn}_${opt}_link";
|
||||
next if $link && $link eq "false";
|
||||
my $cond = eval "\$have_${opt}";
|
||||
print " if (${cond}) $fn = $ofn;\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub filter {
|
||||
my @filtered;
|
||||
foreach (@_) { push @filtered, $_ unless $disabled{$_}; }
|
||||
return @filtered;
|
||||
}
|
||||
|
||||
#
|
||||
# Helper functions for generating the arch specific RTCD files
|
||||
#
|
||||
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}
|
||||
|
||||
#ifdef RTCD_C
|
||||
#define RTCD_EXTERN
|
||||
#else
|
||||
#define RTCD_EXTERN extern
|
||||
#endif
|
||||
|
||||
EOF
|
||||
|
||||
process_forward_decls();
|
||||
print <<EOF;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
EOF
|
||||
declare_function_pointers("c", @ALL_ARCHS);
|
||||
|
||||
print <<EOF;
|
||||
void $opts{sym}(void);
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
sub common_bottom() {
|
||||
print <<EOF;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
EOF
|
||||
}
|
||||
|
||||
sub x86() {
|
||||
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;
|
||||
#ifdef RTCD_C
|
||||
#include "vpx_ports/x86.h"
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
int flags = x86_simd_caps();
|
||||
|
||||
(void)flags;
|
||||
|
||||
EOF
|
||||
|
||||
set_function_pointers("c", @ALL_ARCHS);
|
||||
|
||||
print <<EOF;
|
||||
}
|
||||
#endif
|
||||
EOF
|
||||
common_bottom;
|
||||
}
|
||||
|
||||
sub arm() {
|
||||
determine_indirection("c", @ALL_ARCHS);
|
||||
|
||||
# Assign the helper variable for each enabled extension
|
||||
foreach my $opt (@ALL_ARCHS) {
|
||||
my $opt_uc = uc $opt;
|
||||
# Enable neon assembly based on HAVE_NEON logic instead of adding new
|
||||
# HAVE_NEON_ASM logic
|
||||
if ($opt eq 'neon_asm') { $opt_uc = 'NEON' }
|
||||
eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
|
||||
}
|
||||
|
||||
common_top;
|
||||
print <<EOF;
|
||||
#include "vpx_config.h"
|
||||
|
||||
#ifdef RTCD_C
|
||||
#include "vpx_ports/arm.h"
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
int flags = arm_cpu_caps();
|
||||
|
||||
(void)flags;
|
||||
|
||||
EOF
|
||||
|
||||
set_function_pointers("c", @ALL_ARCHS);
|
||||
|
||||
print <<EOF;
|
||||
}
|
||||
#endif
|
||||
EOF
|
||||
common_bottom;
|
||||
}
|
||||
|
||||
sub mips() {
|
||||
determine_indirection("c", @ALL_ARCHS);
|
||||
common_top;
|
||||
|
||||
print <<EOF;
|
||||
#include "vpx_config.h"
|
||||
|
||||
#ifdef RTCD_C
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
EOF
|
||||
|
||||
set_function_pointers("c", @ALL_ARCHS);
|
||||
|
||||
print <<EOF;
|
||||
#if HAVE_DSPR2
|
||||
void vpx_dsputil_static_init();
|
||||
#if CONFIG_VP8
|
||||
void dsputil_static_init();
|
||||
#endif
|
||||
|
||||
vpx_dsputil_static_init();
|
||||
#if CONFIG_VP8
|
||||
dsputil_static_init();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
print <<EOF;
|
||||
#include "vpx_config.h"
|
||||
|
||||
#ifdef RTCD_C
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
EOF
|
||||
|
||||
set_function_pointers "c";
|
||||
|
||||
print <<EOF;
|
||||
}
|
||||
#endif
|
||||
EOF
|
||||
common_bottom;
|
||||
}
|
||||
|
||||
#
|
||||
# Main Driver
|
||||
#
|
||||
|
||||
&require("c");
|
||||
if ($opts{arch} eq 'x86') {
|
||||
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2 avx512/);
|
||||
x86;
|
||||
} elsif ($opts{arch} eq 'x86_64') {
|
||||
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2 avx512/);
|
||||
@REQUIRES = filter(keys %required ? keys %required : qw/mmx sse sse2/);
|
||||
&require(@REQUIRES);
|
||||
x86;
|
||||
} elsif ($opts{arch} eq 'mips32' || $opts{arch} eq 'mips64') {
|
||||
@ALL_ARCHS = filter("$opts{arch}");
|
||||
open CONFIG_FILE, $opts{config} or
|
||||
die "Error opening config file '$opts{config}': $!\n";
|
||||
while (<CONFIG_FILE>) {
|
||||
if (/HAVE_DSPR2=yes/) {
|
||||
@ALL_ARCHS = filter("$opts{arch}", qw/dspr2/);
|
||||
last;
|
||||
}
|
||||
if (/HAVE_MSA=yes/) {
|
||||
@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} =~ /armv7\w?/) {
|
||||
@ALL_ARCHS = filter(qw/neon_asm neon/);
|
||||
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;
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
rtcd -
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: rtcd.pl [options] FILE
|
||||
|
||||
See 'perldoc rtcd.pl' for more details.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Reads the Run Time CPU Detections definitions from FILE and generates a
|
||||
C header file on stdout.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
Options:
|
||||
--arch=ARCH Architecture to generate defs for (required)
|
||||
--disable-EXT Disable support for EXT extensions
|
||||
--require-EXT Require support for EXT extensions
|
||||
--sym=SYMBOL Unique symbol to use for RTCD initialization function
|
||||
--config=FILE File with CONFIG_FOO=yes lines to parse
|
||||
363
build/make/rtcd.sh
Executable file
363
build/make/rtcd.sh
Executable file
@@ -0,0 +1,363 @@
|
||||
#!/bin/sh
|
||||
self=$0
|
||||
|
||||
usage() {
|
||||
cat <<EOF >&2
|
||||
Usage: $self [options] FILE
|
||||
|
||||
Reads the Run Time CPU Detections definitions from FILE and generates a
|
||||
C header file on stdout.
|
||||
|
||||
Options:
|
||||
--arch=ARCH Architecture to generate defs for (required)
|
||||
--disable-EXT Disable support for EXT extensions
|
||||
--require-EXT Require support for EXT extensions
|
||||
--sym=SYMBOL Unique symbol to use for RTCD initialization function
|
||||
--config=FILE File with CONFIG_FOO=yes lines to parse
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
die_argument_required() {
|
||||
die "Option $opt requires argument"
|
||||
}
|
||||
|
||||
for opt; do
|
||||
optval="${opt#*=}"
|
||||
case "$opt" in
|
||||
--arch) die_argument_required;;
|
||||
--arch=*) arch=${optval};;
|
||||
--disable-*) eval "disable_${opt#--disable-}=true";;
|
||||
--require-*) REQUIRES="${REQUIRES}${opt#--require-} ";;
|
||||
--sym) die_argument_required;;
|
||||
--sym=*) symbol=${optval};;
|
||||
--config=*) config_file=${optval};;
|
||||
-h|--help)
|
||||
usage
|
||||
;;
|
||||
-*)
|
||||
die "Unrecognized option: ${opt%%=*}"
|
||||
;;
|
||||
*)
|
||||
defs_file="$defs_file $opt"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
for f in $defs_file; do [ -f "$f" ] || usage; done
|
||||
[ -n "$arch" ] || usage
|
||||
|
||||
# Import the configuration
|
||||
[ -f "$config_file" ] && eval $(grep CONFIG_ "$config_file")
|
||||
|
||||
#
|
||||
# Routines for the RTCD DSL to call
|
||||
#
|
||||
prototype() {
|
||||
rtyp=""
|
||||
case "$1" in
|
||||
unsigned) rtyp="$1 "; shift;;
|
||||
esac
|
||||
rtyp="${rtyp}$1"
|
||||
fn="$2"
|
||||
args="$3"
|
||||
|
||||
eval "${2}_rtyp='$rtyp'"
|
||||
eval "${2}_args='$3'"
|
||||
ALL_FUNCS="$ALL_FUNCS $fn"
|
||||
specialize $fn c
|
||||
}
|
||||
|
||||
specialize() {
|
||||
fn="$1"
|
||||
shift
|
||||
for opt in "$@"; do
|
||||
eval "${fn}_${opt}=${fn}_${opt}"
|
||||
done
|
||||
}
|
||||
|
||||
require() {
|
||||
for fn in $ALL_FUNCS; do
|
||||
for opt in "$@"; do
|
||||
ofn=$(eval "echo \$${fn}_${opt}")
|
||||
[ -z "$ofn" ] && continue
|
||||
|
||||
# if we already have a default, then we can disable it, as we know
|
||||
# we can do better.
|
||||
best=$(eval "echo \$${fn}_default")
|
||||
best_ofn=$(eval "echo \$${best}")
|
||||
[ -n "$best" ] && [ "$best_ofn" != "$ofn" ] && eval "${best}_link=false"
|
||||
eval "${fn}_default=${fn}_${opt}"
|
||||
eval "${fn}_${opt}_link=true"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
forward_decls() {
|
||||
ALL_FORWARD_DECLS="$ALL_FORWARD_DECLS $1"
|
||||
}
|
||||
|
||||
#
|
||||
# Include the user's directives
|
||||
#
|
||||
for f in $defs_file; do
|
||||
. $f
|
||||
done
|
||||
|
||||
#
|
||||
# Process the directives according to the command line
|
||||
#
|
||||
process_forward_decls() {
|
||||
for fn in $ALL_FORWARD_DECLS; do
|
||||
eval $fn
|
||||
done
|
||||
}
|
||||
|
||||
determine_indirection() {
|
||||
[ "$CONFIG_RUNTIME_CPU_DETECT" = "yes" ] || require $ALL_ARCHS
|
||||
for fn in $ALL_FUNCS; do
|
||||
n=""
|
||||
rtyp="$(eval "echo \$${fn}_rtyp")"
|
||||
args="$(eval "echo \"\$${fn}_args\"")"
|
||||
dfn="$(eval "echo \$${fn}_default")"
|
||||
dfn=$(eval "echo \$${dfn}")
|
||||
for opt in "$@"; do
|
||||
ofn=$(eval "echo \$${fn}_${opt}")
|
||||
[ -z "$ofn" ] && continue
|
||||
link=$(eval "echo \$${fn}_${opt}_link")
|
||||
[ "$link" = "false" ] && continue
|
||||
n="${n}x"
|
||||
done
|
||||
if [ "$n" = "x" ]; then
|
||||
eval "${fn}_indirect=false"
|
||||
else
|
||||
eval "${fn}_indirect=true"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
declare_function_pointers() {
|
||||
for fn in $ALL_FUNCS; do
|
||||
rtyp="$(eval "echo \$${fn}_rtyp")"
|
||||
args="$(eval "echo \"\$${fn}_args\"")"
|
||||
dfn="$(eval "echo \$${fn}_default")"
|
||||
dfn=$(eval "echo \$${dfn}")
|
||||
for opt in "$@"; do
|
||||
ofn=$(eval "echo \$${fn}_${opt}")
|
||||
[ -z "$ofn" ] && continue
|
||||
echo "$rtyp ${ofn}($args);"
|
||||
done
|
||||
if [ "$(eval "echo \$${fn}_indirect")" = "false" ]; then
|
||||
echo "#define ${fn} ${dfn}"
|
||||
else
|
||||
echo "RTCD_EXTERN $rtyp (*${fn})($args);"
|
||||
fi
|
||||
echo
|
||||
done
|
||||
}
|
||||
|
||||
set_function_pointers() {
|
||||
for fn in $ALL_FUNCS; do
|
||||
n=""
|
||||
rtyp="$(eval "echo \$${fn}_rtyp")"
|
||||
args="$(eval "echo \"\$${fn}_args\"")"
|
||||
dfn="$(eval "echo \$${fn}_default")"
|
||||
dfn=$(eval "echo \$${dfn}")
|
||||
if $(eval "echo \$${fn}_indirect"); then
|
||||
echo " $fn = $dfn;"
|
||||
for opt in "$@"; do
|
||||
ofn=$(eval "echo \$${fn}_${opt}")
|
||||
[ -z "$ofn" ] && continue
|
||||
[ "$ofn" = "$dfn" ] && continue;
|
||||
link=$(eval "echo \$${fn}_${opt}_link")
|
||||
[ "$link" = "false" ] && continue
|
||||
cond="$(eval "echo \$have_${opt}")"
|
||||
echo " if (${cond}) $fn = $ofn;"
|
||||
done
|
||||
fi
|
||||
echo
|
||||
done
|
||||
}
|
||||
|
||||
filter() {
|
||||
filtered=""
|
||||
for opt in "$@"; do
|
||||
[ -z $(eval "echo \$disable_${opt}") ] && filtered="$filtered $opt"
|
||||
done
|
||||
echo $filtered
|
||||
}
|
||||
|
||||
#
|
||||
# Helper functions for generating the arch specific RTCD files
|
||||
#
|
||||
common_top() {
|
||||
outfile_basename=$(basename ${symbol:-rtcd})
|
||||
include_guard=$(echo $outfile_basename | tr '[a-z]' '[A-Z]' | \
|
||||
tr -c '[A-Z0-9]' _)H_
|
||||
cat <<EOF
|
||||
#ifndef ${include_guard}
|
||||
#define ${include_guard}
|
||||
|
||||
#ifdef RTCD_C
|
||||
#define RTCD_EXTERN
|
||||
#else
|
||||
#define RTCD_EXTERN extern
|
||||
#endif
|
||||
|
||||
$(process_forward_decls)
|
||||
|
||||
$(declare_function_pointers c $ALL_ARCHS)
|
||||
|
||||
void ${symbol:-rtcd}(void);
|
||||
EOF
|
||||
}
|
||||
|
||||
common_bottom() {
|
||||
cat <<EOF
|
||||
#endif
|
||||
EOF
|
||||
}
|
||||
|
||||
x86() {
|
||||
determine_indirection c $ALL_ARCHS
|
||||
|
||||
# Assign the helper variable for each enabled extension
|
||||
for opt in $ALL_ARCHS; do
|
||||
uc=$(echo $opt | tr '[a-z]' '[A-Z]')
|
||||
eval "have_${opt}=\"flags & HAS_${uc}\""
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
$(common_top)
|
||||
|
||||
#ifdef RTCD_C
|
||||
#include "vpx_ports/x86.h"
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
int flags = x86_simd_caps();
|
||||
|
||||
(void)flags;
|
||||
|
||||
$(set_function_pointers c $ALL_ARCHS)
|
||||
}
|
||||
#endif
|
||||
$(common_bottom)
|
||||
EOF
|
||||
}
|
||||
|
||||
arm() {
|
||||
determine_indirection c $ALL_ARCHS
|
||||
|
||||
# Assign the helper variable for each enabled extension
|
||||
for opt in $ALL_ARCHS; do
|
||||
uc=$(echo $opt | tr '[a-z]' '[A-Z]')
|
||||
eval "have_${opt}=\"flags & HAS_${uc}\""
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
$(common_top)
|
||||
#include "vpx_config.h"
|
||||
|
||||
#ifdef RTCD_C
|
||||
#include "vpx_ports/arm.h"
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
int flags = arm_cpu_caps();
|
||||
|
||||
(void)flags;
|
||||
|
||||
$(set_function_pointers c $ALL_ARCHS)
|
||||
}
|
||||
#endif
|
||||
$(common_bottom)
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
mips() {
|
||||
determine_indirection c $ALL_ARCHS
|
||||
cat <<EOF
|
||||
$(common_top)
|
||||
#include "vpx_config.h"
|
||||
|
||||
#ifdef RTCD_C
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
$(set_function_pointers c $ALL_ARCHS)
|
||||
#if HAVE_DSPR2
|
||||
#if CONFIG_VP8
|
||||
void dsputil_static_init();
|
||||
dsputil_static_init();
|
||||
#endif
|
||||
#if CONFIG_VP9
|
||||
void vp9_dsputil_static_init();
|
||||
vp9_dsputil_static_init();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
$(common_bottom)
|
||||
EOF
|
||||
}
|
||||
|
||||
unoptimized() {
|
||||
determine_indirection c
|
||||
cat <<EOF
|
||||
$(common_top)
|
||||
#include "vpx_config.h"
|
||||
|
||||
#ifdef RTCD_C
|
||||
static void setup_rtcd_internal(void)
|
||||
{
|
||||
$(set_function_pointers c)
|
||||
}
|
||||
#endif
|
||||
$(common_bottom)
|
||||
EOF
|
||||
|
||||
}
|
||||
#
|
||||
# Main Driver
|
||||
#
|
||||
require c
|
||||
case $arch in
|
||||
x86)
|
||||
ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1 avx avx2)
|
||||
x86
|
||||
;;
|
||||
x86_64)
|
||||
ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1 avx avx2)
|
||||
REQUIRES=${REQUIRES:-mmx sse sse2}
|
||||
require $(filter $REQUIRES)
|
||||
x86
|
||||
;;
|
||||
mips32)
|
||||
ALL_ARCHS=$(filter mips32)
|
||||
dspr2=$([ -f "$config_file" ] && eval echo $(grep HAVE_DSPR2 "$config_file"))
|
||||
HAVE_DSPR2="${dspr2#*=}"
|
||||
if [ "$HAVE_DSPR2" = "yes" ]; then
|
||||
ALL_ARCHS=$(filter mips32 dspr2)
|
||||
fi
|
||||
mips
|
||||
;;
|
||||
armv5te)
|
||||
ALL_ARCHS=$(filter edsp)
|
||||
arm
|
||||
;;
|
||||
armv6)
|
||||
ALL_ARCHS=$(filter edsp media)
|
||||
arm
|
||||
;;
|
||||
armv7)
|
||||
ALL_ARCHS=$(filter edsp media neon)
|
||||
arm
|
||||
;;
|
||||
*)
|
||||
unoptimized
|
||||
;;
|
||||
esac
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env perl
|
||||
#!/usr/bin/perl
|
||||
##
|
||||
## Copyright (c) 2013 The WebM project authors. All Rights Reserved.
|
||||
##
|
||||
@@ -51,7 +51,7 @@ sub FixThumbInstructions($$)
|
||||
|
||||
# Convert register post indexing to a separate add instruction.
|
||||
# This converts "ldrneb r9, [r0], r2" into "ldrneb r9, [r0]",
|
||||
# "addne r0, r0, r2".
|
||||
# "add 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
|
||||
|
||||
@@ -24,10 +24,9 @@ out_file=${2}
|
||||
id=${3:-VERSION_STRING}
|
||||
|
||||
git_version_id=""
|
||||
if [ -e "${source_path}/.git" ]; then
|
||||
if [ -d ${source_path}/.git ]; then
|
||||
# Source Path is a git working copy. Check for local modifications.
|
||||
# Note that git submodules may have a file as .git, not a directory.
|
||||
export GIT_DIR="${source_path}/.git"
|
||||
export GIT_DIR=${source_path}/.git
|
||||
git_version_id=`git describe --match=v[0-9]* 2>/dev/null`
|
||||
fi
|
||||
|
||||
@@ -60,7 +59,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
|
||||
|
||||
12
build/x86-msvs/obj_int_extract.bat
Normal file
12
build/x86-msvs/obj_int_extract.bat
Normal file
@@ -0,0 +1,12 @@
|
||||
REM Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||
REM
|
||||
REM Use of this source code is governed by a BSD-style license
|
||||
REM that can be found in the LICENSE file in the root of the source
|
||||
REM tree. An additional intellectual property rights grant can be found
|
||||
REM in the file PATENTS. All contributing project authors may
|
||||
REM be found in the AUTHORS file in the root of the source tree.
|
||||
echo on
|
||||
|
||||
cl /I "./" /I "%1" /nologo /c "%1/vp8/encoder/vp8_asm_enc_offsets.c"
|
||||
obj_int_extract.exe rvds "vp8_asm_enc_offsets.obj" > "vp8_asm_enc_offsets.asm"
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# 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
|
||||
380
configure
vendored
380
configure
vendored
@@ -22,26 +22,21 @@ 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
|
||||
${toggle_encode_perf_tests} build encoder perf tests with unit tests
|
||||
--cpu=CPU tune for the specified CPU (ARM: cortex-a8, X86: sse3)
|
||||
--libc=PATH path to alternate libc
|
||||
--size-limit=WxH max size to allow in the decoder
|
||||
--as={yasm|nasm|auto} use specified assembler [auto, yasm preferred]
|
||||
--sdk-path=PATH path to root of sdk (android builds only)
|
||||
${toggle_fast_unaligned} don't use unaligned accesses, even when
|
||||
supported by hardware [auto]
|
||||
${toggle_codec_srcs} in/exclude codec library source code
|
||||
${toggle_debug_libs} in/exclude debug version of libraries
|
||||
${toggle_static_msvcrt} use static MSVCRT (VS builds only)
|
||||
${toggle_vp9_highbitdepth} use VP9 high bit depth (10/12) profiles
|
||||
${toggle_better_hw_compatibility}
|
||||
enable encoder to produce streams with better
|
||||
hardware decoder compatibility
|
||||
${toggle_vp8} VP8 codec support
|
||||
${toggle_vp9} VP9 codec support
|
||||
${toggle_internal_stats} output of encoder internal stats for debug, if supported (encoders)
|
||||
${toggle_mem_tracker} track memory usage
|
||||
${toggle_postproc} postprocessing
|
||||
${toggle_vp9_postproc} vp9 specific postprocessing
|
||||
${toggle_multithread} multithreaded encoding and decoding
|
||||
@@ -49,9 +44,6 @@ Advanced options:
|
||||
${toggle_realtime_only} enable this option while building for real-time encoding
|
||||
${toggle_onthefly_bitpacking} enable on-the-fly bitpacking in real-time encoding
|
||||
${toggle_error_concealment} enable this option to get a decoder which is able to conceal losses
|
||||
${toggle_coefficient_range_checking}
|
||||
enable decoder to check if intermediate
|
||||
transform coefficients are in valid range
|
||||
${toggle_runtime_cpu_detect} runtime cpu detection
|
||||
${toggle_shared} shared library support
|
||||
${toggle_static} static library support
|
||||
@@ -59,10 +51,6 @@ Advanced options:
|
||||
${toggle_postproc_visualizer} macro block / block level visualizers
|
||||
${toggle_multi_res_encoding} enable multiple-resolution encoding
|
||||
${toggle_temporal_denoising} enable temporal denoising and disable the spatial denoiser
|
||||
${toggle_vp9_temporal_denoising}
|
||||
enable vp9 temporal denoising
|
||||
${toggle_webm_io} enable input from and output to WebM container
|
||||
${toggle_libyuv} enable libyuv
|
||||
|
||||
Codecs:
|
||||
Codecs can be selectively enabled or disabled individually, or by family:
|
||||
@@ -75,10 +63,10 @@ Codecs:
|
||||
EOF
|
||||
#restore editor state '
|
||||
|
||||
family="";
|
||||
last_family="";
|
||||
c="";
|
||||
str="";
|
||||
local family;
|
||||
local last_family;
|
||||
local c;
|
||||
local str;
|
||||
for c in ${CODECS}; do
|
||||
family=${c%_*}
|
||||
if [ "${family}" != "${last_family}" ]; then
|
||||
@@ -98,9 +86,14 @@ 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} arm64-darwin-gcc"
|
||||
all_platforms="${all_platforms} arm64-linux-gcc"
|
||||
all_platforms="${all_platforms} armv5te-android-gcc"
|
||||
all_platforms="${all_platforms} armv5te-linux-rvct"
|
||||
all_platforms="${all_platforms} armv5te-linux-gcc"
|
||||
all_platforms="${all_platforms} armv5te-none-rvct"
|
||||
all_platforms="${all_platforms} armv6-darwin-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} 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
|
||||
@@ -108,14 +101,13 @@ 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-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} ppc32-darwin8-gcc"
|
||||
all_platforms="${all_platforms} ppc32-darwin9-gcc"
|
||||
all_platforms="${all_platforms} ppc32-linux-gcc"
|
||||
all_platforms="${all_platforms} ppc64-darwin8-gcc"
|
||||
all_platforms="${all_platforms} ppc64-darwin9-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"
|
||||
@@ -126,65 +118,48 @@ all_platforms="${all_platforms} x86-darwin10-gcc"
|
||||
all_platforms="${all_platforms} x86-darwin11-gcc"
|
||||
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-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"
|
||||
all_platforms="${all_platforms} x86_64-darwin11-gcc"
|
||||
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-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} universal-darwin8-gcc"
|
||||
all_platforms="${all_platforms} universal-darwin9-gcc"
|
||||
all_platforms="${all_platforms} universal-darwin10-gcc"
|
||||
all_platforms="${all_platforms} universal-darwin11-gcc"
|
||||
all_platforms="${all_platforms} universal-darwin12-gcc"
|
||||
all_platforms="${all_platforms} universal-darwin13-gcc"
|
||||
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}
|
||||
[ -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
|
||||
die "source directory already configured; run 'make distclean' there first"
|
||||
fi
|
||||
fi
|
||||
|
||||
# check installed doxygen version
|
||||
doxy_version=$(doxygen --version 2>/dev/null)
|
||||
doxy_major=${doxy_version%%.*}
|
||||
@@ -198,44 +173,63 @@ if [ ${doxy_major:-0} -ge 1 ]; then
|
||||
[ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable_feature doxygen
|
||||
fi
|
||||
|
||||
# disable codecs when their source directory does not exist
|
||||
[ -d "${source_path}/vp8" ] || disable_codec vp8
|
||||
[ -d "${source_path}/vp9" ] || disable_codec vp9
|
||||
|
||||
# install everything except the sources, by default. sources will have
|
||||
# to be enabled when doing dist builds, since that's no longer a common
|
||||
# case.
|
||||
enabled doxygen && enable_feature install_docs
|
||||
enabled doxygen && php -v >/dev/null 2>&1 && enable_feature install_docs
|
||||
enable_feature install_bins
|
||||
enable_feature install_libs
|
||||
|
||||
enable_feature static
|
||||
enable_feature optimizations
|
||||
enable_feature dependency_tracking
|
||||
enable_feature fast_unaligned #allow unaligned accesses, if supported by hw
|
||||
enable_feature spatial_resampling
|
||||
enable_feature multithread
|
||||
enable_feature os_support
|
||||
enable_feature temporal_denoising
|
||||
|
||||
CODECS="
|
||||
vp8_encoder
|
||||
vp8_decoder
|
||||
vp9_encoder
|
||||
vp9_decoder
|
||||
"
|
||||
CODEC_FAMILIES="
|
||||
vp8
|
||||
vp9
|
||||
"
|
||||
[ -d ${source_path}/../include ] && enable_feature alt_tree_layout
|
||||
for d in vp8 vp9; do
|
||||
[ -d ${source_path}/${d} ] && disable_feature alt_tree_layout;
|
||||
done
|
||||
|
||||
if ! enabled alt_tree_layout; then
|
||||
# development environment
|
||||
[ -d ${source_path}/vp8 ] && CODECS="${CODECS} vp8_encoder vp8_decoder"
|
||||
[ -d ${source_path}/vp9 ] && CODECS="${CODECS} vp9_encoder vp9_decoder"
|
||||
else
|
||||
# customer environment
|
||||
[ -f ${source_path}/../include/vpx/vp8cx.h ] && CODECS="${CODECS} vp8_encoder"
|
||||
[ -f ${source_path}/../include/vpx/vp8dx.h ] && CODECS="${CODECS} vp8_decoder"
|
||||
[ -f ${source_path}/../include/vpx/vp9cx.h ] && CODECS="${CODECS} vp9_encoder"
|
||||
[ -f ${source_path}/../include/vpx/vp9dx.h ] && CODECS="${CODECS} vp9_decoder"
|
||||
[ -f ${source_path}/../include/vpx/vp8cx.h ] || disable_feature vp8_encoder
|
||||
[ -f ${source_path}/../include/vpx/vp8dx.h ] || disable_feature vp8_decoder
|
||||
[ -f ${source_path}/../include/vpx/vp9cx.h ] || disable_feature vp9_encoder
|
||||
[ -f ${source_path}/../include/vpx/vp9dx.h ] || disable_feature vp9_decoder
|
||||
|
||||
[ -f ${source_path}/../lib/*/*mt.lib ] && soft_enable static_msvcrt
|
||||
fi
|
||||
|
||||
CODECS="$(echo ${CODECS} | tr ' ' '\n')"
|
||||
CODEC_FAMILIES="$(for c in ${CODECS}; do echo ${c%_*}; done | sort | uniq)"
|
||||
|
||||
ARCH_LIST="
|
||||
arm
|
||||
mips
|
||||
x86
|
||||
x86_64
|
||||
ppc
|
||||
ppc32
|
||||
ppc64
|
||||
"
|
||||
ARCH_EXT_LIST_X86="
|
||||
ARCH_EXT_LIST="
|
||||
edsp
|
||||
media
|
||||
neon
|
||||
|
||||
mips32
|
||||
dspr2
|
||||
|
||||
mmx
|
||||
sse
|
||||
sse2
|
||||
@@ -244,46 +238,30 @@ ARCH_EXT_LIST_X86="
|
||||
sse4_1
|
||||
avx
|
||||
avx2
|
||||
avx512
|
||||
"
|
||||
|
||||
ARCH_EXT_LIST_LOONGSON="
|
||||
mmi
|
||||
"
|
||||
|
||||
ARCH_EXT_LIST="
|
||||
neon
|
||||
neon_asm
|
||||
|
||||
mips32
|
||||
dspr2
|
||||
msa
|
||||
mips64
|
||||
|
||||
${ARCH_EXT_LIST_X86}
|
||||
|
||||
vsx
|
||||
|
||||
${ARCH_EXT_LIST_LOONGSON}
|
||||
altivec
|
||||
"
|
||||
HAVE_LIST="
|
||||
${ARCH_EXT_LIST}
|
||||
vpx_ports
|
||||
stdint_h
|
||||
alt_tree_layout
|
||||
pthread_h
|
||||
sys_mman_h
|
||||
unistd_h
|
||||
"
|
||||
EXPERIMENT_LIST="
|
||||
spatial_svc
|
||||
fp_mb_stats
|
||||
emulate_hardware
|
||||
multiple_arf
|
||||
non420
|
||||
alpha
|
||||
"
|
||||
CONFIG_LIST="
|
||||
dependency_tracking
|
||||
external_build
|
||||
install_docs
|
||||
install_bins
|
||||
install_libs
|
||||
install_srcs
|
||||
use_x86inc
|
||||
debug
|
||||
gprof
|
||||
gcov
|
||||
@@ -295,6 +273,10 @@ CONFIG_LIST="
|
||||
|
||||
codec_srcs
|
||||
debug_libs
|
||||
fast_unaligned
|
||||
mem_manager
|
||||
mem_tracker
|
||||
mem_checks
|
||||
|
||||
dequant_tokens
|
||||
dc_recon
|
||||
@@ -318,23 +300,14 @@ CONFIG_LIST="
|
||||
postproc_visualizer
|
||||
os_support
|
||||
unit_tests
|
||||
webm_io
|
||||
libyuv
|
||||
decode_perf_tests
|
||||
encode_perf_tests
|
||||
multi_res_encoding
|
||||
temporal_denoising
|
||||
vp9_temporal_denoising
|
||||
coefficient_range_checking
|
||||
vp9_highbitdepth
|
||||
better_hw_compatibility
|
||||
experimental
|
||||
size_limit
|
||||
always_adjust_bpm
|
||||
decrypt
|
||||
${EXPERIMENT_LIST}
|
||||
"
|
||||
CMDLINE_SELECT="
|
||||
dependency_tracking
|
||||
external_build
|
||||
extra_warnings
|
||||
werror
|
||||
@@ -346,6 +319,7 @@ CMDLINE_SELECT="
|
||||
gprof
|
||||
gcov
|
||||
pic
|
||||
use_x86inc
|
||||
optimizations
|
||||
ccache
|
||||
runtime_cpu_detect
|
||||
@@ -353,11 +327,10 @@ CMDLINE_SELECT="
|
||||
|
||||
libs
|
||||
examples
|
||||
tools
|
||||
docs
|
||||
libc
|
||||
as
|
||||
size_limit
|
||||
fast_unaligned
|
||||
codec_srcs
|
||||
debug_libs
|
||||
|
||||
@@ -370,6 +343,7 @@ CMDLINE_SELECT="
|
||||
${CODECS}
|
||||
${CODEC_FAMILIES}
|
||||
static_msvcrt
|
||||
mem_tracker
|
||||
spatial_resampling
|
||||
realtime_only
|
||||
onthefly_bitpacking
|
||||
@@ -379,37 +353,26 @@ CMDLINE_SELECT="
|
||||
small
|
||||
postproc_visualizer
|
||||
unit_tests
|
||||
webm_io
|
||||
libyuv
|
||||
decode_perf_tests
|
||||
encode_perf_tests
|
||||
multi_res_encoding
|
||||
temporal_denoising
|
||||
vp9_temporal_denoising
|
||||
coefficient_range_checking
|
||||
better_hw_compatibility
|
||||
vp9_highbitdepth
|
||||
experimental
|
||||
always_adjust_bpm
|
||||
decrypt
|
||||
"
|
||||
|
||||
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
|
||||
@@ -421,7 +384,15 @@ process_cmdline() {
|
||||
}
|
||||
|
||||
post_process_cmdline() {
|
||||
c=""
|
||||
local 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
|
||||
@@ -440,12 +411,28 @@ post_process_cmdline() {
|
||||
|
||||
process_targets() {
|
||||
enabled child || write_common_config_banner
|
||||
write_common_target_config_h ${BUILD_PFX}vpx_config.h
|
||||
enabled universal || write_common_target_config_h ${BUILD_PFX}vpx_config.h
|
||||
|
||||
# TODO: add host tools target (obj_int_extract, etc)
|
||||
|
||||
# For fat binaries, call configure recursively to configure for each
|
||||
# binary architecture to be included.
|
||||
if enabled universal; then
|
||||
# Call configure (ourselves) for each subarchitecture
|
||||
for arch in $fat_bin_archs; do
|
||||
BUILD_PFX=${arch}/ toolchain=${arch} $self --child $cmdline_args || exit $?
|
||||
done
|
||||
fi
|
||||
|
||||
# The write_common_config (config.mk) logic is deferred until after the
|
||||
# recursive calls to configure complete, because we want our universal
|
||||
# targets to be executed last.
|
||||
write_common_config_targets
|
||||
enabled universal && echo "FAT_ARCHS=${fat_bin_archs}" >> config.mk
|
||||
|
||||
# Calculate the default distribution name, based on the enabled features
|
||||
cf=""
|
||||
DIST_DIR=vpx
|
||||
local cf
|
||||
local DIST_DIR=vpx
|
||||
for cf in $CODEC_FAMILIES; do
|
||||
if enabled ${cf}_encoder && enabled ${cf}_decoder; then
|
||||
DIST_DIR="${DIST_DIR}-${cf}"
|
||||
@@ -467,7 +454,7 @@ process_targets() {
|
||||
;;
|
||||
esac
|
||||
if [ -f "${source_path}/build/make/version.sh" ]; then
|
||||
ver=`"$source_path/build/make/version.sh" --bare "$source_path"`
|
||||
local ver=`"$source_path/build/make/version.sh" --bare $source_path`
|
||||
DIST_DIR="${DIST_DIR}-${ver}"
|
||||
VERSION_STRING=${ver}
|
||||
ver=${ver%%-*}
|
||||
@@ -500,8 +487,8 @@ EOF
|
||||
#
|
||||
# Write makefiles for all enabled targets
|
||||
#
|
||||
for tgt in libs examples tools docs solution; do
|
||||
tgt_fn="$tgt-$toolchain.mk"
|
||||
for tgt in libs examples docs solution; do
|
||||
local tgt_fn="$tgt-$toolchain.mk"
|
||||
|
||||
if enabled $tgt; then
|
||||
echo "Creating makefiles for ${toolchain} ${tgt}"
|
||||
@@ -517,18 +504,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; 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 for now"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if [ -z "$CC" ] || enabled external_build; then
|
||||
echo "Bypassing toolchain for environment detection."
|
||||
@@ -545,7 +527,7 @@ process_detect() {
|
||||
true;
|
||||
;;
|
||||
*)
|
||||
result=false
|
||||
local result=false
|
||||
for d in "$@"; do
|
||||
[ -f "${d##-I}/$header" ] && result=true && break
|
||||
done
|
||||
@@ -555,12 +537,16 @@ process_detect() {
|
||||
# Specialize windows and POSIX environments.
|
||||
case $toolchain in
|
||||
*-win*-*)
|
||||
# Don't check for any headers in Windows builds.
|
||||
false
|
||||
;;
|
||||
case $header-$toolchain in
|
||||
stdint*-gcc) true;;
|
||||
*) false;;
|
||||
esac && enable_feature $var
|
||||
;;
|
||||
*)
|
||||
case $header in
|
||||
stdint.h) true;;
|
||||
pthread.h) true;;
|
||||
sys/mman.h) true;;
|
||||
unistd.h) true;;
|
||||
*) false;;
|
||||
esac && enable_feature $var
|
||||
@@ -576,7 +562,9 @@ process_detect() {
|
||||
int main(void) {return 0;}
|
||||
EOF
|
||||
# check system headers
|
||||
check_header stdint.h
|
||||
check_header pthread.h
|
||||
check_header sys/mman.h
|
||||
check_header unistd.h # for sysconf(3) and friends.
|
||||
|
||||
check_header vpx/vpx_integer.h -I${source_path} && enable_feature vpx_ports
|
||||
@@ -585,35 +573,53 @@ EOF
|
||||
process_toolchain() {
|
||||
process_common_toolchain
|
||||
|
||||
# Handle universal binaries for this architecture
|
||||
case $toolchain in
|
||||
universal-darwin*)
|
||||
local darwin_ver=${tgt_os##darwin}
|
||||
|
||||
# Snow Leopard (10.6/darwin10) dropped support for PPC
|
||||
# Include PPC support for all prior versions
|
||||
if [ $darwin_ver -lt 10 ]; then
|
||||
fat_bin_archs="$fat_bin_archs ppc32-${tgt_os}-gcc"
|
||||
fi
|
||||
|
||||
# Tiger (10.4/darwin8) brought support for x86
|
||||
if [ $darwin_ver -ge 8 ]; then
|
||||
fat_bin_archs="$fat_bin_archs x86-${tgt_os}-${tgt_cc}"
|
||||
fi
|
||||
|
||||
# Leopard (10.5/darwin9) brought 64 bit support
|
||||
if [ $darwin_ver -ge 9 ]; then
|
||||
fat_bin_archs="$fat_bin_archs x86_64-${tgt_os}-${tgt_cc}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Enable some useful compiler flags
|
||||
if enabled gcc; then
|
||||
enabled werror && check_add_cflags -Werror
|
||||
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
|
||||
# -Wundef so add it explicitly to CFLAGS only.
|
||||
check_cflags -Wundef && add_cflags_only -Wundef
|
||||
if enabled mips || [ -z "${INLINE}" ]; then
|
||||
enabled extra_warnings || check_add_cflags -Wno-unused-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
|
||||
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
|
||||
enabled extra_warnings || check_add_cflags -Wno-unused-function
|
||||
fi
|
||||
|
||||
if enabled icc; then
|
||||
@@ -661,16 +667,23 @@ 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)
|
||||
VCPROJ_SFX=vcxproj
|
||||
gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh
|
||||
;;
|
||||
esac
|
||||
all_targets="${all_targets} solution"
|
||||
INLINE="__inline"
|
||||
INLINE="__forceinline"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Other toolchain specific defaults
|
||||
case $toolchain in x86*) soft_enable postproc;; esac
|
||||
case $toolchain in x86*|ppc*|universal*) soft_enable postproc;; esac
|
||||
|
||||
if enabled postproc_visualizer; then
|
||||
enabled postproc || die "postproc_visualizer requires postproc to be enabled"
|
||||
@@ -680,60 +693,28 @@ process_toolchain() {
|
||||
case "$toolchain" in
|
||||
*-vs*)
|
||||
soft_enable unit_tests
|
||||
soft_enable webm_io
|
||||
soft_enable libyuv
|
||||
;;
|
||||
*-android-*)
|
||||
soft_enable webm_io
|
||||
soft_enable libyuv
|
||||
# GTestLog must be modified to use Android logging utilities.
|
||||
;;
|
||||
*-darwin-*)
|
||||
# iOS/ARM builds do not work with gtest. This does not match
|
||||
# x86 targets.
|
||||
;;
|
||||
*-iphonesimulator-*)
|
||||
soft_enable webm_io
|
||||
soft_enable libyuv
|
||||
;;
|
||||
*-win*)
|
||||
# Some mingw toolchains don't have pthread available by default.
|
||||
# Treat these more like visual studio where threading in gtest
|
||||
# would be disabled for the same reason.
|
||||
check_cxx "$@" <<EOF && soft_enable unit_tests
|
||||
int z;
|
||||
EOF
|
||||
check_cxx "$@" <<EOF && soft_enable webm_io
|
||||
int z;
|
||||
EOF
|
||||
check_cxx "$@" <<EOF && soft_enable libyuv
|
||||
int z;
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
enabled pthread_h && check_cxx "$@" <<EOF && soft_enable unit_tests
|
||||
int z;
|
||||
EOF
|
||||
check_cxx "$@" <<EOF && soft_enable webm_io
|
||||
int z;
|
||||
EOF
|
||||
check_cxx "$@" <<EOF && soft_enable libyuv
|
||||
int z;
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
# libwebm needs to be linked with C++ standard library
|
||||
enabled webm_io && LD=${CXX}
|
||||
|
||||
# append any user defined extra cflags
|
||||
if [ -n "${extra_cflags}" ] ; then
|
||||
check_add_cflags ${extra_cflags} || \
|
||||
die "Requested extra CFLAGS '${extra_cflags}' not supported by compiler"
|
||||
fi
|
||||
if [ -n "${extra_cxxflags}" ]; then
|
||||
check_add_cxxflags ${extra_cxxflags} || \
|
||||
die "Requested extra CXXFLAGS '${extra_cxxflags}' not supported by compiler"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -744,7 +725,6 @@ CONFIGURE_ARGS="$@"
|
||||
process "$@"
|
||||
print_webm_license ${BUILD_PFX}vpx_config.c "/*" " */"
|
||||
cat <<EOF >> ${BUILD_PFX}vpx_config.c
|
||||
#include "vpx/vpx_codec.h"
|
||||
static const char* const cfg = "$CONFIGURE_ARGS";
|
||||
const char *vpx_codec_build_config(void) {return cfg;}
|
||||
EOF
|
||||
|
||||
10
docs.mk
10
docs.mk
@@ -23,10 +23,14 @@ CODEC_DOX := mainpage.dox \
|
||||
# Other doxy files sourced in Markdown
|
||||
TXT_DOX = $(call enabled,TXT_DOX)
|
||||
|
||||
EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc
|
||||
EXAMPLE_PATH += $(SRC_PATH_BARE)/examples
|
||||
%.dox: %.txt
|
||||
@echo " [DOXY] $@"
|
||||
@$(SRC_PATH_BARE)/examples/gen_example_doxy.php \
|
||||
$(@:.dox=) "$($@.DESC)" > $@ < $<
|
||||
|
||||
|
||||
EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc
|
||||
|
||||
doxyfile: $(if $(findstring examples, $(ALL_TARGETS)),examples.doxy)
|
||||
doxyfile: libs.doxy_template libs.doxy
|
||||
@echo " [CREATE] $@"
|
||||
@cat $^ > $@
|
||||
|
||||
191
example_xma.c
Normal file
191
example_xma.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/* This is a simple program showing how to initialize the decoder in XMA mode */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx_config.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#if CONFIG_VP9_DECODER
|
||||
#include "vpx/vp8dx.h"
|
||||
#endif
|
||||
|
||||
static char *exec_name;
|
||||
static int verbose = 0;
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
const vpx_codec_iface_t *iface;
|
||||
} ifaces[] = {
|
||||
#if CONFIG_VP9_DECODER
|
||||
{"vp9", &vpx_codec_vp8_dx_algo},
|
||||
#endif
|
||||
};
|
||||
|
||||
static void usage_exit(void) {
|
||||
int i;
|
||||
|
||||
printf("Usage: %s <options>\n\n"
|
||||
"Options:\n"
|
||||
"\t--codec <name>\tCodec to use (default=%s)\n"
|
||||
"\t-h <height>\tHeight of the simulated video frame, in pixels\n"
|
||||
"\t-w <width> \tWidth of the simulated video frame, in pixels\n"
|
||||
"\t-v \tVerbose mode (show individual segment sizes)\n"
|
||||
"\t--help \tShow this message\n"
|
||||
"\n"
|
||||
"Included decoders:\n"
|
||||
"\n",
|
||||
exec_name,
|
||||
ifaces[0].name);
|
||||
|
||||
for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
|
||||
printf(" %-6s - %s\n",
|
||||
ifaces[i].name,
|
||||
vpx_codec_iface_name(ifaces[i].iface));
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void usage_error(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
printf("\n");
|
||||
usage_exit();
|
||||
}
|
||||
|
||||
void my_mem_dtor(vpx_codec_mmap_t *mmap) {
|
||||
if (verbose)
|
||||
printf("freeing segment %d\n", mmap->id);
|
||||
|
||||
free(mmap->priv);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
vpx_codec_ctx_t decoder;
|
||||
vpx_codec_iface_t *iface = ifaces[0].iface;
|
||||
vpx_codec_iter_t iter;
|
||||
vpx_codec_dec_cfg_t cfg;
|
||||
vpx_codec_err_t res = VPX_CODEC_OK;
|
||||
unsigned int alloc_sz = 0;
|
||||
unsigned int w = 352;
|
||||
unsigned int h = 288;
|
||||
int i;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--codec")) {
|
||||
if (i + 1 < argc) {
|
||||
int j, k = -1;
|
||||
|
||||
i++;
|
||||
|
||||
for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
|
||||
if (!strcmp(ifaces[j].name, argv[i]))
|
||||
k = j;
|
||||
|
||||
if (k >= 0)
|
||||
iface = ifaces[k].iface;
|
||||
else
|
||||
usage_error("Error: Unrecognized argument (%s) to --codec\n",
|
||||
argv[i]);
|
||||
} else
|
||||
usage_error("Error: Option --codec requires argument.\n");
|
||||
} else if (!strcmp(argv[i], "-v"))
|
||||
verbose = 1;
|
||||
else if (!strcmp(argv[i], "-h"))
|
||||
if (i + 1 < argc) {
|
||||
h = atoi(argv[++i]);
|
||||
} else
|
||||
usage_error("Error: Option -h requires argument.\n");
|
||||
else if (!strcmp(argv[i], "-w"))
|
||||
if (i + 1 < argc) {
|
||||
w = atoi(argv[++i]);
|
||||
} else
|
||||
usage_error("Error: Option -w requires argument.\n");
|
||||
else if (!strcmp(argv[i], "--help"))
|
||||
usage_exit();
|
||||
else
|
||||
usage_error("Error: Unrecognized option %s\n\n", argv[i]);
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
printf("Using built-in defaults. For options, rerun with --help\n\n");
|
||||
|
||||
/* XMA mode is not supported on all decoders! */
|
||||
if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA)) {
|
||||
printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* The codec knows how much memory to allocate based on the size of the
|
||||
* encoded frames. This data can be parsed from the bitstream with
|
||||
* vpx_codec_peek_stream_info() if a bitstream is available. Otherwise,
|
||||
* a fixed size can be used that will be the upper limit on the frame
|
||||
* size the decoder can decode.
|
||||
*/
|
||||
cfg.w = w;
|
||||
cfg.h = h;
|
||||
|
||||
/* Initialize the decoder in XMA mode. */
|
||||
if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA)) {
|
||||
printf("Failed to initialize decoder in XMA mode: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Iterate through the list of memory maps, allocating them with the
|
||||
* requested alignment.
|
||||
*/
|
||||
iter = NULL;
|
||||
|
||||
do {
|
||||
vpx_codec_mmap_t mmap;
|
||||
unsigned int align;
|
||||
|
||||
res = vpx_codec_get_mem_map(&decoder, &mmap, &iter);
|
||||
align = mmap.align ? mmap.align - 1 : 0;
|
||||
|
||||
if (!res) {
|
||||
if (verbose)
|
||||
printf("Allocating segment %u, size %lu, align %u %s\n",
|
||||
mmap.id, mmap.sz, mmap.align,
|
||||
mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : "");
|
||||
|
||||
if (mmap.flags & VPX_CODEC_MEM_ZERO)
|
||||
mmap.priv = calloc(1, mmap.sz + align);
|
||||
else
|
||||
mmap.priv = malloc(mmap.sz + align);
|
||||
|
||||
mmap.base = (void *)((((uintptr_t)mmap.priv) + align) & ~(uintptr_t)align);
|
||||
mmap.dtor = my_mem_dtor;
|
||||
alloc_sz += mmap.sz + align;
|
||||
|
||||
if (vpx_codec_set_mem_map(&decoder, &mmap, 1)) {
|
||||
printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else if (res != VPX_CODEC_LIST_END) {
|
||||
printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} while (res != VPX_CODEC_LIST_END);
|
||||
|
||||
printf("%s\n %d bytes external memory required for %dx%d.\n",
|
||||
decoder.name, alloc_sz, cfg.w, cfg.h);
|
||||
vpx_codec_destroy(&decoder);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
}
|
||||
366
examples.mk
366
examples.mk
@@ -9,237 +9,112 @@
|
||||
##
|
||||
|
||||
LIBYUV_SRCS += third_party/libyuv/include/libyuv/basic_types.h \
|
||||
third_party/libyuv/include/libyuv/convert.h \
|
||||
third_party/libyuv/include/libyuv/convert_argb.h \
|
||||
third_party/libyuv/include/libyuv/convert_from.h \
|
||||
third_party/libyuv/include/libyuv/cpu_id.h \
|
||||
third_party/libyuv/include/libyuv/planar_functions.h \
|
||||
third_party/libyuv/include/libyuv/rotate.h \
|
||||
third_party/libyuv/include/libyuv/row.h \
|
||||
third_party/libyuv/include/libyuv/scale.h \
|
||||
third_party/libyuv/include/libyuv/scale_row.h \
|
||||
third_party/libyuv/source/cpu_id.cc \
|
||||
third_party/libyuv/source/planar_functions.cc \
|
||||
third_party/libyuv/source/row_any.cc \
|
||||
third_party/libyuv/source/row_common.cc \
|
||||
third_party/libyuv/source/row_gcc.cc \
|
||||
third_party/libyuv/source/row_mips.cc \
|
||||
third_party/libyuv/source/row_neon.cc \
|
||||
third_party/libyuv/source/row_neon64.cc \
|
||||
third_party/libyuv/source/row_win.cc \
|
||||
third_party/libyuv/source/scale.cc \
|
||||
third_party/libyuv/source/scale_any.cc \
|
||||
third_party/libyuv/source/scale_common.cc \
|
||||
third_party/libyuv/source/scale_gcc.cc \
|
||||
third_party/libyuv/source/scale_mips.cc \
|
||||
third_party/libyuv/source/scale_neon.cc \
|
||||
third_party/libyuv/source/scale_neon64.cc \
|
||||
third_party/libyuv/source/scale_win.cc \
|
||||
third_party/libyuv/source/row.h \
|
||||
third_party/libyuv/source/scale.c \
|
||||
third_party/libyuv/source/cpu_id.c
|
||||
|
||||
LIBWEBM_COMMON_SRCS += third_party/libwebm/common/hdr_util.cc \
|
||||
third_party/libwebm/common/hdr_util.h \
|
||||
third_party/libwebm/common/webmids.h
|
||||
|
||||
LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer/mkvmuxer.cc \
|
||||
third_party/libwebm/mkvmuxer/mkvmuxerutil.cc \
|
||||
third_party/libwebm/mkvmuxer/mkvwriter.cc \
|
||||
third_party/libwebm/mkvmuxer/mkvmuxer.h \
|
||||
third_party/libwebm/mkvmuxer/mkvmuxertypes.h \
|
||||
third_party/libwebm/mkvmuxer/mkvmuxerutil.h \
|
||||
third_party/libwebm/mkvparser/mkvparser.h \
|
||||
third_party/libwebm/mkvmuxer/mkvwriter.h
|
||||
|
||||
LIBWEBM_PARSER_SRCS = third_party/libwebm/mkvparser/mkvparser.cc \
|
||||
third_party/libwebm/mkvparser/mkvreader.cc \
|
||||
third_party/libwebm/mkvparser/mkvparser.h \
|
||||
third_party/libwebm/mkvparser/mkvreader.h
|
||||
|
||||
# Add compile flags and include path for libwebm sources.
|
||||
ifeq ($(CONFIG_WEBM_IO),yes)
|
||||
CXXFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
|
||||
INC_PATH-yes += $(SRC_PATH_BARE)/third_party/libwebm
|
||||
endif
|
||||
|
||||
|
||||
# List of examples to build. UTILS are tools meant for distribution
|
||||
# while EXAMPLES demonstrate specific portions of the API.
|
||||
# List of examples to build. UTILS are files that are taken from the source
|
||||
# tree directly, and GEN_EXAMPLES are files that are created from the
|
||||
# examples folder.
|
||||
UTILS-$(CONFIG_DECODERS) += vpxdec.c
|
||||
vpxdec.SRCS += md5_utils.c md5_utils.h
|
||||
vpxdec.SRCS += vpx_ports/mem_ops.h
|
||||
vpxdec.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
vpxdec.SRCS += vpx_ports/msvc.h
|
||||
vpxdec.SRCS += vpx_ports/vpx_timer.h
|
||||
vpxdec.SRCS += vpx/vpx_integer.h
|
||||
vpxdec.SRCS += args.c args.h
|
||||
vpxdec.SRCS += ivfdec.c ivfdec.h
|
||||
vpxdec.SRCS += tools_common.c tools_common.h
|
||||
vpxdec.SRCS += webmdec.c webmdec.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)
|
||||
vpxdec.SRCS += $(LIBWEBM_MUXER_SRCS)
|
||||
vpxdec.SRCS += $(LIBWEBM_PARSER_SRCS)
|
||||
vpxdec.SRCS += webmdec.cc webmdec.h
|
||||
endif
|
||||
vpxdec.SRCS += nestegg/halloc/halloc.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/align.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/halloc.c
|
||||
vpxdec.SRCS += nestegg/halloc/src/hlist.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/macros.h
|
||||
vpxdec.SRCS += nestegg/include/nestegg/nestegg.h
|
||||
vpxdec.SRCS += nestegg/src/nestegg.c
|
||||
vpxdec.SRCS += $(LIBYUV_SRCS)
|
||||
vpxdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
|
||||
vpxdec.DESCRIPTION = Full featured decoder
|
||||
UTILS-$(CONFIG_ENCODERS) += vpxenc.c
|
||||
vpxenc.SRCS += args.c args.h y4minput.c y4minput.h vpxenc.h
|
||||
vpxenc.SRCS += ivfdec.c ivfdec.h
|
||||
vpxenc.SRCS += ivfenc.c ivfenc.h
|
||||
vpxenc.SRCS += rate_hist.c rate_hist.h
|
||||
vpxenc.SRCS += tools_common.c tools_common.h
|
||||
vpxenc.SRCS += warnings.c warnings.h
|
||||
vpxenc.SRCS += webmenc.c webmenc.h
|
||||
vpxenc.SRCS += vpx_ports/mem_ops.h
|
||||
vpxenc.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
vpxenc.SRCS += vpx_ports/msvc.h
|
||||
vpxenc.SRCS += vpx_ports/vpx_timer.h
|
||||
vpxenc.SRCS += vpxstats.c vpxstats.h
|
||||
ifeq ($(CONFIG_LIBYUV),yes)
|
||||
vpxenc.SRCS += $(LIBYUV_SRCS)
|
||||
endif
|
||||
ifeq ($(CONFIG_WEBM_IO),yes)
|
||||
vpxenc.SRCS += $(LIBWEBM_COMMON_SRCS)
|
||||
vpxenc.SRCS += $(LIBWEBM_MUXER_SRCS)
|
||||
vpxenc.SRCS += $(LIBWEBM_PARSER_SRCS)
|
||||
vpxenc.SRCS += webmenc.cc webmenc.h
|
||||
endif
|
||||
vpxenc.SRCS += third_party/libmkv/EbmlIDs.h
|
||||
vpxenc.SRCS += third_party/libmkv/EbmlWriter.c
|
||||
vpxenc.SRCS += third_party/libmkv/EbmlWriter.h
|
||||
vpxenc.SRCS += $(LIBYUV_SRCS)
|
||||
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
|
||||
vpxenc.DESCRIPTION = Full featured 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
|
||||
UTILS-$(CONFIG_VP8_ENCODER) += vp8_scalable_patterns.c
|
||||
vp8_scalable_patterns.GUID = 0D6A210B-F482-4D6F-8570-4A9C01ACC88C
|
||||
vp8_scalable_patterns.DESCRIPTION = Temporal Scalability Encoder
|
||||
UTILS-$(CONFIG_VP9_ENCODER) += vp9_spatial_scalable_encoder.c
|
||||
vp9_spatial_scalable_encoder.SRCS += args.c args.h
|
||||
vp9_spatial_scalable_encoder.SRCS += ivfenc.c ivfenc.h
|
||||
vp9_spatial_scalable_encoder.SRCS += tools_common.c tools_common.h
|
||||
vp9_spatial_scalable_encoder.GUID = 4A38598D-627D-4505-9C7B-D4020C84100D
|
||||
vp9_spatial_scalable_encoder.DESCRIPTION = Spatial Scalable Encoder
|
||||
|
||||
ifneq ($(CONFIG_SHARED),yes)
|
||||
EXAMPLES-$(CONFIG_VP9_ENCODER) += resize_util.c
|
||||
endif
|
||||
# XMA example disabled for now, not used in VP8
|
||||
#UTILS-$(CONFIG_DECODERS) += example_xma.c
|
||||
#example_xma.GUID = A955FC4A-73F1-44F7-135E-30D84D32F022
|
||||
#example_xma.DESCRIPTION = External Memory Allocation mode usage
|
||||
|
||||
EXAMPLES-$(CONFIG_ENCODERS) += vpx_temporal_svc_encoder.c
|
||||
vpx_temporal_svc_encoder.SRCS += ivfenc.c ivfenc.h
|
||||
vpx_temporal_svc_encoder.SRCS += tools_common.c tools_common.h
|
||||
vpx_temporal_svc_encoder.SRCS += video_common.h
|
||||
vpx_temporal_svc_encoder.SRCS += video_writer.h video_writer.c
|
||||
vpx_temporal_svc_encoder.SRCS += vpx_ports/msvc.h
|
||||
vpx_temporal_svc_encoder.GUID = B18C08F2-A439-4502-A78E-849BE3D60947
|
||||
vpx_temporal_svc_encoder.DESCRIPTION = Temporal SVC Encoder
|
||||
EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
|
||||
simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
|
||||
simple_decoder.SRCS += ivfdec.h ivfdec.c
|
||||
simple_decoder.SRCS += tools_common.h tools_common.c
|
||||
simple_decoder.SRCS += video_common.h
|
||||
simple_decoder.SRCS += video_reader.h video_reader.c
|
||||
simple_decoder.SRCS += vpx_ports/mem_ops.h
|
||||
simple_decoder.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
simple_decoder.SRCS += vpx_ports/msvc.h
|
||||
simple_decoder.DESCRIPTION = Simplified decoder loop
|
||||
EXAMPLES-$(CONFIG_DECODERS) += postproc.c
|
||||
postproc.SRCS += ivfdec.h ivfdec.c
|
||||
postproc.SRCS += tools_common.h tools_common.c
|
||||
postproc.SRCS += video_common.h
|
||||
postproc.SRCS += video_reader.h video_reader.c
|
||||
postproc.SRCS += vpx_ports/mem_ops.h
|
||||
postproc.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
postproc.SRCS += vpx_ports/msvc.h
|
||||
postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
|
||||
postproc.DESCRIPTION = Decoder postprocessor control
|
||||
EXAMPLES-$(CONFIG_DECODERS) += decode_to_md5.c
|
||||
decode_to_md5.SRCS += md5_utils.h md5_utils.c
|
||||
decode_to_md5.SRCS += ivfdec.h ivfdec.c
|
||||
decode_to_md5.SRCS += tools_common.h tools_common.c
|
||||
decode_to_md5.SRCS += video_common.h
|
||||
decode_to_md5.SRCS += video_reader.h video_reader.c
|
||||
decode_to_md5.SRCS += vpx_ports/mem_ops.h
|
||||
decode_to_md5.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
decode_to_md5.SRCS += vpx_ports/msvc.h
|
||||
decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42
|
||||
decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum
|
||||
EXAMPLES-$(CONFIG_ENCODERS) += simple_encoder.c
|
||||
simple_encoder.SRCS += ivfenc.h ivfenc.c
|
||||
simple_encoder.SRCS += tools_common.h tools_common.c
|
||||
simple_encoder.SRCS += video_common.h
|
||||
simple_encoder.SRCS += video_writer.h video_writer.c
|
||||
simple_encoder.SRCS += vpx_ports/msvc.h
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += simple_decoder.c
|
||||
simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
|
||||
simple_decoder.DESCRIPTION = Simplified decoder loop
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += postproc.c
|
||||
postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
|
||||
postproc.DESCRIPTION = Decoder postprocessor control
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += decode_to_md5.c
|
||||
decode_to_md5.SRCS += md5_utils.h md5_utils.c
|
||||
decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42
|
||||
decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum
|
||||
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += simple_encoder.c
|
||||
simple_encoder.GUID = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
|
||||
simple_encoder.DESCRIPTION = Simplified encoder loop
|
||||
EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_lossless_encoder.c
|
||||
vp9_lossless_encoder.SRCS += ivfenc.h ivfenc.c
|
||||
vp9_lossless_encoder.SRCS += tools_common.h tools_common.c
|
||||
vp9_lossless_encoder.SRCS += video_common.h
|
||||
vp9_lossless_encoder.SRCS += video_writer.h video_writer.c
|
||||
vp9_lossless_encoder.SRCS += vpx_ports/msvc.h
|
||||
vp9_lossless_encoder.GUID = B63C7C88-5348-46DC-A5A6-CC151EF93366
|
||||
vp9_lossless_encoder.DESCRIPTION = Simplified lossless VP9 encoder
|
||||
EXAMPLES-$(CONFIG_ENCODERS) += twopass_encoder.c
|
||||
twopass_encoder.SRCS += ivfenc.h ivfenc.c
|
||||
twopass_encoder.SRCS += tools_common.h tools_common.c
|
||||
twopass_encoder.SRCS += video_common.h
|
||||
twopass_encoder.SRCS += video_writer.h video_writer.c
|
||||
twopass_encoder.SRCS += vpx_ports/msvc.h
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += twopass_encoder.c
|
||||
twopass_encoder.GUID = 73494FA6-4AF9-4763-8FBB-265C92402FD8
|
||||
twopass_encoder.DESCRIPTION = Two-pass encoder loop
|
||||
EXAMPLES-$(CONFIG_DECODERS) += decode_with_drops.c
|
||||
decode_with_drops.SRCS += ivfdec.h ivfdec.c
|
||||
decode_with_drops.SRCS += tools_common.h tools_common.c
|
||||
decode_with_drops.SRCS += video_common.h
|
||||
decode_with_drops.SRCS += video_reader.h video_reader.c
|
||||
decode_with_drops.SRCS += vpx_ports/mem_ops.h
|
||||
decode_with_drops.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
decode_with_drops.SRCS += vpx_ports/msvc.h
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += force_keyframe.c
|
||||
force_keyframe.GUID = 3C67CADF-029F-4C86-81F5-D6D4F51177F0
|
||||
force_keyframe.DESCRIPTION = Force generation of keyframes
|
||||
ifeq ($(CONFIG_DECODERS),yes)
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += decode_with_drops.c
|
||||
endif
|
||||
decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
|
||||
decode_with_drops.DESCRIPTION = Drops frames while decoding
|
||||
EXAMPLES-$(CONFIG_ENCODERS) += set_maps.c
|
||||
set_maps.SRCS += ivfenc.h ivfenc.c
|
||||
set_maps.SRCS += tools_common.h tools_common.c
|
||||
set_maps.SRCS += video_common.h
|
||||
set_maps.SRCS += video_writer.h video_writer.c
|
||||
set_maps.SRCS += vpx_ports/msvc.h
|
||||
set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
|
||||
set_maps.DESCRIPTION = Set active and ROI maps
|
||||
EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c
|
||||
vp8cx_set_ref.SRCS += ivfenc.h ivfenc.c
|
||||
vp8cx_set_ref.SRCS += tools_common.h tools_common.c
|
||||
vp8cx_set_ref.SRCS += video_common.h
|
||||
vp8cx_set_ref.SRCS += video_writer.h video_writer.c
|
||||
vp8cx_set_ref.SRCS += vpx_ports/msvc.h
|
||||
ifeq ($(CONFIG_VP8_DECODER),yes)
|
||||
GEN_EXAMPLES-$(CONFIG_ERROR_CONCEALMENT) += decode_with_partial_drops.c
|
||||
endif
|
||||
decode_with_partial_drops.GUID = 61C2D026-5754-46AC-916F-1343ECC5537E
|
||||
decode_with_partial_drops.DESCRIPTION = Drops parts of frames while decoding
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += error_resilient.c
|
||||
error_resilient.GUID = DF5837B9-4145-4F92-A031-44E4F832E00C
|
||||
error_resilient.DESCRIPTION = Error Resiliency Feature
|
||||
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_set_maps.c
|
||||
vp8_set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
|
||||
vp8_set_maps.DESCRIPTION = VP8 set active and ROI maps
|
||||
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c
|
||||
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)
|
||||
EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_multi_resolution_encoder.c
|
||||
vp8_multi_resolution_encoder.SRCS += ivfenc.h ivfenc.c
|
||||
vp8_multi_resolution_encoder.SRCS += tools_common.h tools_common.c
|
||||
vp8_multi_resolution_encoder.SRCS += video_writer.h video_writer.c
|
||||
vp8_multi_resolution_encoder.SRCS += vpx_ports/msvc.h
|
||||
vp8_multi_resolution_encoder.SRCS += $(LIBYUV_SRCS)
|
||||
vp8_multi_resolution_encoder.GUID = 04f8738e-63c8-423b-90fa-7c2703a374de
|
||||
vp8_multi_resolution_encoder.DESCRIPTION = VP8 Multiple-resolution Encoding
|
||||
endif
|
||||
endif
|
||||
# C file is provided, not generated automatically.
|
||||
UTILS-$(CONFIG_MULTI_RES_ENCODING) += vp8_multi_resolution_encoder.c
|
||||
vp8_multi_resolution_encoder.SRCS += $(LIBYUV_SRCS)
|
||||
vp8_multi_resolution_encoder.GUID = 04f8738e-63c8-423b-90fa-7c2703a374de
|
||||
vp8_multi_resolution_encoder.DESCRIPTION = VP8 Multiple-resolution Encoding
|
||||
|
||||
# Handle extra library flags depending on codec configuration
|
||||
|
||||
@@ -264,35 +139,42 @@ endif
|
||||
# from an installed tree or a version controlled tree. Determine
|
||||
# the proper paths.
|
||||
ifeq ($(HAVE_ALT_TREE_LAYOUT),yes)
|
||||
LIB_PATH-yes := $(SRC_PATH_BARE)/../lib
|
||||
INC_PATH-yes := $(SRC_PATH_BARE)/../include
|
||||
LIB_PATH := $(SRC_PATH_BARE)/../lib
|
||||
INC_PATH := $(SRC_PATH_BARE)/../include
|
||||
else
|
||||
LIB_PATH-yes += $(if $(BUILD_PFX),$(BUILD_PFX),.)
|
||||
INC_PATH-$(CONFIG_VP8_DECODER) += $(SRC_PATH_BARE)/vp8
|
||||
INC_PATH-$(CONFIG_VP8_ENCODER) += $(SRC_PATH_BARE)/vp8
|
||||
INC_PATH-$(CONFIG_VP9_DECODER) += $(SRC_PATH_BARE)/vp9
|
||||
INC_PATH-$(CONFIG_VP9_ENCODER) += $(SRC_PATH_BARE)/vp9
|
||||
LIB_PATH := $(call enabled,LIB_PATH)
|
||||
INC_PATH := $(call enabled,INC_PATH)
|
||||
endif
|
||||
INC_PATH-$(CONFIG_LIBYUV) += $(SRC_PATH_BARE)/third_party/libyuv/include
|
||||
LIB_PATH := $(call enabled,LIB_PATH)
|
||||
INC_PATH := $(call enabled,INC_PATH)
|
||||
INTERNAL_CFLAGS = $(addprefix -I,$(INC_PATH))
|
||||
INTERNAL_LDFLAGS += $(addprefix -L,$(LIB_PATH))
|
||||
|
||||
|
||||
# Expand list of selected examples to build (as specified above)
|
||||
UTILS = $(call enabled,UTILS)
|
||||
EXAMPLES = $(addprefix examples/,$(call enabled,EXAMPLES))
|
||||
ALL_EXAMPLES = $(UTILS) $(EXAMPLES)
|
||||
GEN_EXAMPLES = $(call enabled,GEN_EXAMPLES)
|
||||
ALL_EXAMPLES = $(UTILS) $(GEN_EXAMPLES)
|
||||
UTIL_SRCS = $(foreach ex,$(UTILS),$($(ex:.c=).SRCS))
|
||||
ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(notdir $(ex:.c=)).SRCS))
|
||||
ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(ex:.c=).SRCS))
|
||||
CODEC_EXTRA_LIBS=$(sort $(call enabled,CODEC_EXTRA_LIBS))
|
||||
|
||||
|
||||
# Expand all example sources into a variable containing all sources
|
||||
# for that example (not just them main one specified in UTILS/EXAMPLES)
|
||||
# for that example (not just them main one specified in UTILS/GEN_EXAMPLES)
|
||||
# and add this file to the list (for MSVS workspace generation)
|
||||
$(foreach ex,$(ALL_EXAMPLES),$(eval $(notdir $(ex:.c=)).SRCS += $(ex) examples.mk))
|
||||
$(foreach ex,$(ALL_EXAMPLES),$(eval $(ex:.c=).SRCS += $(ex) examples.mk))
|
||||
|
||||
|
||||
# If this is a universal (fat) binary, then all the subarchitectures have
|
||||
# already been built and our job is to stitch them together. The
|
||||
# BUILD_OBJS variable indicates whether we should be building
|
||||
# (compiling, linking) the library. The LIPO_OBJS variable indicates
|
||||
# that we're stitching.
|
||||
$(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_OBJS,BUILD_OBJS):=yes)
|
||||
|
||||
|
||||
# Create build/install dependencies for all examples. The common case
|
||||
@@ -302,28 +184,32 @@ DIST-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=$(EXE_SFX)))
|
||||
INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(UTILS:.c=$(EXE_SFX)))
|
||||
DIST-SRCS-yes += $(ALL_SRCS)
|
||||
INSTALL-SRCS-yes += $(UTIL_SRCS)
|
||||
OBJS-$(NOT_MSVS) += $(call objs,$(ALL_SRCS))
|
||||
OBJS-$(NOT_MSVS) += $(if $(BUILD_OBJS),$(call objs,$(ALL_SRCS)))
|
||||
BINS-$(NOT_MSVS) += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=$(EXE_SFX)))
|
||||
|
||||
|
||||
# Instantiate linker template for all examples.
|
||||
CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx)
|
||||
ifneq ($(filter darwin%,$(TGT_OS)),)
|
||||
SHARED_LIB_SUF=.dylib
|
||||
else
|
||||
ifneq ($(filter os2%,$(TGT_OS)),)
|
||||
SHARED_LIB_SUF=_dll.a
|
||||
else
|
||||
SHARED_LIB_SUF=.so
|
||||
endif
|
||||
endif
|
||||
SHARED_LIB_SUF=$(if $(filter darwin%,$(TGT_OS)),.dylib,.so)
|
||||
CODEC_LIB_SUF=$(if $(CONFIG_SHARED),$(SHARED_LIB_SUF),.a)
|
||||
$(foreach bin,$(BINS-yes),\
|
||||
$(eval $(bin):$(LIB_PATH)/lib$(CODEC_LIB)$(CODEC_LIB_SUF))\
|
||||
$(eval $(call linker_template,$(bin),\
|
||||
$(if $(BUILD_OBJS),$(eval $(bin):\
|
||||
$(LIB_PATH)/lib$(CODEC_LIB)$(CODEC_LIB_SUF)))\
|
||||
$(if $(BUILD_OBJS),$(eval $(call linker_template,$(bin),\
|
||||
$(call objs,$($(notdir $(bin:$(EXE_SFX)=)).SRCS)) \
|
||||
-l$(CODEC_LIB) $(addprefix -l,$(CODEC_EXTRA_LIBS))\
|
||||
)))
|
||||
)))\
|
||||
$(if $(LIPO_OBJS),$(eval $(call lipo_bin_template,$(bin))))\
|
||||
)
|
||||
|
||||
|
||||
# Rules to generate the GEN_EXAMPLES sources
|
||||
.PRECIOUS: %.c
|
||||
CLEAN-OBJS += $(GEN_EXAMPLES)
|
||||
%.c: examples/%.c
|
||||
@echo " [EXAMPLE] $@"
|
||||
@cp $< $@
|
||||
|
||||
|
||||
# The following pairs define a mapping of locations in the distribution
|
||||
# tree to locations in the source/build trees.
|
||||
@@ -351,55 +237,19 @@ endif
|
||||
# the makefiles). We may want to revisit this.
|
||||
define vcproj_template
|
||||
$(1): $($(1:.$(VCPROJ_SFX)=).SRCS) vpx.$(VCPROJ_SFX)
|
||||
$(if $(quiet),@echo " [vcproj] $$@")
|
||||
$(qexec)$$(GEN_VCPROJ)\
|
||||
@echo " [vcproj] $$@"
|
||||
$$(GEN_VCPROJ)\
|
||||
--exe\
|
||||
--target=$$(TOOLCHAIN)\
|
||||
--name=$$(@:.$(VCPROJ_SFX)=)\
|
||||
--ver=$$(CONFIG_VS_VERSION)\
|
||||
--proj-guid=$$($$(@:.$(VCPROJ_SFX)=).GUID)\
|
||||
--src-path-bare="$(SRC_PATH_BARE)" \
|
||||
$$(if $$(CONFIG_STATIC_MSVCRT),--static-crt) \
|
||||
--out=$$@ $$(INTERNAL_CFLAGS) $$(CFLAGS) \
|
||||
$$(INTERNAL_LDFLAGS) $$(LDFLAGS) -l$$(CODEC_LIB) $$^
|
||||
endef
|
||||
ALL_EXAMPLES_BASENAME := $(notdir $(ALL_EXAMPLES))
|
||||
PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES_BASENAME:.c=.$(VCPROJ_SFX))
|
||||
PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES:.c=.$(VCPROJ_SFX))
|
||||
INSTALL-BINS-$(CONFIG_MSVS) += $(foreach p,$(VS_PLATFORMS),\
|
||||
$(addprefix bin/$(p)/,$(ALL_EXAMPLES_BASENAME:.c=.exe)))
|
||||
$(addprefix bin/$(p)/,$(ALL_EXAMPLES:.c=.exe)))
|
||||
$(foreach proj,$(call enabled,PROJECTS),\
|
||||
$(eval $(call vcproj_template,$(proj))))
|
||||
|
||||
#
|
||||
# Documentation Rules
|
||||
#
|
||||
%.dox: %.c
|
||||
@echo " [DOXY] $@"
|
||||
@mkdir -p $(dir $@)
|
||||
@echo "/*!\page example_$(@F:.dox=) $(@F:.dox=)" > $@
|
||||
@echo " \includelineno $(<F)" >> $@
|
||||
@echo "*/" >> $@
|
||||
|
||||
samples.dox: examples.mk
|
||||
@echo " [DOXY] $@"
|
||||
@echo "/*!\page samples Sample Code" > $@
|
||||
@echo " This SDK includes a number of sample applications."\
|
||||
"Each sample documents a feature of the SDK in both prose"\
|
||||
"and the associated C code."\
|
||||
"The following samples are included: ">>$@
|
||||
@$(foreach ex,$(sort $(notdir $(EXAMPLES:.c=))),\
|
||||
echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
|
||||
@echo >> $@
|
||||
@echo " In addition, the SDK contains a number of utilities."\
|
||||
"Since these utilities are built upon the concepts described"\
|
||||
"in the sample code listed above, they are not documented in"\
|
||||
"pieces like the samples are. Their source is included here"\
|
||||
"for reference. The following utilities are included:" >> $@
|
||||
@$(foreach ex,$(sort $(UTILS:.c=)),\
|
||||
echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
|
||||
@echo "*/" >> $@
|
||||
|
||||
CLEAN-OBJS += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
|
||||
DOCS-yes += examples.doxy samples.dox
|
||||
examples.doxy: samples.dox $(ALL_EXAMPLES:.c=.dox)
|
||||
@echo "INPUT += $^" > $@
|
||||
|
||||
@@ -29,17 +29,54 @@
|
||||
// is processed, then U, then V. It is important to honor the image's `stride`
|
||||
// values.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#include "md5_utils.h"
|
||||
|
||||
#include "../md5_utils.h"
|
||||
#include "../tools_common.h"
|
||||
#include "../video_reader.h"
|
||||
#include "./vpx_config.h"
|
||||
#define VP8_FOURCC 0x30385056
|
||||
#define VP9_FOURCC 0x30395056
|
||||
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) {
|
||||
switch (fourcc) {
|
||||
case VP8_FOURCC:
|
||||
return vpx_codec_vp8_dx();
|
||||
case VP9_FOURCC:
|
||||
return vpx_codec_vp9_dx();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned int mem_get_le32(const unsigned char *mem) {
|
||||
return (mem[3] << 24) | (mem[2] << 16) | (mem[1] << 8) | (mem[0]);
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if (fmt[strlen(fmt) - 1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) {
|
||||
int plane, y;
|
||||
@@ -65,51 +102,55 @@ 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]);
|
||||
}
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
for (i = 0; i < 16; ++i)
|
||||
fprintf(stream, "%02x", digest[i]);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int frame_cnt = 0;
|
||||
FILE *outfile = NULL;
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
const VpxInterface *decoder = NULL;
|
||||
vpx_codec_iface_t *iface;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
unsigned char file_hdr[IVF_FILE_HDR_SZ];
|
||||
unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
|
||||
unsigned char frame[256 * 1024];
|
||||
|
||||
exec_name = argv[0];
|
||||
if (argc != 3)
|
||||
die("Usage: %s <infile> <outfile>\n", argv[0]);
|
||||
|
||||
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 (!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
if (!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ &&
|
||||
file_hdr[0] == 'D' && file_hdr[1] == 'K' &&
|
||||
file_hdr[2] == 'I' && file_hdr[3] == 'F'))
|
||||
die("%s is not an IVF file.", argv[1]);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
iface = get_codec_interface(mem_get_le32(file_hdr + 8));
|
||||
if (!iface)
|
||||
die("Unknown FOURCC code.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
|
||||
printf("Using %s\n", vpx_codec_iface_name(iface));
|
||||
|
||||
if (vpx_codec_dec_init(&codec, iface, NULL, flags))
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
|
||||
while (vpx_video_reader_read_frame(reader)) {
|
||||
while (fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
|
||||
const int frame_size = mem_get_le32(frame_hdr);
|
||||
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);
|
||||
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
|
||||
vpx_image_t *img;
|
||||
|
||||
if (frame_size > sizeof(frame))
|
||||
die("Frame %d data too big for example code buffer", frame_size);
|
||||
|
||||
if (fread(frame, 1, frame_size, infile) != frame_size)
|
||||
die("Failed to read complete frame");
|
||||
|
||||
if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
|
||||
@@ -117,16 +158,16 @@ 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.");
|
||||
|
||||
vpx_video_reader_close(reader);
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -52,97 +52,126 @@
|
||||
// The example decides whether to drop the frame based on the current
|
||||
// frame number, immediately before decoding the frame.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#define interface (vpx_codec_vp8_dx())
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_reader.h"
|
||||
#include "./vpx_config.h"
|
||||
|
||||
static const char *exec_name;
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
static unsigned int mem_get_le32(const unsigned char *mem) {
|
||||
return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int frame_cnt = 0;
|
||||
FILE *outfile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
const VpxInterface *decoder = NULL;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
int n = 0;
|
||||
int m = 0;
|
||||
int is_range = 0;
|
||||
char *nptr = NULL;
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
unsigned char file_hdr[IVF_FILE_HDR_SZ];
|
||||
unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
|
||||
unsigned char frame[256*1024];
|
||||
vpx_codec_err_t res;
|
||||
int n, m, is_range;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
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 (!(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);
|
||||
is_range = (*nptr == '-');
|
||||
if (!n || !m || (*nptr != '-' && *nptr != '/'))
|
||||
die("Couldn't parse pattern %s.\n", argv[3]);
|
||||
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
|
||||
die_codec(&codec, "Failed to initialize decoder.");
|
||||
|
||||
while (vpx_video_reader_read_frame(reader)) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
int skip;
|
||||
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.");
|
||||
|
||||
++frame_cnt;
|
||||
|
||||
skip = (is_range && frame_cnt >= n && frame_cnt <= m) ||
|
||||
(!is_range && m - (frame_cnt - 1) % m <= n);
|
||||
|
||||
if (!skip) {
|
||||
putc('.', stdout);
|
||||
|
||||
while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL)
|
||||
vpx_img_write(img, outfile);
|
||||
} else {
|
||||
putc('X', stdout);
|
||||
(void)res;
|
||||
/* Open files */
|
||||
if(argc!=4)
|
||||
die("Usage: %s <infile> <outfile> <N-M|N/M>\n", argv[0]);
|
||||
{
|
||||
char *nptr;
|
||||
n = strtol(argv[3], &nptr, 0);
|
||||
m = strtol(nptr+1, NULL, 0);
|
||||
is_range = *nptr == '-';
|
||||
if(!n || !m || (*nptr != '-' && *nptr != '/'))
|
||||
die("Couldn't parse pattern %s\n", argv[3]);
|
||||
}
|
||||
if(!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
if(!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
/* Read file header */
|
||||
if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
|
||||
&& file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
|
||||
&& file_hdr[3]=='F'))
|
||||
die("%s is not an IVF file.", argv[1]);
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_dec_init(&codec, interface, NULL, flags))
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
/* Read each frame */
|
||||
while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
|
||||
int frame_sz = mem_get_le32(frame_hdr);
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img;
|
||||
|
||||
vpx_video_reader_close(reader);
|
||||
fclose(outfile);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
frame_cnt++;
|
||||
if(frame_sz > sizeof(frame))
|
||||
die("Frame %d data too big for example code buffer", frame_sz);
|
||||
if(fread(frame, 1, frame_sz, infile) != frame_sz)
|
||||
die("Frame %d failed to read complete frame", frame_cnt);
|
||||
|
||||
if((is_range && frame_cnt >= n && frame_cnt <= m)
|
||||
||(!is_range && m - (frame_cnt-1)%m <= n)) {
|
||||
putc('X', stdout);
|
||||
continue;
|
||||
}
|
||||
putc('.', stdout);
|
||||
fflush(stdout);
|
||||
/* Decode the frame */
|
||||
if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
/* Write decoded data to disk */
|
||||
while((img = vpx_codec_get_frame(&codec, &iter))) {
|
||||
unsigned int plane, y;
|
||||
|
||||
for(plane=0; plane < 3; plane++) {
|
||||
unsigned char *buf =img->planes[plane];
|
||||
|
||||
for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
|
||||
(void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
|
||||
outfile);
|
||||
buf += img->stride[plane];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Processed %d frames.\n",frame_cnt);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
328
examples/decode_with_partial_drops.c
Normal file
328
examples/decode_with_partial_drops.c
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Decode With Partial Drops Example
|
||||
// =========================
|
||||
//
|
||||
// This is an example utility which drops a series of frames (or parts of
|
||||
// frames), as specified on the command line. This is useful for observing the
|
||||
// error recovery features of the codec.
|
||||
//
|
||||
// Usage
|
||||
// -----
|
||||
// This example adds a single argument to the `simple_decoder` example,
|
||||
// which specifies the range or pattern of frames to drop. The parameter is
|
||||
// parsed as follows.
|
||||
//
|
||||
// Dropping A Range Of Frames
|
||||
// --------------------------
|
||||
// To drop a range of frames, specify the starting frame and the ending
|
||||
// frame to drop, separated by a dash. The following command will drop
|
||||
// frames 5 through 10 (base 1).
|
||||
//
|
||||
// $ ./decode_with_partial_drops in.ivf out.i420 5-10
|
||||
//
|
||||
//
|
||||
// Dropping A Pattern Of Frames
|
||||
// ----------------------------
|
||||
// To drop a pattern of frames, specify the number of frames to drop and
|
||||
// the number of frames after which to repeat the pattern, separated by
|
||||
// a forward-slash. The following command will drop 3 of 7 frames.
|
||||
// Specifically, it will decode 4 frames, then drop 3 frames, and then
|
||||
// repeat.
|
||||
//
|
||||
// $ ./decode_with_partial_drops in.ivf out.i420 3/7
|
||||
//
|
||||
// Dropping Random Parts Of Frames
|
||||
// -------------------------------
|
||||
// A third argument tuple is available to split the frame into 1500 bytes pieces
|
||||
// and randomly drop pieces rather than frames. The frame will be split at
|
||||
// partition boundaries where possible. The following example will seed the RNG
|
||||
// with the seed 123 and drop approximately 5% of the pieces. Pieces which
|
||||
// are depending on an already dropped piece will also be dropped.
|
||||
//
|
||||
// $ ./decode_with_partial_drops in.ivf out.i420 5,123
|
||||
//
|
||||
// Extra Variables
|
||||
// ---------------
|
||||
// This example maintains the pattern passed on the command line in the
|
||||
// `n`, `m`, and `is_range` variables:
|
||||
//
|
||||
// Making The Drop Decision
|
||||
// ------------------------
|
||||
// The example decides whether to drop the frame based on the current
|
||||
// frame number, immediately before decoding the frame.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#define interface (vpx_codec_vp8_dx())
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static unsigned int mem_get_le32(const unsigned char *mem) {
|
||||
return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct parsed_header
|
||||
{
|
||||
char key_frame;
|
||||
int version;
|
||||
char show_frame;
|
||||
int first_part_size;
|
||||
};
|
||||
|
||||
int next_packet(struct parsed_header* hdr, int pos, int length, int mtu)
|
||||
{
|
||||
int size = 0;
|
||||
int remaining = length - pos;
|
||||
/* Uncompressed part is 3 bytes for P frames and 10 bytes for I frames */
|
||||
int uncomp_part_size = (hdr->key_frame ? 10 : 3);
|
||||
/* number of bytes yet to send from header and the first partition */
|
||||
int remainFirst = uncomp_part_size + hdr->first_part_size - pos;
|
||||
if (remainFirst > 0)
|
||||
{
|
||||
if (remainFirst <= mtu)
|
||||
{
|
||||
size = remainFirst;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = mtu;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* second partition; just slot it up according to MTU */
|
||||
if (remaining <= mtu)
|
||||
{
|
||||
size = remaining;
|
||||
return size;
|
||||
}
|
||||
return mtu;
|
||||
}
|
||||
|
||||
void throw_packets(unsigned char* frame, int* size, int loss_rate,
|
||||
int* thrown, int* kept)
|
||||
{
|
||||
unsigned char loss_frame[256*1024];
|
||||
int pkg_size = 1;
|
||||
int pos = 0;
|
||||
int loss_pos = 0;
|
||||
struct parsed_header hdr;
|
||||
unsigned int tmp;
|
||||
int mtu = 1500;
|
||||
|
||||
if (*size < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
putc('|', stdout);
|
||||
/* parse uncompressed 3 bytes */
|
||||
tmp = (frame[2] << 16) | (frame[1] << 8) | frame[0];
|
||||
hdr.key_frame = !(tmp & 0x1); /* inverse logic */
|
||||
hdr.version = (tmp >> 1) & 0x7;
|
||||
hdr.show_frame = (tmp >> 4) & 0x1;
|
||||
hdr.first_part_size = (tmp >> 5) & 0x7FFFF;
|
||||
|
||||
/* don't drop key frames */
|
||||
if (hdr.key_frame)
|
||||
{
|
||||
int i;
|
||||
*kept = *size/mtu + ((*size % mtu > 0) ? 1 : 0); /* approximate */
|
||||
for (i=0; i < *kept; i++)
|
||||
putc('.', stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((pkg_size = next_packet(&hdr, pos, *size, mtu)) > 0)
|
||||
{
|
||||
int loss_event = ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate/100.0);
|
||||
if (*thrown == 0 && !loss_event)
|
||||
{
|
||||
memcpy(loss_frame + loss_pos, frame + pos, pkg_size);
|
||||
loss_pos += pkg_size;
|
||||
(*kept)++;
|
||||
putc('.', stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*thrown)++;
|
||||
putc('X', stdout);
|
||||
}
|
||||
pos += pkg_size;
|
||||
}
|
||||
memcpy(frame, loss_frame, loss_pos);
|
||||
memset(frame + loss_pos, 0, *size - loss_pos);
|
||||
*size = loss_pos;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
unsigned char file_hdr[IVF_FILE_HDR_SZ];
|
||||
unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
|
||||
unsigned char frame[256*1024];
|
||||
vpx_codec_err_t res;
|
||||
int n, m, mode;
|
||||
unsigned int seed;
|
||||
int thrown=0, kept=0;
|
||||
int thrown_frame=0, kept_frame=0;
|
||||
vpx_codec_dec_cfg_t dec_cfg = {0};
|
||||
|
||||
(void)res;
|
||||
/* Open files */
|
||||
if(argc < 4 || argc > 6)
|
||||
die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n",
|
||||
argv[0]);
|
||||
{
|
||||
char *nptr;
|
||||
int arg_num = 3;
|
||||
if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0)
|
||||
dec_cfg.threads = strtol(argv[arg_num++], NULL, 0);
|
||||
n = strtol(argv[arg_num], &nptr, 0);
|
||||
mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0;
|
||||
|
||||
m = strtol(nptr+1, NULL, 0);
|
||||
if((!n && !m) || (*nptr != '-' && *nptr != '/' &&
|
||||
*nptr != '\0' && *nptr != ','))
|
||||
die("Couldn't parse pattern %s\n", argv[3]);
|
||||
}
|
||||
seed = (m > 0) ? m : (unsigned int)time(NULL);
|
||||
srand(seed);thrown_frame = 0;
|
||||
printf("Seed: %u\n", seed);
|
||||
printf("Threads: %d\n", dec_cfg.threads);
|
||||
if(!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
if(!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
|
||||
/* Read file header */
|
||||
if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
|
||||
&& file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
|
||||
&& file_hdr[3]=='F'))
|
||||
die("%s is not an IVF file.", argv[1]);
|
||||
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
/* Initialize codec */
|
||||
flags = VPX_CODEC_USE_ERROR_CONCEALMENT;
|
||||
res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags);
|
||||
if(res)
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
|
||||
|
||||
/* Read each frame */
|
||||
while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
|
||||
int frame_sz = mem_get_le32(frame_hdr);
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img;
|
||||
|
||||
|
||||
frame_cnt++;
|
||||
if(frame_sz > sizeof(frame))
|
||||
die("Frame %d data too big for example code buffer", frame_sz);
|
||||
if(fread(frame, 1, frame_sz, infile) != frame_sz)
|
||||
die("Frame %d failed to read complete frame", frame_cnt);
|
||||
|
||||
/* Decide whether to throw parts of the frame or the whole frame
|
||||
depending on the drop mode */
|
||||
thrown_frame = 0;
|
||||
kept_frame = 0;
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
if (m - (frame_cnt-1)%m <= n)
|
||||
{
|
||||
frame_sz = 0;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (frame_cnt >= n && frame_cnt <= m)
|
||||
{
|
||||
frame_sz = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
throw_packets(frame, &frame_sz, n, &thrown_frame, &kept_frame);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (mode < 2)
|
||||
{
|
||||
if (frame_sz == 0)
|
||||
{
|
||||
putc('X', stdout);
|
||||
thrown_frame++;
|
||||
}
|
||||
else
|
||||
{
|
||||
putc('.', stdout);
|
||||
kept_frame++;
|
||||
}
|
||||
}
|
||||
thrown += thrown_frame;
|
||||
kept += kept_frame;
|
||||
fflush(stdout);
|
||||
/* Decode the frame */
|
||||
if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
/* Write decoded data to disk */
|
||||
while((img = vpx_codec_get_frame(&codec, &iter))) {
|
||||
unsigned int plane, y;
|
||||
|
||||
for(plane=0; plane < 3; plane++) {
|
||||
unsigned char *buf =img->planes[plane];
|
||||
|
||||
for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
|
||||
(void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
|
||||
outfile);
|
||||
buf += img->stride[plane];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Processed %d frames.\n",frame_cnt);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
223
examples/error_resilient.c
Normal file
223
examples/error_resilient.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Error Resiliency Features
|
||||
// =========================
|
||||
//
|
||||
// This is an example demonstrating how to enable the error resiliency
|
||||
// features of the codec.
|
||||
//
|
||||
// Configuration
|
||||
// -------------
|
||||
// Error resiliency is controlled by the g_error_resilient member of the
|
||||
// configuration structure.
|
||||
//
|
||||
// Observing The Effects
|
||||
// ---------------------
|
||||
// Use the `decode_with_drops` example to decode with frames 5-10 dropped.
|
||||
// Compare the output for a file encoded with this example versus one
|
||||
// encoded with the `simple_encoder` example.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static void mem_put_le16(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
}
|
||||
|
||||
static void mem_put_le32(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
mem[2] = val>>16;
|
||||
mem[3] = val>>24;
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w*img->h*3/2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if(nbytes != to_read) {
|
||||
res = 0;
|
||||
if(nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void write_ivf_file_header(FILE *outfile,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
||||
return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header+4, 0); /* version */
|
||||
mem_put_le16(header+6, 32); /* headersize */
|
||||
mem_put_le32(header+8, fourcc); /* headersize */
|
||||
mem_put_le16(header+12, cfg->g_w); /* width */
|
||||
mem_put_le16(header+14, cfg->g_h); /* height */
|
||||
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header+24, frame_cnt); /* length */
|
||||
mem_put_le32(header+28, 0); /* unused */
|
||||
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
||||
return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header+4, pts&0xFFFFFFFF);
|
||||
mem_put_le32(header+8, pts >> 32);
|
||||
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
long width;
|
||||
long height;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
|
||||
/* Open files */
|
||||
if(argc!=5)
|
||||
die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
|
||||
die("Faile to allocate image", width, height);
|
||||
if(!(outfile = fopen(argv[4], "wb")))
|
||||
die("Failed to open %s for writing", argv[4]);
|
||||
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
|
||||
/* Populate encoder configuration */
|
||||
res = vpx_codec_enc_config_default(interface, &cfg, 0);
|
||||
if(res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Update the default configuration with our settings */
|
||||
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
|
||||
/ cfg.g_w / cfg.g_h;
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
/* Enable error resilient mode */
|
||||
cfg.g_error_resilient = 1;
|
||||
|
||||
write_ivf_file_header(outfile, &cfg, 0);
|
||||
|
||||
|
||||
/* Open input file for this encoding pass */
|
||||
if(!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
while(frame_avail || got_data) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
frame_avail = read_frame(infile, &raw);
|
||||
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
|
||||
1, flags, VPX_DL_REALTIME))
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
got_data = 0;
|
||||
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch(pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
(void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
|
||||
outfile);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
|
||||
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
|
||||
fflush(stdout);
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
|
||||
printf("Processed %d frames.\n",frame_cnt-1);
|
||||
vpx_img_free(&raw);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
193
examples/example_xma.c
Normal file
193
examples/example_xma.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/* This is a simple program showing how to initialize the decoder in XMA mode */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx_config.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#if CONFIG_VP9_DECODER
|
||||
#include "vpx/vp8dx.h"
|
||||
#endif
|
||||
|
||||
static char *exec_name;
|
||||
static int verbose = 0;
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
const vpx_codec_iface_t *iface;
|
||||
} ifaces[] = {
|
||||
#if CONFIG_VP9_DECODER
|
||||
{"vp9", &vpx_codec_vp8_dx_algo},
|
||||
#endif
|
||||
};
|
||||
|
||||
static void usage_exit(void) {
|
||||
int i;
|
||||
|
||||
printf("Usage: %s <options>\n\n"
|
||||
"Options:\n"
|
||||
"\t--codec <name>\tCodec to use (default=%s)\n"
|
||||
"\t-h <height>\tHeight of the simulated video frame, in pixels\n"
|
||||
"\t-w <width> \tWidth of the simulated video frame, in pixels\n"
|
||||
"\t-v \tVerbose mode (show individual segment sizes)\n"
|
||||
"\t--help \tShow this message\n"
|
||||
"\n"
|
||||
"Included decoders:\n"
|
||||
"\n",
|
||||
exec_name,
|
||||
ifaces[0].name);
|
||||
|
||||
for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
|
||||
printf(" %-6s - %s\n",
|
||||
ifaces[i].name,
|
||||
vpx_codec_iface_name(ifaces[i].iface));
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void usage_error(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
printf("\n");
|
||||
usage_exit();
|
||||
}
|
||||
|
||||
void my_mem_dtor(vpx_codec_mmap_t *mmap) {
|
||||
if (verbose)
|
||||
printf("freeing segment %d\n", mmap->id);
|
||||
|
||||
free(mmap->priv);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
vpx_codec_ctx_t decoder;
|
||||
vpx_codec_iface_t *iface = ifaces[0].iface;
|
||||
vpx_codec_iter_t iter;
|
||||
vpx_codec_dec_cfg_t cfg;
|
||||
vpx_codec_err_t res = VPX_CODEC_OK;
|
||||
unsigned int alloc_sz = 0;
|
||||
unsigned int w = 352;
|
||||
unsigned int h = 288;
|
||||
int i;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--codec")) {
|
||||
if (i + 1 < argc) {
|
||||
int j, k = -1;
|
||||
|
||||
i++;
|
||||
|
||||
for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
|
||||
if (!strcmp(ifaces[j].name, argv[i]))
|
||||
k = j;
|
||||
|
||||
if (k >= 0)
|
||||
iface = ifaces[k].iface;
|
||||
else
|
||||
usage_error("Error: Unrecognized argument (%s) to --codec\n",
|
||||
argv[i]);
|
||||
} else
|
||||
usage_error("Error: Option --codec requires argument.\n");
|
||||
} else if (!strcmp(argv[i], "-v"))
|
||||
verbose = 1;
|
||||
else if (!strcmp(argv[i], "-h"))
|
||||
if (i + 1 < argc) {
|
||||
h = atoi(argv[++i]);
|
||||
} else
|
||||
usage_error("Error: Option -h requires argument.\n");
|
||||
else if (!strcmp(argv[i], "-w"))
|
||||
if (i + 1 < argc) {
|
||||
w = atoi(argv[++i]);
|
||||
} else
|
||||
usage_error("Error: Option -w requires argument.\n");
|
||||
else if (!strcmp(argv[i], "--help"))
|
||||
usage_exit();
|
||||
else
|
||||
usage_error("Error: Unrecognized option %s\n\n", argv[i]);
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
printf("Using built-in defaults. For options, rerun with --help\n\n");
|
||||
|
||||
/* XMA mode is not supported on all decoders! */
|
||||
if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA)) {
|
||||
printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* The codec knows how much memory to allocate based on the size of the
|
||||
* encoded frames. This data can be parsed from the bitstream with
|
||||
* vpx_codec_peek_stream_info() if a bitstream is available. Otherwise,
|
||||
* a fixed size can be used that will be the upper limit on the frame
|
||||
* size the decoder can decode.
|
||||
*/
|
||||
cfg.w = w;
|
||||
cfg.h = h;
|
||||
|
||||
/* Initialize the decoder in XMA mode. */
|
||||
if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA)) {
|
||||
printf("Failed to initialize decoder in XMA mode: %s\n",
|
||||
vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Iterate through the list of memory maps, allocating them with the
|
||||
* requested alignment.
|
||||
*/
|
||||
iter = NULL;
|
||||
|
||||
do {
|
||||
vpx_codec_mmap_t mmap;
|
||||
unsigned int align;
|
||||
|
||||
res = vpx_codec_get_mem_map(&decoder, &mmap, &iter);
|
||||
align = mmap.align ? mmap.align - 1 : 0;
|
||||
|
||||
if (!res) {
|
||||
if (verbose)
|
||||
printf("Allocating segment %u, size %lu, align %u %s\n",
|
||||
mmap.id, mmap.sz, mmap.align,
|
||||
mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : "");
|
||||
|
||||
if (mmap.flags & VPX_CODEC_MEM_ZERO)
|
||||
mmap.priv = calloc(1, mmap.sz + align);
|
||||
else
|
||||
mmap.priv = malloc(mmap.sz + align);
|
||||
|
||||
mmap.base = (void *)((((uintptr_t)mmap.priv) + align) &
|
||||
~(uintptr_t)align);
|
||||
mmap.dtor = my_mem_dtor;
|
||||
alloc_sz += mmap.sz + align;
|
||||
|
||||
if (vpx_codec_set_mem_map(&decoder, &mmap, 1)) {
|
||||
printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else if (res != VPX_CODEC_LIST_END) {
|
||||
printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} while (res != VPX_CODEC_LIST_END);
|
||||
|
||||
printf("%s\n %d bytes external memory required for %dx%d.\n",
|
||||
decoder.name, alloc_sz, cfg.w, cfg.h);
|
||||
vpx_codec_destroy(&decoder);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
}
|
||||
225
examples/force_keyframe.c
Normal file
225
examples/force_keyframe.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Forcing A Keyframe
|
||||
// ==================
|
||||
//
|
||||
// This is an example demonstrating how to control placement of keyframes
|
||||
// on a frame-by-frame basis.
|
||||
//
|
||||
// Configuration
|
||||
// -------------
|
||||
// Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the
|
||||
// flags passed to `vpx_codec_control()`. In this example, we force a
|
||||
// keyframe every 8 frames.
|
||||
//
|
||||
// Observing The Effects
|
||||
// ---------------------
|
||||
// The output of the encoder examples shows a 'K' rather than a dot '.'
|
||||
// when the encoder generates a keyframe. Note that every 8 frames a 'K'
|
||||
// is output.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static void mem_put_le16(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
}
|
||||
|
||||
static void mem_put_le32(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
mem[2] = val>>16;
|
||||
mem[3] = val>>24;
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w*img->h*3/2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if(nbytes != to_read) {
|
||||
res = 0;
|
||||
if(nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void write_ivf_file_header(FILE *outfile,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
||||
return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header+4, 0); /* version */
|
||||
mem_put_le16(header+6, 32); /* headersize */
|
||||
mem_put_le32(header+8, fourcc); /* headersize */
|
||||
mem_put_le16(header+12, cfg->g_w); /* width */
|
||||
mem_put_le16(header+14, cfg->g_h); /* height */
|
||||
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header+24, frame_cnt); /* length */
|
||||
mem_put_le32(header+28, 0); /* unused */
|
||||
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
||||
return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header+4, pts&0xFFFFFFFF);
|
||||
mem_put_le32(header+8, pts >> 32);
|
||||
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
long width;
|
||||
long height;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
|
||||
/* Open files */
|
||||
if(argc!=5)
|
||||
die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
|
||||
die("Faile to allocate image", width, height);
|
||||
if(!(outfile = fopen(argv[4], "wb")))
|
||||
die("Failed to open %s for writing", argv[4]);
|
||||
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
|
||||
/* Populate encoder configuration */
|
||||
res = vpx_codec_enc_config_default(interface, &cfg, 0);
|
||||
if(res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Update the default configuration with our settings */
|
||||
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
|
||||
/ cfg.g_w / cfg.g_h;
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
write_ivf_file_header(outfile, &cfg, 0);
|
||||
|
||||
|
||||
/* Open input file for this encoding pass */
|
||||
if(!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
while(frame_avail || got_data) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
if(!(frame_cnt & 7))
|
||||
flags |= VPX_EFLAG_FORCE_KF;
|
||||
else
|
||||
flags &= ~VPX_EFLAG_FORCE_KF;
|
||||
frame_avail = read_frame(infile, &raw);
|
||||
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
|
||||
1, flags, VPX_DL_REALTIME))
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
got_data = 0;
|
||||
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch(pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
(void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
|
||||
outfile);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
|
||||
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
|
||||
fflush(stdout);
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
|
||||
printf("Processed %d frames.\n",frame_cnt-1);
|
||||
vpx_img_free(&raw);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -39,95 +39,130 @@
|
||||
// postprocessors. VP8 is one example. The following sample code toggles
|
||||
// postprocessing on and off every 15 frames.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#define interface (vpx_codec_vp8_dx())
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_reader.h"
|
||||
#include "./vpx_config.h"
|
||||
|
||||
static const char *exec_name;
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
static unsigned int mem_get_le32(const unsigned char *mem) {
|
||||
return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int frame_cnt = 0;
|
||||
FILE *outfile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxInterface *decoder = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
unsigned char file_hdr[IVF_FILE_HDR_SZ];
|
||||
unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
|
||||
unsigned char frame[256*1024];
|
||||
vpx_codec_err_t res;
|
||||
|
||||
exec_name = argv[0];
|
||||
(void)res;
|
||||
/* Open files */
|
||||
if(argc!=3)
|
||||
die("Usage: %s <infile> <outfile>\n", argv[0]);
|
||||
if(!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
if(!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
|
||||
if (argc != 3) die("Invalid number of arguments.");
|
||||
/* Read file header */
|
||||
if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
|
||||
&& file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
|
||||
&& file_hdr[3]=='F'))
|
||||
die("%s is not an IVF file.", argv[1]);
|
||||
|
||||
reader = vpx_video_reader_open(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]);
|
||||
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
res = vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL,
|
||||
VPX_CODEC_USE_POSTPROC);
|
||||
if (res == VPX_CODEC_INCAPABLE)
|
||||
die_codec(&codec, "Postproc not supported by this decoder.");
|
||||
|
||||
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);
|
||||
|
||||
++frame_cnt;
|
||||
|
||||
if (frame_cnt % 30 == 1) {
|
||||
vp8_postproc_cfg_t pp = { 0, 0, 0 };
|
||||
|
||||
if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn off postproc.");
|
||||
} else if (frame_cnt % 30 == 16) {
|
||||
vp8_postproc_cfg_t pp = { VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE, 4,
|
||||
0 };
|
||||
if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn on postproc.");
|
||||
};
|
||||
|
||||
// Decode the frame with 15ms deadline
|
||||
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 15000))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
|
||||
vpx_img_write(img, outfile);
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
/* Initialize codec */
|
||||
res = vpx_codec_dec_init(&codec, interface, NULL,
|
||||
VPX_CODEC_USE_POSTPROC);
|
||||
if(res == VPX_CODEC_INCAPABLE) {
|
||||
printf("NOTICE: Postproc not supported by %s\n",
|
||||
vpx_codec_iface_name(interface));
|
||||
res = vpx_codec_dec_init(&codec, interface, NULL, flags);
|
||||
}
|
||||
}
|
||||
if(res)
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
/* Read each frame */
|
||||
while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
|
||||
int frame_sz = mem_get_le32(frame_hdr);
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img;
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
||||
vpx_video_reader_close(reader);
|
||||
frame_cnt++;
|
||||
if(frame_sz > sizeof(frame))
|
||||
die("Frame %d data too big for example code buffer", frame_sz);
|
||||
if(fread(frame, 1, frame_sz, infile) != frame_sz)
|
||||
die("Frame %d failed to read complete frame", frame_cnt);
|
||||
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
#if CONFIG_VP9_DECODER
|
||||
if(frame_cnt%30 == 1) {
|
||||
vp8_postproc_cfg_t pp = {0, 0, 0};
|
||||
|
||||
if(vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn off postproc");
|
||||
} else if(frame_cnt%30 == 16) {
|
||||
vp8_postproc_cfg_t pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE, 4, 0};
|
||||
|
||||
if(vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn on postproc");
|
||||
};
|
||||
#endif
|
||||
/* Decode the frame with 15ms deadline */
|
||||
if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 15000))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
/* Write decoded data to disk */
|
||||
while((img = vpx_codec_get_frame(&codec, &iter))) {
|
||||
unsigned int plane, y;
|
||||
|
||||
for(plane=0; plane < 3; plane++) {
|
||||
unsigned char *buf =img->planes[plane];
|
||||
|
||||
for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
|
||||
(void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
|
||||
outfile);
|
||||
buf += img->stride[plane];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Processed %d frames.\n",frame_cnt);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,123 +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 <assert.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../vp9/encoder/vp9_resize.h"
|
||||
|
||||
static const char *exec_name = NULL;
|
||||
|
||||
static void usage() {
|
||||
printf("Usage:\n");
|
||||
printf("%s <input_yuv> <width>x<height> <target_width>x<target_height> ",
|
||||
exec_name);
|
||||
printf("<output_yuv> [<frames>]\n");
|
||||
}
|
||||
|
||||
void usage_exit(void) {
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
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;
|
||||
*width = atoi(v);
|
||||
*height = atoi(&x[1]);
|
||||
if (*width <= 0 || *height <= 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *fin, *fout;
|
||||
FILE *fpin, *fpout;
|
||||
uint8_t *inbuf, *outbuf;
|
||||
uint8_t *inbuf_u, *outbuf_u;
|
||||
uint8_t *inbuf_v, *outbuf_v;
|
||||
int f, frames;
|
||||
int width, height, target_width, target_height;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc < 5) {
|
||||
printf("Incorrect parameters:\n");
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
fin = argv[1];
|
||||
fout = argv[4];
|
||||
if (!parse_dim(argv[2], &width, &height)) {
|
||||
printf("Incorrect parameters: %s\n", argv[2]);
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
if (!parse_dim(argv[3], &target_width, &target_height)) {
|
||||
printf("Incorrect parameters: %s\n", argv[3]);
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
fpin = fopen(fin, "rb");
|
||||
if (fpin == NULL) {
|
||||
printf("Can't open file %s to read\n", fin);
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
fpout = fopen(fout, "wb");
|
||||
if (fpout == NULL) {
|
||||
printf("Can't open file %s to write\n", fout);
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
if (argc >= 6)
|
||||
frames = atoi(argv[5]);
|
||||
else
|
||||
frames = INT_MAX;
|
||||
|
||||
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_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);
|
||||
fwrite(outbuf, target_width * target_height * 3 / 2, 1, fpout);
|
||||
f++;
|
||||
}
|
||||
printf("%d frames processed\n", f);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
|
||||
free(inbuf);
|
||||
free(outbuf);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// VP8 Set Active and ROI Maps
|
||||
// ===========================
|
||||
//
|
||||
// This is an example demonstrating how to control the VP8 encoder's
|
||||
// ROI and Active maps.
|
||||
//
|
||||
// ROI (Reigon of Interest) maps are a way for the application to assign
|
||||
// each macroblock in the image to a region, and then set quantizer and
|
||||
// filtering parameters on that image.
|
||||
//
|
||||
// Active maps are a way for the application to specify on a
|
||||
// macroblock-by-macroblock basis whether there is any activity in that
|
||||
// macroblock.
|
||||
//
|
||||
//
|
||||
// Configuration
|
||||
// -------------
|
||||
// An ROI map is set on frame 22. If the width of the image in macroblocks
|
||||
// is evenly divisble by 4, then the output will appear to have distinct
|
||||
// columns, where the quantizer, loopfilter, and static threshold differ
|
||||
// from column to column.
|
||||
//
|
||||
// An active map is set on frame 33. If the width of the image in macroblocks
|
||||
// is evenly divisble by 4, then the output will appear to have distinct
|
||||
// columns, where one column will have motion and the next will not.
|
||||
//
|
||||
// The active map is cleared on frame 44.
|
||||
//
|
||||
// Observing The Effects
|
||||
// ---------------------
|
||||
// Use the `simple_decoder` example to decode this sample, and observe
|
||||
// the change in the image at frames 22, 33, and 44.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void set_roi_map(const vpx_codec_enc_cfg_t *cfg,
|
||||
vpx_codec_ctx_t *codec) {
|
||||
unsigned int i;
|
||||
vpx_roi_map_t roi;
|
||||
memset(&roi, 0, sizeof(roi));
|
||||
|
||||
roi.rows = (cfg->g_h + 15) / 16;
|
||||
roi.cols = (cfg->g_w + 15) / 16;
|
||||
|
||||
roi.delta_q[0] = 0;
|
||||
roi.delta_q[1] = -2;
|
||||
roi.delta_q[2] = -4;
|
||||
roi.delta_q[3] = -6;
|
||||
|
||||
roi.delta_lf[0] = 0;
|
||||
roi.delta_lf[1] = 1;
|
||||
roi.delta_lf[2] = 2;
|
||||
roi.delta_lf[3] = 3;
|
||||
|
||||
roi.static_threshold[0] = 1500;
|
||||
roi.static_threshold[1] = 1000;
|
||||
roi.static_threshold[2] = 500;
|
||||
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;
|
||||
|
||||
if (vpx_codec_control(codec, VP8E_SET_ROI_MAP, &roi))
|
||||
die_codec(codec, "Failed to set ROI map");
|
||||
|
||||
free(roi.roi_map);
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
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;
|
||||
|
||||
if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map))
|
||||
die_codec(codec, "Failed to set active map");
|
||||
|
||||
free(map.active_map);
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
map.rows = (cfg->g_h + 15) / 16;
|
||||
map.cols = (cfg->g_w + 15) / 16;
|
||||
map.active_map = NULL;
|
||||
|
||||
if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map))
|
||||
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) {
|
||||
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");
|
||||
|
||||
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,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
}
|
||||
|
||||
printf(keyframe ? "K" : ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
return got_pkts;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info;
|
||||
VpxVideoWriter *writer = NULL;
|
||||
const VpxInterface *encoder = NULL;
|
||||
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");
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
encoder = get_vpx_encoder_by_name(argv[1]);
|
||||
if (encoder == NULL) {
|
||||
die("Unsupported codec.");
|
||||
}
|
||||
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.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(&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.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 (!(infile = fopen(argv[4], "rb")))
|
||||
die("Failed to open %s for reading.", argv[4]);
|
||||
|
||||
if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
// Encode frames.
|
||||
while (vpx_img_read(&raw, infile)) {
|
||||
++frame_count;
|
||||
|
||||
if (frame_count == 22 && encoder->fourcc == VP8_FOURCC) {
|
||||
set_roi_map(&cfg, &codec);
|
||||
} else if (frame_count == 33) {
|
||||
set_active_map(&cfg, &codec);
|
||||
} else if (frame_count == 44) {
|
||||
unset_active_map(&cfg, &codec);
|
||||
}
|
||||
|
||||
encode_frame(&codec, &raw, frame_count, writer);
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
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.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
// Simple Decoder
|
||||
// ==============
|
||||
//
|
||||
@@ -28,29 +29,30 @@
|
||||
// -----------------
|
||||
// For decoders, you only have to include `vpx_decoder.h` and then any
|
||||
// header files for the specific codecs you use. In this case, we're using
|
||||
// vp8.
|
||||
// vp8. The `VPX_CODEC_DISABLE_COMPAT` macro can be defined to ensure
|
||||
// strict compliance with the latest SDK by disabling some backwards
|
||||
// compatibility features. Defining this macro is encouraged.
|
||||
//
|
||||
// Initializing The Codec
|
||||
// ----------------------
|
||||
// The libvpx decoder is initialized by the call to vpx_codec_dec_init().
|
||||
// Determining the codec interface to use is handled by VpxVideoReader and the
|
||||
// functions prefixed with vpx_video_reader_. Discussion of those functions is
|
||||
// beyond the scope of this example, but the main gist is to open the input file
|
||||
// and parse just enough of it to determine if it's a VPx file and which VPx
|
||||
// codec is contained within the file.
|
||||
// Note the NULL pointer passed to vpx_codec_dec_init(). We do that in this
|
||||
// example because we want the algorithm to determine the stream configuration
|
||||
// (width/height) and allocate memory automatically.
|
||||
// The decoder is initialized by the following code. This is an example for
|
||||
// the VP8 decoder, but the code is analogous for all algorithms. Replace
|
||||
// `vpx_codec_vp8_dx()` with a pointer to the interface exposed by the
|
||||
// algorithm you want to use. The `cfg` argument is left as NULL in this
|
||||
// example, because we want the algorithm to determine the stream
|
||||
// configuration (width/height) and allocate memory automatically. This
|
||||
// parameter is generally only used if you need to preallocate memory,
|
||||
// particularly in External Memory Allocation mode.
|
||||
//
|
||||
// Decoding A Frame
|
||||
// ----------------
|
||||
// Once the frame has been read into memory, it is decoded using the
|
||||
// `vpx_codec_decode` function. The call takes a pointer to the data
|
||||
// (`frame`) and the length of the data (`frame_size`). No application data
|
||||
// (`frame`) and the length of the data (`frame_sz`). No application data
|
||||
// is associated with the frame in this example, so the `user_priv`
|
||||
// parameter is NULL. The `deadline` parameter is left at zero for this
|
||||
// example. This parameter is generally only used when doing adaptive post
|
||||
// processing.
|
||||
// example. This parameter is generally only used when doing adaptive
|
||||
// postprocessing.
|
||||
//
|
||||
// Codecs may produce a variable number of output frames for every call to
|
||||
// `vpx_codec_decode`. These frames are retrieved by the
|
||||
@@ -72,78 +74,113 @@
|
||||
// --------------
|
||||
// This example does not special case any error return codes. If there was
|
||||
// an error, a descriptive message is printed and the program exits. With
|
||||
// few exceptions, vpx_codec functions return an enumerated error status,
|
||||
// few exeptions, vpx_codec functions return an enumerated error status,
|
||||
// with the value `0` indicating success.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vpx/vpx_decoder.h"
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_reader.h"
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#define interface (vpx_codec_vp8_dx())
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static unsigned int mem_get_le32(const unsigned char *mem) {
|
||||
return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int frame_cnt = 0;
|
||||
FILE *outfile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxInterface *decoder = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
unsigned char file_hdr[IVF_FILE_HDR_SZ];
|
||||
unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
|
||||
unsigned char frame[256*1024];
|
||||
vpx_codec_err_t res;
|
||||
|
||||
exec_name = argv[0];
|
||||
(void)res;
|
||||
/* Open files */
|
||||
if(argc!=3)
|
||||
die("Usage: %s <infile> <outfile>\n", argv[0]);
|
||||
if(!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
if(!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
|
||||
if (argc != 3) die("Invalid number of arguments.");
|
||||
/* Read file header */
|
||||
if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
|
||||
&& file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
|
||||
&& file_hdr[3]=='F'))
|
||||
die("%s is not an IVF file.", argv[1]);
|
||||
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_dec_init(&codec, interface, NULL, flags))
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
/* Read each frame */
|
||||
while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
|
||||
int frame_sz = mem_get_le32(frame_hdr);
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img;
|
||||
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
frame_cnt++;
|
||||
if(frame_sz > sizeof(frame))
|
||||
die("Frame %d data too big for example code buffer", frame_sz);
|
||||
if(fread(frame, 1, frame_sz, infile) != frame_sz)
|
||||
die("Frame %d failed to read complete frame", frame_cnt);
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
|
||||
/* Decode the frame */
|
||||
if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
|
||||
die_codec(&codec, "Failed to initialize decoder.");
|
||||
/* Write decoded data to disk */
|
||||
while((img = vpx_codec_get_frame(&codec, &iter))) {
|
||||
unsigned int plane, y;
|
||||
|
||||
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);
|
||||
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame.");
|
||||
for(plane=0; plane < 3; plane++) {
|
||||
unsigned char *buf =img->planes[plane];
|
||||
|
||||
while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
|
||||
vpx_img_write(img, outfile);
|
||||
++frame_cnt;
|
||||
for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
|
||||
(void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
|
||||
outfile);
|
||||
buf += img->stride[plane];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Processed %d frames.\n",frame_cnt);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
||||
vpx_video_reader_close(reader);
|
||||
|
||||
fclose(outfile);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -28,13 +28,15 @@
|
||||
// -----------------
|
||||
// For encoders, you only have to include `vpx_encoder.h` and then any
|
||||
// header files for the specific codecs you use. In this case, we're using
|
||||
// vp8.
|
||||
// vp8. The `VPX_CODEC_DISABLE_COMPAT` macro can be defined to ensure
|
||||
// strict compliance with the latest SDK by disabling some backwards
|
||||
// compatibility features. Defining this macro is encouraged.
|
||||
//
|
||||
// Getting The Default Configuration
|
||||
// ---------------------------------
|
||||
// Encoders have the notion of "usage profiles." For example, an encoder
|
||||
// may want to publish default configurations for both a video
|
||||
// conferencing application and a best quality offline encoder. These
|
||||
// conferencing appliction and a best quality offline encoder. These
|
||||
// obviously have very different default settings. Consult the
|
||||
// documentation for your codec to see if it provides any default
|
||||
// configurations. All codecs provide a default configuration, number 0,
|
||||
@@ -62,15 +64,6 @@
|
||||
// frame is shown for one frame-time in duration. The flags parameter is
|
||||
// unused in this example. The deadline is set to VPX_DL_REALTIME to
|
||||
// make the example run as quickly as possible.
|
||||
|
||||
// Forced Keyframes
|
||||
// ----------------
|
||||
// Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the
|
||||
// flags passed to `vpx_codec_control()`. In this example, we force a
|
||||
// keyframe every <keyframe-interval> frames. Note, the output stream can
|
||||
// contain additional keyframes beyond those that have been forced using the
|
||||
// VPX_EFLAG_FORCE_KF flag because of automatic keyframe placement by the
|
||||
// encoder.
|
||||
//
|
||||
// Processing The Encoded Data
|
||||
// ---------------------------
|
||||
@@ -87,161 +80,197 @@
|
||||
// an error, a descriptive message is printed and the program exits. With
|
||||
// few exeptions, vpx_codec functions return an enumerated error status,
|
||||
// with the value `0` indicating success.
|
||||
//
|
||||
// Error Resiliency Features
|
||||
// -------------------------
|
||||
// Error resiliency is controlled by the g_error_resilient member of the
|
||||
// configuration structure. Use the `decode_with_drops` example to decode with
|
||||
// frames 5-10 dropped. Compare the output for a file encoded with this example
|
||||
// versus one encoded with the `simple_encoder` example.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
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",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
static void mem_put_le16(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
}
|
||||
|
||||
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");
|
||||
static void mem_put_le32(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
mem[2] = val>>16;
|
||||
mem[3] = val>>24;
|
||||
}
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
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,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
}
|
||||
printf(keyframe ? "K" : ".");
|
||||
fflush(stdout);
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w*img->h*3/2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if(nbytes != to_read) {
|
||||
res = 0;
|
||||
if(nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
}
|
||||
}
|
||||
|
||||
return got_pkts;
|
||||
return res;
|
||||
}
|
||||
|
||||
static void write_ivf_file_header(FILE *outfile,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
||||
return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header+4, 0); /* version */
|
||||
mem_put_le16(header+6, 32); /* headersize */
|
||||
mem_put_le32(header+8, fourcc); /* headersize */
|
||||
mem_put_le16(header+12, cfg->g_w); /* width */
|
||||
mem_put_le16(header+14, cfg->g_h); /* height */
|
||||
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header+24, frame_cnt); /* length */
|
||||
mem_put_le32(header+28, 0); /* unused */
|
||||
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
||||
return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header+4, pts&0xFFFFFFFF);
|
||||
mem_put_le32(header+8, pts >> 32);
|
||||
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
// 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;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info = { 0, 0, 0, { 0, 0 } };
|
||||
VpxVideoWriter *writer = NULL;
|
||||
const VpxInterface *encoder = NULL;
|
||||
const int fps = 30;
|
||||
const int bitrate = 200;
|
||||
int keyframe_interval = 0;
|
||||
int max_frames = 0;
|
||||
int frames_encoded = 0;
|
||||
const char *codec_arg = NULL;
|
||||
const char *width_arg = NULL;
|
||||
const char *height_arg = NULL;
|
||||
const char *infile_arg = NULL;
|
||||
const char *outfile_arg = NULL;
|
||||
const char *keyframe_interval_arg = NULL;
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
long width;
|
||||
long height;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
|
||||
exec_name = argv[0];
|
||||
/* Open files */
|
||||
if(argc!=5)
|
||||
die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
|
||||
die("Faile to allocate image", width, height);
|
||||
if(!(outfile = fopen(argv[4], "wb")))
|
||||
die("Failed to open %s for writing", argv[4]);
|
||||
|
||||
if (argc != 9) die("Invalid number of arguments");
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
|
||||
codec_arg = argv[1];
|
||||
width_arg = argv[2];
|
||||
height_arg = argv[3];
|
||||
infile_arg = argv[4];
|
||||
outfile_arg = argv[5];
|
||||
keyframe_interval_arg = argv[6];
|
||||
max_frames = (int)strtol(argv[8], NULL, 0);
|
||||
/* Populate encoder configuration */
|
||||
res = vpx_codec_enc_config_default(interface, &cfg, 0);
|
||||
if(res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
encoder = get_vpx_encoder_by_name(codec_arg);
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
/* Update the default configuration with our settings */
|
||||
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
|
||||
/ cfg.g_w / cfg.g_h;
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
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;
|
||||
write_ivf_file_header(outfile, &cfg, 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)) {
|
||||
die("Failed to allocate image.");
|
||||
}
|
||||
/* Open input file for this encoding pass */
|
||||
if(!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
|
||||
keyframe_interval = (int)strtol(keyframe_interval_arg, NULL, 0);
|
||||
if (keyframe_interval < 0) die("Invalid keyframe interval value.");
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
while(frame_avail || got_data) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&codec, "Failed to get default codec config.");
|
||||
frame_avail = read_frame(infile, &raw);
|
||||
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
|
||||
1, flags, VPX_DL_REALTIME))
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
got_data = 0;
|
||||
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch(pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
(void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
|
||||
outfile);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
|
||||
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
|
||||
fflush(stdout);
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
|
||||
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);
|
||||
printf("Processed %d frames.\n",frame_cnt-1);
|
||||
vpx_img_free(&raw);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
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(&codec, encoder->codec_interface(), &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
// Encode frames.
|
||||
while (vpx_img_read(&raw, infile)) {
|
||||
int flags = 0;
|
||||
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)) {
|
||||
}
|
||||
|
||||
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.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@
|
||||
// Encoding A Frame
|
||||
// ----------------
|
||||
// Encoding a frame in two pass mode is identical to the simple encoder
|
||||
// example. To increase the quality while sacrificing encoding speed,
|
||||
// VPX_DL_BEST_QUALITY can be used in place of VPX_DL_GOOD_QUALITY.
|
||||
// example, except the deadline is set to VPX_DL_BEST_QUALITY to get the
|
||||
// best quality possible. VPX_DL_GOOD_QUALITY could also be used.
|
||||
//
|
||||
//
|
||||
// Processing Statistics Packets
|
||||
// -----------------------------
|
||||
@@ -49,208 +50,218 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <codec> <width> <height> <infile> <outfile> "
|
||||
"<frame limit>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
static void mem_put_le16(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
}
|
||||
|
||||
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.");
|
||||
static void mem_put_le32(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
mem[2] = val>>16;
|
||||
mem[3] = val>>24;
|
||||
}
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
if (pkt->kind == VPX_CODEC_STATS_PKT) {
|
||||
const uint8_t *const pkt_buf = pkt->data.twopass_stats.buf;
|
||||
const size_t pkt_size = pkt->data.twopass_stats.sz;
|
||||
stats->buf = realloc(stats->buf, stats->sz + pkt_size);
|
||||
memcpy((uint8_t *)stats->buf + stats->sz, pkt_buf, pkt_size);
|
||||
stats->sz += pkt_size;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w*img->h*3/2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if(nbytes != to_read) {
|
||||
res = 0;
|
||||
if(nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
}
|
||||
}
|
||||
|
||||
return got_pkts;
|
||||
return res;
|
||||
}
|
||||
|
||||
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.");
|
||||
static void write_ivf_file_header(FILE *outfile,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(ctx, &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(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
||||
return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header+4, 0); /* version */
|
||||
mem_put_le16(header+6, 32); /* headersize */
|
||||
mem_put_le32(header+8, fourcc); /* headersize */
|
||||
mem_put_le16(header+12, cfg->g_w); /* width */
|
||||
mem_put_le16(header+14, cfg->g_h); /* height */
|
||||
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header+24, frame_cnt); /* length */
|
||||
mem_put_le32(header+28, 0); /* unused */
|
||||
|
||||
if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts))
|
||||
die_codec(ctx, "Failed to write compressed frame.");
|
||||
printf(keyframe ? "K" : ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
return got_pkts;
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
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) {
|
||||
vpx_codec_ctx_t codec;
|
||||
int frame_count = 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");
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
// Calculate frame statistics.
|
||||
while (vpx_img_read(raw, 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;
|
||||
}
|
||||
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
||||
return;
|
||||
|
||||
// Flush encoder.
|
||||
while (get_frame_stats(&codec, NULL, frame_count, 1, 0, VPX_DL_GOOD_QUALITY,
|
||||
&stats)) {
|
||||
}
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header+4, pts&0xFFFFFFFF);
|
||||
mem_put_le32(header+8, pts >> 32);
|
||||
|
||||
printf("Pass 0 complete. Processed %d frames.\n", frame_count);
|
||||
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 } };
|
||||
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 (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
// Encode frames.
|
||||
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)) {
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
printf("Pass 1 complete. Processed %d frames.\n", frame_count);
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile = NULL;
|
||||
int w, h;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
vpx_fixed_buf_t stats;
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
long width;
|
||||
long height;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
int pass;
|
||||
vpx_fixed_buf_t stats = {0};
|
||||
|
||||
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 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];
|
||||
/* Open files */
|
||||
if(argc!=5)
|
||||
die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
|
||||
die("Faile to allocate image", width, height);
|
||||
if(!(outfile = fopen(argv[4], "wb")))
|
||||
die("Failed to open %s for writing", argv[4]);
|
||||
|
||||
if (argc != 7) die("Invalid number of arguments.");
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
|
||||
max_frames = (int)strtol(argv[6], NULL, 0);
|
||||
/* Populate encoder configuration */
|
||||
res = vpx_codec_enc_config_default(interface, &cfg, 0);
|
||||
if(res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
encoder = get_vpx_encoder_by_name(codec_arg);
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
/* Update the default configuration with our settings */
|
||||
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
|
||||
/ cfg.g_w / cfg.g_h;
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
w = (int)strtol(width_arg, NULL, 0);
|
||||
h = (int)strtol(height_arg, NULL, 0);
|
||||
write_ivf_file_header(outfile, &cfg, 0);
|
||||
|
||||
if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0)
|
||||
die("Invalid frame size: %dx%d", w, h);
|
||||
for(pass=0; pass<2; pass++) {
|
||||
frame_cnt = 0;
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, w, h, 1))
|
||||
die("Failed to allocate image", w, h);
|
||||
if(pass == 0)
|
||||
cfg.g_pass = VPX_RC_FIRST_PASS;
|
||||
else {
|
||||
cfg.g_pass = VPX_RC_LAST_PASS;
|
||||
cfg.rc_twopass_stats_in = stats;
|
||||
}
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
|
||||
/* Open input file for this encoding pass */
|
||||
if(!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
|
||||
// Configuration
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) die_codec(&codec, "Failed to get default codec config.");
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
cfg.g_w = w;
|
||||
cfg.g_h = h;
|
||||
cfg.g_timebase.num = 1;
|
||||
cfg.g_timebase.den = fps;
|
||||
cfg.rc_target_bitrate = bitrate;
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
while(frame_avail || got_data) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
if (!(infile = fopen(infile_arg, "rb")))
|
||||
die("Failed to open %s for reading", infile_arg);
|
||||
frame_avail = read_frame(infile, &raw);
|
||||
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
|
||||
1, flags, VPX_DL_BEST_QUALITY))
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
got_data = 0;
|
||||
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch(pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
(void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
|
||||
outfile);
|
||||
break;
|
||||
case VPX_CODEC_STATS_PKT:
|
||||
stats.buf = realloc(stats.buf, stats.sz
|
||||
+ pkt->data.twopass_stats.sz);
|
||||
if(!stats.buf)
|
||||
die("Memory reallocation failed.\n");
|
||||
memcpy((char*)stats.buf + stats.sz,
|
||||
pkt->data.twopass_stats.buf,
|
||||
pkt->data.twopass_stats.sz);
|
||||
stats.sz += pkt->data.twopass_stats.sz;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
|
||||
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
|
||||
fflush(stdout);
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
printf("Pass %d complete.\n", pass+1);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
}
|
||||
|
||||
// Pass 0
|
||||
cfg.g_pass = VPX_RC_FIRST_PASS;
|
||||
stats = pass0(&raw, infile, encoder, &cfg, max_frames);
|
||||
printf("Processed %d frames.\n",frame_cnt-1);
|
||||
vpx_img_free(&raw);
|
||||
free(stats.buf);
|
||||
|
||||
// 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);
|
||||
free(stats.buf);
|
||||
|
||||
vpx_img_free(&raw);
|
||||
fclose(infile);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,666 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an example demonstrating multi-resolution encoding in VP8.
|
||||
* High-resolution input video is down-sampled to lower-resolutions. The
|
||||
* encoder then encodes the video and outputs multiple bitstreams with
|
||||
* different resolutions.
|
||||
*
|
||||
* This test also allows for settings temporal layers for each spatial layer.
|
||||
* Different number of temporal layers per spatial stream may be used.
|
||||
* Currently up to 3 temporal layers per spatial stream (encoder) are supported
|
||||
* in this test.
|
||||
*/
|
||||
|
||||
#include "./vpx_config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include "vpx_ports/vpx_timer.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx_ports/mem_ops.h"
|
||||
#include "../tools_common.h"
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
void usage_exit(void) { exit(EXIT_FAILURE); }
|
||||
|
||||
/*
|
||||
* The input video frame is downsampled several times to generate a multi-level
|
||||
* hierarchical structure. NUM_ENCODERS is defined as the number of encoding
|
||||
* levels required. For example, if the size of input video is 1280x720,
|
||||
* NUM_ENCODERS is 3, and down-sampling factor is 2, the encoder outputs 3
|
||||
* bitstreams with resolution of 1280x720(level 0), 640x360(level 1), and
|
||||
* 320x180(level 2) respectively.
|
||||
*/
|
||||
|
||||
/* Number of encoders (spatial resolutions) used in this test. */
|
||||
#define NUM_ENCODERS 3
|
||||
|
||||
/* Maximum number of temporal layers allowed for this test. */
|
||||
#define MAX_NUM_TEMPORAL_LAYERS 3
|
||||
|
||||
/* This example uses the scaler function in libyuv. */
|
||||
#include "third_party/libyuv/include/libyuv/basic_types.h"
|
||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||
#include "third_party/libyuv/include/libyuv/cpu_id.h"
|
||||
|
||||
int (*read_frame_p)(FILE *f, vpx_image_t *img);
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w * img->h * 3 / 2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if (nbytes != to_read) {
|
||||
res = 0;
|
||||
if (nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int read_frame_by_row(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
int plane;
|
||||
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
unsigned char *ptr;
|
||||
int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
|
||||
int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
|
||||
int r;
|
||||
|
||||
/* Determine the correct plane based on the image format. The for-loop
|
||||
* always counts in Y,U,V order, but this may not match the order of
|
||||
* the data on disk.
|
||||
*/
|
||||
switch (plane) {
|
||||
case 1:
|
||||
ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V
|
||||
: VPX_PLANE_U];
|
||||
break;
|
||||
case 2:
|
||||
ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U
|
||||
: VPX_PLANE_V];
|
||||
break;
|
||||
default: ptr = img->planes[plane];
|
||||
}
|
||||
|
||||
for (r = 0; r < h; r++) {
|
||||
to_read = w;
|
||||
|
||||
nbytes = fread(ptr, 1, to_read, f);
|
||||
if (nbytes != to_read) {
|
||||
res = 0;
|
||||
if (nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += img->stride[plane];
|
||||
}
|
||||
if (!res) break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void write_ivf_file_header(FILE *outfile, const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS) return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header + 4, 0); /* version */
|
||||
mem_put_le16(header + 6, 32); /* headersize */
|
||||
mem_put_le32(header + 8, fourcc); /* headersize */
|
||||
mem_put_le16(header + 12, cfg->g_w); /* width */
|
||||
mem_put_le16(header + 14, cfg->g_h); /* height */
|
||||
mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header + 24, frame_cnt); /* length */
|
||||
mem_put_le32(header + 28, 0); /* unused */
|
||||
|
||||
(void)fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt) {
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, (int)pkt->data.frame.sz);
|
||||
mem_put_le32(header + 4, pts & 0xFFFFFFFF);
|
||||
mem_put_le32(header + 8, pts >> 32);
|
||||
|
||||
(void)fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
/* Temporal scaling parameters */
|
||||
/* This sets all the temporal layer parameters given |num_temporal_layers|,
|
||||
* including the target bit allocation across temporal layers. Bit allocation
|
||||
* parameters will be passed in as user parameters in another version.
|
||||
*/
|
||||
static void set_temporal_layer_pattern(int num_temporal_layers,
|
||||
vpx_codec_enc_cfg_t *cfg, int bitrate,
|
||||
int *layer_flags) {
|
||||
assert(num_temporal_layers <= MAX_NUM_TEMPORAL_LAYERS);
|
||||
switch (num_temporal_layers) {
|
||||
case 1: {
|
||||
/* 1-layer */
|
||||
cfg->ts_number_layers = 1;
|
||||
cfg->ts_periodicity = 1;
|
||||
cfg->ts_rate_decimator[0] = 1;
|
||||
cfg->ts_layer_id[0] = 0;
|
||||
cfg->ts_target_bitrate[0] = bitrate;
|
||||
|
||||
// Update L only.
|
||||
layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
/* 2-layers, with sync point at first frame of layer 1. */
|
||||
cfg->ts_number_layers = 2;
|
||||
cfg->ts_periodicity = 2;
|
||||
cfg->ts_rate_decimator[0] = 2;
|
||||
cfg->ts_rate_decimator[1] = 1;
|
||||
cfg->ts_layer_id[0] = 0;
|
||||
cfg->ts_layer_id[1] = 1;
|
||||
// Use 60/40 bit allocation as example.
|
||||
cfg->ts_target_bitrate[0] = (int)(0.6f * bitrate);
|
||||
cfg->ts_target_bitrate[1] = bitrate;
|
||||
|
||||
/* 0=L, 1=GF */
|
||||
// ARF is used as predictor for all frames, and is only updated on
|
||||
// key frame. Sync point every 8 frames.
|
||||
|
||||
// Layer 0: predict from L and ARF, update L and G.
|
||||
layer_flags[0] = 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 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 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;
|
||||
|
||||
// Layer 0
|
||||
layer_flags[4] = layer_flags[2];
|
||||
|
||||
// Layer 1
|
||||
layer_flags[5] = layer_flags[3];
|
||||
|
||||
// Layer 0
|
||||
layer_flags[6] = layer_flags[4];
|
||||
|
||||
// Layer 1
|
||||
layer_flags[7] = layer_flags[5];
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
default: {
|
||||
// 3-layers structure where ARF is used as predictor for all frames,
|
||||
// and is only updated on key frame.
|
||||
// Sync points for layer 1 and 2 every 8 frames.
|
||||
cfg->ts_number_layers = 3;
|
||||
cfg->ts_periodicity = 4;
|
||||
cfg->ts_rate_decimator[0] = 4;
|
||||
cfg->ts_rate_decimator[1] = 2;
|
||||
cfg->ts_rate_decimator[2] = 1;
|
||||
cfg->ts_layer_id[0] = 0;
|
||||
cfg->ts_layer_id[1] = 2;
|
||||
cfg->ts_layer_id[2] = 1;
|
||||
cfg->ts_layer_id[3] = 2;
|
||||
// Use 45/20/35 bit allocation as example.
|
||||
cfg->ts_target_bitrate[0] = (int)(0.45f * bitrate);
|
||||
cfg->ts_target_bitrate[1] = (int)(0.65f * bitrate);
|
||||
cfg->ts_target_bitrate[2] = bitrate;
|
||||
|
||||
/* 0=L, 1=GF, 2=ARF */
|
||||
|
||||
// Layer 0: predict from L and ARF; update L and G.
|
||||
layer_flags[0] = 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;
|
||||
|
||||
// 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 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;
|
||||
|
||||
// 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 2: predict from L, G, ARF; update none.
|
||||
layer_flags[5] = layer_flags[3];
|
||||
|
||||
// Layer 1: predict from L, G, ARF; update G.
|
||||
layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
|
||||
// Layer 2: predict from L, G, ARF; update none.
|
||||
layer_flags[7] = layer_flags[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The periodicity of the pattern given the number of temporal layers. */
|
||||
static int periodicity_to_num_layers[MAX_NUM_TEMPORAL_LAYERS] = { 1, 8, 8 };
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile[NUM_ENCODERS];
|
||||
FILE *downsampled_input[NUM_ENCODERS - 1];
|
||||
char filename[50];
|
||||
vpx_codec_ctx_t codec[NUM_ENCODERS];
|
||||
vpx_codec_enc_cfg_t cfg[NUM_ENCODERS];
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw[NUM_ENCODERS];
|
||||
vpx_codec_err_t res[NUM_ENCODERS];
|
||||
|
||||
int i;
|
||||
int width;
|
||||
int height;
|
||||
int length_frame;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
int layer_id = 0;
|
||||
|
||||
int layer_flags[VPX_TS_MAX_PERIODICITY * NUM_ENCODERS] = { 0 };
|
||||
int flag_periodicity;
|
||||
|
||||
/*Currently, only realtime mode is supported in multi-resolution encoding.*/
|
||||
int arg_deadline = VPX_DL_REALTIME;
|
||||
|
||||
/* Set show_psnr to 1/0 to show/not show PSNR. Choose show_psnr=0 if you
|
||||
don't need to know PSNR, which will skip PSNR calculation and save
|
||||
encoding time. */
|
||||
int show_psnr = 0;
|
||||
int key_frame_insert = 0;
|
||||
uint64_t psnr_sse_total[NUM_ENCODERS] = { 0 };
|
||||
uint64_t psnr_samples_total[NUM_ENCODERS] = { 0 };
|
||||
double psnr_totals[NUM_ENCODERS][4] = { { 0, 0 } };
|
||||
int psnr_count[NUM_ENCODERS] = { 0 };
|
||||
|
||||
int64_t cx_time = 0;
|
||||
|
||||
/* Set the required target bitrates for each resolution level.
|
||||
* If target bitrate for highest-resolution level is set to 0,
|
||||
* (i.e. target_bitrate[0]=0), we skip encoding at that level.
|
||||
*/
|
||||
unsigned int target_bitrate[NUM_ENCODERS] = { 1000, 500, 100 };
|
||||
|
||||
/* Enter the frame rate of the input video */
|
||||
int framerate = 30;
|
||||
|
||||
/* Set down-sampling factor for each resolution level.
|
||||
dsf[0] controls down sampling from level 0 to level 1;
|
||||
dsf[1] controls down sampling from level 1 to level 2;
|
||||
dsf[2] is not used. */
|
||||
vpx_rational_t dsf[NUM_ENCODERS] = { { 2, 1 }, { 2, 1 }, { 1, 1 } };
|
||||
|
||||
/* Set the number of temporal layers for each encoder/resolution level,
|
||||
* starting from highest resoln down to lowest resoln. */
|
||||
unsigned int num_temporal_layers[NUM_ENCODERS] = { 3, 3, 3 };
|
||||
|
||||
if (argc != (7 + 3 * NUM_ENCODERS))
|
||||
die("Usage: %s <width> <height> <frame_rate> <infile> <outfile(s)> "
|
||||
"<rate_encoder(s)> <temporal_layer(s)> <key_frame_insert> <output "
|
||||
"psnr?> \n",
|
||||
argv[0]);
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(interface));
|
||||
|
||||
width = (int)strtol(argv[1], NULL, 0);
|
||||
height = (int)strtol(argv[2], NULL, 0);
|
||||
framerate = (int)strtol(argv[3], NULL, 0);
|
||||
|
||||
if (width < 16 || width % 2 || height < 16 || height % 2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
|
||||
/* Open input video file for encoding */
|
||||
if (!(infile = fopen(argv[4], "rb")))
|
||||
die("Failed to open %s for reading", argv[4]);
|
||||
|
||||
/* Open output file for each encoder to output bitstreams */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
if (!target_bitrate[i]) {
|
||||
outfile[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(outfile[i] = fopen(argv[i + 5], "wb")))
|
||||
die("Failed to open %s for writing", argv[i + 4]);
|
||||
}
|
||||
|
||||
// Bitrates per spatial layer: overwrite default rates above.
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
target_bitrate[i] = (int)strtol(argv[NUM_ENCODERS + 5 + i], NULL, 0);
|
||||
}
|
||||
|
||||
// Temporal layers per spatial layers: overwrite default settings above.
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
num_temporal_layers[i] =
|
||||
(int)strtol(argv[2 * NUM_ENCODERS + 5 + i], NULL, 0);
|
||||
if (num_temporal_layers[i] < 1 || num_temporal_layers[i] > 3)
|
||||
die("Invalid temporal layers: %d, Must be 1, 2, or 3. \n",
|
||||
num_temporal_layers);
|
||||
}
|
||||
|
||||
/* Open file to write out each spatially downsampled input stream. */
|
||||
for (i = 0; i < NUM_ENCODERS - 1; i++) {
|
||||
// Highest resoln is encoder 0.
|
||||
if (sprintf(filename, "ds%d.yuv", NUM_ENCODERS - i) < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
downsampled_input[i] = fopen(filename, "wb");
|
||||
}
|
||||
|
||||
key_frame_insert = (int)strtol(argv[3 * NUM_ENCODERS + 5], NULL, 0);
|
||||
|
||||
show_psnr = (int)strtol(argv[3 * NUM_ENCODERS + 6], NULL, 0);
|
||||
|
||||
/* Populate default encoder configuration */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
res[i] = vpx_codec_enc_config_default(interface, &cfg[i], 0);
|
||||
if (res[i]) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res[i]));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the default configuration according to needs of the application.
|
||||
*/
|
||||
/* 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;
|
||||
|
||||
/* Disable automatic keyframe placement */
|
||||
/* Note: These 3 settings are copied to all levels. But, except the lowest
|
||||
* resolution level, all other levels are set to VPX_KF_DISABLED internally.
|
||||
*/
|
||||
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[0]; /* Set target bitrate */
|
||||
cfg[0].g_timebase.num = 1; /* Set fps */
|
||||
cfg[0].g_timebase.den = framerate;
|
||||
|
||||
/* Other-resolution encoder settings */
|
||||
for (i = 1; i < NUM_ENCODERS; i++) {
|
||||
memcpy(&cfg[i], &cfg[0], sizeof(vpx_codec_enc_cfg_t));
|
||||
|
||||
cfg[i].rc_target_bitrate = target_bitrate[i];
|
||||
|
||||
/* Note: Width & height of other-resolution encoders are calculated
|
||||
* from the highest-resolution encoder's size and the corresponding
|
||||
* down_sampling_factor.
|
||||
*/
|
||||
{
|
||||
unsigned int iw = cfg[i - 1].g_w * dsf[i - 1].den + dsf[i - 1].num - 1;
|
||||
unsigned int ih = cfg[i - 1].g_h * dsf[i - 1].den + dsf[i - 1].num - 1;
|
||||
cfg[i].g_w = iw / dsf[i - 1].num;
|
||||
cfg[i].g_h = ih / dsf[i - 1].num;
|
||||
}
|
||||
|
||||
/* Make width & height to be multiplier of 2. */
|
||||
// Should support odd size ???
|
||||
if ((cfg[i].g_w) % 2) cfg[i].g_w++;
|
||||
if ((cfg[i].g_h) % 2) cfg[i].g_h++;
|
||||
}
|
||||
|
||||
// Set the number of threads per encode/spatial layer.
|
||||
// (1, 1, 1) means no encoder threading.
|
||||
cfg[0].g_threads = 1;
|
||||
cfg[1].g_threads = 1;
|
||||
cfg[2].g_threads = 1;
|
||||
|
||||
/* Allocate image for each encoder */
|
||||
for (i = 0; i < NUM_ENCODERS; i++)
|
||||
if (!vpx_img_alloc(&raw[i], VPX_IMG_FMT_I420, cfg[i].g_w, cfg[i].g_h, 32))
|
||||
die("Failed to allocate image", cfg[i].g_w, cfg[i].g_h);
|
||||
|
||||
if (raw[0].stride[VPX_PLANE_Y] == (int)raw[0].d_w)
|
||||
read_frame_p = read_frame;
|
||||
else
|
||||
read_frame_p = read_frame_by_row;
|
||||
|
||||
for (i = 0; i < NUM_ENCODERS; i++)
|
||||
if (outfile[i]) write_ivf_file_header(outfile[i], &cfg[i], 0);
|
||||
|
||||
/* Temporal layers settings */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
set_temporal_layer_pattern(num_temporal_layers[i], &cfg[i],
|
||||
cfg[i].rc_target_bitrate,
|
||||
&layer_flags[i * VPX_TS_MAX_PERIODICITY]);
|
||||
}
|
||||
|
||||
/* Initialize multi-encoder */
|
||||
if (vpx_codec_enc_init_multi(&codec[0], interface, &cfg[0], NUM_ENCODERS,
|
||||
(show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[0]))
|
||||
die_codec(&codec[0], "Failed to initialize encoder");
|
||||
|
||||
/* The extra encoding configuration parameters can be set as follows. */
|
||||
/* Set encoding speed */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
int speed = -6;
|
||||
/* Lower speed for the lowest resolution. */
|
||||
if (i == NUM_ENCODERS - 1) speed = -4;
|
||||
if (vpx_codec_control(&codec[i], VP8E_SET_CPUUSED, speed))
|
||||
die_codec(&codec[i], "Failed to set cpu_used");
|
||||
}
|
||||
|
||||
/* Set static threshold = 1 for all encoders */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
if (vpx_codec_control(&codec[i], VP8E_SET_STATIC_THRESHOLD, 1))
|
||||
die_codec(&codec[i], "Failed to set static threshold");
|
||||
}
|
||||
|
||||
/* Set NOISE_SENSITIVITY to do TEMPORAL_DENOISING */
|
||||
/* Enable denoising for the highest-resolution encoder. */
|
||||
if (vpx_codec_control(&codec[0], VP8E_SET_NOISE_SENSITIVITY, 1))
|
||||
die_codec(&codec[0], "Failed to set noise_sensitivity");
|
||||
if (vpx_codec_control(&codec[1], VP8E_SET_NOISE_SENSITIVITY, 1))
|
||||
die_codec(&codec[1], "Failed to set noise_sensitivity");
|
||||
for (i = 2; i < NUM_ENCODERS; i++) {
|
||||
if (vpx_codec_control(&codec[i], VP8E_SET_NOISE_SENSITIVITY, 0))
|
||||
die_codec(&codec[i], "Failed to set noise_sensitivity");
|
||||
}
|
||||
|
||||
/* Set the number of token partitions */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
if (vpx_codec_control(&codec[i], VP8E_SET_TOKEN_PARTITIONS, 1))
|
||||
die_codec(&codec[i], "Failed to set static threshold");
|
||||
}
|
||||
|
||||
/* Set the max intra target bitrate */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
unsigned int max_intra_size_pct =
|
||||
(int)(((double)cfg[0].rc_buf_optimal_sz * 0.5) * framerate / 10);
|
||||
if (vpx_codec_control(&codec[i], VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
||||
max_intra_size_pct))
|
||||
die_codec(&codec[i], "Failed to set static threshold");
|
||||
// printf("%d %d \n",i,max_intra_size_pct);
|
||||
}
|
||||
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
|
||||
while (frame_avail || got_data) {
|
||||
struct vpx_usec_timer timer;
|
||||
vpx_codec_iter_t iter[NUM_ENCODERS] = { NULL };
|
||||
const vpx_codec_cx_pkt_t *pkt[NUM_ENCODERS];
|
||||
|
||||
flags = 0;
|
||||
frame_avail = read_frame_p(infile, &raw[0]);
|
||||
|
||||
if (frame_avail) {
|
||||
for (i = 1; i < NUM_ENCODERS; i++) {
|
||||
/*Scale the image down a number of times by downsampling factor*/
|
||||
/* FilterMode 1 or 2 give better psnr than FilterMode 0. */
|
||||
I420Scale(
|
||||
raw[i - 1].planes[VPX_PLANE_Y], raw[i - 1].stride[VPX_PLANE_Y],
|
||||
raw[i - 1].planes[VPX_PLANE_U], raw[i - 1].stride[VPX_PLANE_U],
|
||||
raw[i - 1].planes[VPX_PLANE_V], raw[i - 1].stride[VPX_PLANE_V],
|
||||
raw[i - 1].d_w, raw[i - 1].d_h, raw[i].planes[VPX_PLANE_Y],
|
||||
raw[i].stride[VPX_PLANE_Y], raw[i].planes[VPX_PLANE_U],
|
||||
raw[i].stride[VPX_PLANE_U], raw[i].planes[VPX_PLANE_V],
|
||||
raw[i].stride[VPX_PLANE_V], raw[i].d_w, raw[i].d_h, 1);
|
||||
/* Write out down-sampled input. */
|
||||
length_frame = cfg[i].g_w * cfg[i].g_h * 3 / 2;
|
||||
if (fwrite(raw[i].planes[0], 1, length_frame,
|
||||
downsampled_input[NUM_ENCODERS - i - 1]) !=
|
||||
(unsigned int)length_frame) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the flags (reference and update) for all the encoders.*/
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
layer_id = cfg[i].ts_layer_id[frame_cnt % cfg[i].ts_periodicity];
|
||||
flags = 0;
|
||||
flag_periodicity = periodicity_to_num_layers[num_temporal_layers[i] - 1];
|
||||
flags = layer_flags[i * VPX_TS_MAX_PERIODICITY +
|
||||
frame_cnt % flag_periodicity];
|
||||
// Key frame flag for first frame.
|
||||
if (frame_cnt == 0) {
|
||||
flags |= VPX_EFLAG_FORCE_KF;
|
||||
}
|
||||
if (frame_cnt > 0 && frame_cnt == key_frame_insert) {
|
||||
flags = VPX_EFLAG_FORCE_KF;
|
||||
}
|
||||
|
||||
vpx_codec_control(&codec[i], VP8E_SET_FRAME_FLAGS, flags);
|
||||
vpx_codec_control(&codec[i], VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
|
||||
}
|
||||
|
||||
/* Encode each frame at multi-levels */
|
||||
/* Note the flags must be set to 0 in the encode call if they are set
|
||||
for each frame with the vpx_codec_control(), as done above. */
|
||||
vpx_usec_timer_start(&timer);
|
||||
if (vpx_codec_encode(&codec[0], frame_avail ? &raw[0] : NULL, frame_cnt, 1,
|
||||
0, arg_deadline)) {
|
||||
die_codec(&codec[0], "Failed to encode frame");
|
||||
}
|
||||
vpx_usec_timer_mark(&timer);
|
||||
cx_time += vpx_usec_timer_elapsed(&timer);
|
||||
|
||||
for (i = NUM_ENCODERS - 1; i >= 0; i--) {
|
||||
got_data = 0;
|
||||
while ((pkt[i] = vpx_codec_get_cx_data(&codec[i], &iter[i]))) {
|
||||
got_data = 1;
|
||||
switch (pkt[i]->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile[i], pkt[i]);
|
||||
(void)fwrite(pkt[i]->data.frame.buf, 1, pkt[i]->data.frame.sz,
|
||||
outfile[i]);
|
||||
break;
|
||||
case VPX_CODEC_PSNR_PKT:
|
||||
if (show_psnr) {
|
||||
int j;
|
||||
|
||||
psnr_sse_total[i] += pkt[i]->data.psnr.sse[0];
|
||||
psnr_samples_total[i] += pkt[i]->data.psnr.samples[0];
|
||||
for (j = 0; j < 4; j++) {
|
||||
psnr_totals[i][j] += pkt[i]->data.psnr.psnr[j];
|
||||
}
|
||||
psnr_count[i]++;
|
||||
}
|
||||
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
fclose(infile);
|
||||
|
||||
printf("Processed %ld frames.\n", (long int)frame_cnt - 1);
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
/* Calculate PSNR and print it out */
|
||||
if ((show_psnr) && (psnr_count[i] > 0)) {
|
||||
int j;
|
||||
double ovpsnr =
|
||||
sse_to_psnr(psnr_samples_total[i], 255.0, psnr_sse_total[i]);
|
||||
|
||||
fprintf(stderr, "\n ENC%d PSNR (Overall/Avg/Y/U/V)", i);
|
||||
|
||||
fprintf(stderr, " %.3lf", ovpsnr);
|
||||
for (j = 0; j < 4; j++) {
|
||||
fprintf(stderr, " %.3lf", psnr_totals[i][j] / psnr_count[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (vpx_codec_destroy(&codec[i]))
|
||||
die_codec(&codec[i], "Failed to destroy codec");
|
||||
|
||||
vpx_img_free(&raw[i]);
|
||||
|
||||
if (!outfile[i]) continue;
|
||||
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if (!fseek(outfile[i], 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile[i], &cfg[i], frame_cnt - 1);
|
||||
fclose(outfile[i]);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
296
examples/vp8_set_maps.c
Normal file
296
examples/vp8_set_maps.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
// VP8 Set Active and ROI Maps
|
||||
// ===========================
|
||||
//
|
||||
// This is an example demonstrating how to control the VP8 encoder's
|
||||
// ROI and Active maps.
|
||||
//
|
||||
// ROI (Reigon of Interest) maps are a way for the application to assign
|
||||
// each macroblock in the image to a region, and then set quantizer and
|
||||
// filtering parameters on that image.
|
||||
//
|
||||
// Active maps are a way for the application to specify on a
|
||||
// macroblock-by-macroblock basis whether there is any activity in that
|
||||
// macroblock.
|
||||
//
|
||||
//
|
||||
// Configuration
|
||||
// -------------
|
||||
// An ROI map is set on frame 22. If the width of the image in macroblocks
|
||||
// is evenly divisble by 4, then the output will appear to have distinct
|
||||
// columns, where the quantizer, loopfilter, and static threshold differ
|
||||
// from column to column.
|
||||
//
|
||||
// An active map is set on frame 33. If the width of the image in macroblocks
|
||||
// is evenly divisble by 4, then the output will appear to have distinct
|
||||
// columns, where one column will have motion and the next will not.
|
||||
//
|
||||
// The active map is cleared on frame 44.
|
||||
//
|
||||
// Observing The Effects
|
||||
// ---------------------
|
||||
// Use the `simple_decoder` example to decode this sample, and observe
|
||||
// the change in the image at frames 22, 33, and 44.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static void mem_put_le16(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
}
|
||||
|
||||
static void mem_put_le32(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
mem[2] = val>>16;
|
||||
mem[3] = val>>24;
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w*img->h*3/2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if(nbytes != to_read) {
|
||||
res = 0;
|
||||
if(nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void write_ivf_file_header(FILE *outfile,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
||||
return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header+4, 0); /* version */
|
||||
mem_put_le16(header+6, 32); /* headersize */
|
||||
mem_put_le32(header+8, fourcc); /* headersize */
|
||||
mem_put_le16(header+12, cfg->g_w); /* width */
|
||||
mem_put_le16(header+14, cfg->g_h); /* height */
|
||||
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header+24, frame_cnt); /* length */
|
||||
mem_put_le32(header+28, 0); /* unused */
|
||||
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
||||
return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header+4, pts&0xFFFFFFFF);
|
||||
mem_put_le32(header+8, pts >> 32);
|
||||
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
long width;
|
||||
long height;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
|
||||
/* Open files */
|
||||
if(argc!=5)
|
||||
die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
|
||||
die("Faile to allocate image", width, height);
|
||||
if(!(outfile = fopen(argv[4], "wb")))
|
||||
die("Failed to open %s for writing", argv[4]);
|
||||
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
|
||||
/* Populate encoder configuration */
|
||||
res = vpx_codec_enc_config_default(interface, &cfg, 0);
|
||||
if(res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Update the default configuration with our settings */
|
||||
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
|
||||
/ cfg.g_w / cfg.g_h;
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
write_ivf_file_header(outfile, &cfg, 0);
|
||||
|
||||
|
||||
/* Open input file for this encoding pass */
|
||||
if(!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
while(frame_avail || got_data) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
if(frame_cnt + 1 == 22) {
|
||||
vpx_roi_map_t roi;
|
||||
int i;
|
||||
|
||||
roi.rows = cfg.g_h/16;
|
||||
roi.cols = cfg.g_w/16;
|
||||
|
||||
roi.delta_q[0] = 0;
|
||||
roi.delta_q[1] = -2;
|
||||
roi.delta_q[2] = -4;
|
||||
roi.delta_q[3] = -6;
|
||||
|
||||
roi.delta_lf[0] = 0;
|
||||
roi.delta_lf[1] = 1;
|
||||
roi.delta_lf[2] = 2;
|
||||
roi.delta_lf[3] = 3;
|
||||
|
||||
roi.static_threshold[0] = 1500;
|
||||
roi.static_threshold[1] = 1000;
|
||||
roi.static_threshold[2] = 500;
|
||||
roi.static_threshold[3] = 0;
|
||||
|
||||
/* generate an ROI map for example */
|
||||
roi.roi_map = malloc(roi.rows * roi.cols);
|
||||
for(i=0;i<roi.rows*roi.cols;i++)
|
||||
roi.roi_map[i] = i & 3;
|
||||
|
||||
if(vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))
|
||||
die_codec(&codec, "Failed to set ROI map");
|
||||
|
||||
free(roi.roi_map);
|
||||
} else if(frame_cnt + 1 == 33) {
|
||||
vpx_active_map_t active;
|
||||
int i;
|
||||
|
||||
active.rows = cfg.g_h/16;
|
||||
active.cols = cfg.g_w/16;
|
||||
|
||||
/* generate active map for example */
|
||||
active.active_map = malloc(active.rows * active.cols);
|
||||
for(i=0;i<active.rows*active.cols;i++)
|
||||
active.active_map[i] = i & 1;
|
||||
|
||||
if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))
|
||||
die_codec(&codec, "Failed to set active map");
|
||||
|
||||
free(active.active_map);
|
||||
} else if(frame_cnt + 1 == 44) {
|
||||
vpx_active_map_t active;
|
||||
|
||||
active.rows = cfg.g_h/16;
|
||||
active.cols = cfg.g_w/16;
|
||||
|
||||
/* pass in null map to disable active_map*/
|
||||
active.active_map = NULL;
|
||||
|
||||
if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))
|
||||
die_codec(&codec, "Failed to set active map");
|
||||
}
|
||||
frame_avail = read_frame(infile, &raw);
|
||||
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
|
||||
1, flags, VPX_DL_REALTIME))
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
got_data = 0;
|
||||
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch(pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
(void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
|
||||
outfile);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
|
||||
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
|
||||
fflush(stdout);
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
|
||||
printf("Processed %d frames.\n",frame_cnt-1);
|
||||
vpx_img_free(&raw);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
// VP8 Set Reference Frame
|
||||
// =======================
|
||||
//
|
||||
@@ -47,141 +48,212 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vpx/vp8cx.h"
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vp8/common/common.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile> <frame>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
static void mem_put_le16(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
}
|
||||
|
||||
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");
|
||||
static void mem_put_le32(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
mem[2] = val>>16;
|
||||
mem[3] = val>>24;
|
||||
}
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
|
||||
got_pkts = 1;
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
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,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf(keyframe ? "K" : ".");
|
||||
fflush(stdout);
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w*img->h*3/2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if(nbytes != to_read) {
|
||||
res = 0;
|
||||
if(nbytes > 0)
|
||||
printf("Warning: Read partial frame. Check your width & height!\n");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
return got_pkts;
|
||||
static void write_ivf_file_header(FILE *outfile,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
||||
return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header+4, 0); /* version */
|
||||
mem_put_le16(header+6, 32); /* headersize */
|
||||
mem_put_le32(header+8, fourcc); /* headersize */
|
||||
mem_put_le16(header+12, cfg->g_w); /* width */
|
||||
mem_put_le16(header+14, cfg->g_h); /* height */
|
||||
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header+24, frame_cnt); /* length */
|
||||
mem_put_le32(header+28, 0); /* unused */
|
||||
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
||||
return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header+4, pts&0xFFFFFFFF);
|
||||
mem_put_le32(header+8, pts >> 32);
|
||||
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info;
|
||||
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
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
long width;
|
||||
long height;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
int update_frame_num = 0;
|
||||
|
||||
vp8_zero(codec);
|
||||
vp8_zero(cfg);
|
||||
vp8_zero(info);
|
||||
/* Open files */
|
||||
if(argc!=6)
|
||||
die("Usage: %s <width> <height> <infile> <outfile> <frame>\n",
|
||||
argv[0]);
|
||||
|
||||
exec_name = argv[0];
|
||||
update_frame_num = atoi(argv[5]);
|
||||
if(!update_frame_num)
|
||||
die("Couldn't parse frame number '%s'\n", argv[5]);
|
||||
|
||||
if (argc != 6) die("Invalid number of arguments");
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
|
||||
die("Faile to allocate image", width, height);
|
||||
if(!(outfile = fopen(argv[4], "wb")))
|
||||
die("Failed to open %s for writing", argv[4]);
|
||||
|
||||
// TODO(dkovalev): add vp9 support and rename the file accordingly
|
||||
encoder = get_vpx_encoder_by_name("vp8");
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
printf("Using %s\n",vpx_codec_iface_name(interface));
|
||||
|
||||
update_frame_num = atoi(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.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(&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;
|
||||
|
||||
writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
|
||||
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]);
|
||||
|
||||
if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
// Encode frames.
|
||||
while (vpx_img_read(&raw, infile)) {
|
||||
if (frame_count + 1 == update_frame_num) {
|
||||
vpx_ref_frame_t ref;
|
||||
ref.frame_type = VP8_LAST_FRAME;
|
||||
ref.img = raw;
|
||||
if (vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref))
|
||||
die_codec(&codec, "Failed to set reference frame");
|
||||
/* Populate encoder configuration */
|
||||
res = vpx_codec_enc_config_default(interface, &cfg, 0);
|
||||
if(res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
encode_frame(&codec, &raw, frame_count++, writer);
|
||||
}
|
||||
/* Update the default configuration with our settings */
|
||||
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
|
||||
/ cfg.g_w / cfg.g_h;
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
// Flush encoder.
|
||||
while (encode_frame(&codec, NULL, -1, writer)) {
|
||||
}
|
||||
write_ivf_file_header(outfile, &cfg, 0);
|
||||
|
||||
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.");
|
||||
/* Open input file for this encoding pass */
|
||||
if(!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
/* Initialize codec */
|
||||
if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
while(frame_avail || got_data) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
frame_avail = read_frame(infile, &raw);
|
||||
|
||||
if(frame_cnt + 1 == update_frame_num) {
|
||||
vpx_ref_frame_t ref;
|
||||
|
||||
ref.frame_type = VP8_LAST_FRAME;
|
||||
ref.img = raw;
|
||||
|
||||
if(vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref))
|
||||
die_codec(&codec, "Failed to set reference frame");
|
||||
}
|
||||
|
||||
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
|
||||
1, flags, VPX_DL_REALTIME))
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
got_data = 0;
|
||||
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch(pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
(void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
|
||||
outfile);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
|
||||
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
|
||||
fflush(stdout);
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("\n");
|
||||
fclose(infile);
|
||||
|
||||
printf("Processed %d frames.\n",frame_cnt-1);
|
||||
vpx_img_free(&raw);
|
||||
if(vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,137 +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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vp9/common/vp9_common.h"
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
|
||||
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, "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) {
|
||||
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");
|
||||
|
||||
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,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts)) {
|
||||
die_codec(codec, "Failed to write compressed frame");
|
||||
}
|
||||
printf(keyframe ? "K" : ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
return got_pkts;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
VpxVideoInfo info;
|
||||
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");
|
||||
|
||||
encoder = get_vpx_encoder_by_name("vp9");
|
||||
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.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(&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;
|
||||
|
||||
writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
|
||||
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]);
|
||||
|
||||
if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
if (vpx_codec_control_(&codec, VP9E_SET_LOSSLESS, 1))
|
||||
die_codec(&codec, "Failed to use lossless mode");
|
||||
|
||||
// Encode frames.
|
||||
while (vpx_img_read(&raw, infile)) {
|
||||
encode_frame(&codec, &raw, frame_count++, 0, writer);
|
||||
}
|
||||
|
||||
// Flush encoder.
|
||||
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.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,925 +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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an example demonstrating how to implement a multi-layer
|
||||
* VP9 encoding scheme based on spatial scalability for video applications
|
||||
* that benefit from a scalable bitstream.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../args.h"
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
|
||||
#include "../vpx_ports/vpx_timer.h"
|
||||
#include "vpx/svc_context.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "../vpxstats.h"
|
||||
#include "vp9/encoder/vp9_encoder.h"
|
||||
#define OUTPUT_RC_STATS 1
|
||||
|
||||
static const arg_def_t skip_frames_arg =
|
||||
ARG_DEF("s", "skip-frames", 1, "input frames to skip");
|
||||
static const arg_def_t frames_arg =
|
||||
ARG_DEF("f", "frames", 1, "number of frames to encode");
|
||||
static const arg_def_t threads_arg =
|
||||
ARG_DEF("th", "threads", 1, "number of threads to use");
|
||||
#if OUTPUT_RC_STATS
|
||||
static const arg_def_t output_rc_stats_arg =
|
||||
ARG_DEF("rcstat", "output_rc_stats", 1, "output rc stats");
|
||||
#endif
|
||||
static const arg_def_t width_arg = ARG_DEF("w", "width", 1, "source width");
|
||||
static const arg_def_t height_arg = ARG_DEF("h", "height", 1, "source height");
|
||||
static const arg_def_t timebase_arg =
|
||||
ARG_DEF("t", "timebase", 1, "timebase (num/den)");
|
||||
static const arg_def_t bitrate_arg = ARG_DEF(
|
||||
"b", "target-bitrate", 1, "encoding bitrate, in kilobits per second");
|
||||
static const arg_def_t spatial_layers_arg =
|
||||
ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers");
|
||||
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");
|
||||
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 =
|
||||
ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)");
|
||||
static const arg_def_t passes_arg =
|
||||
ARG_DEF("p", "passes", 1, "Number of passes (1/2)");
|
||||
static const arg_def_t pass_arg =
|
||||
ARG_DEF(NULL, "pass", 1, "Pass to execute (1/2)");
|
||||
static const arg_def_t fpf_name_arg =
|
||||
ARG_DEF(NULL, "fpf", 1, "First pass statistics file name");
|
||||
static const arg_def_t min_q_arg =
|
||||
ARG_DEF(NULL, "min-q", 1, "Minimum quantizer");
|
||||
static const arg_def_t max_q_arg =
|
||||
ARG_DEF(NULL, "max-q", 1, "Maximum quantizer");
|
||||
static const arg_def_t min_bitrate_arg =
|
||||
ARG_DEF(NULL, "min-bitrate", 1, "Minimum bitrate");
|
||||
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");
|
||||
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 }
|
||||
};
|
||||
|
||||
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,
|
||||
#if OUTPUT_RC_STATS
|
||||
&output_rc_stats_arg,
|
||||
#endif
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
&bitdepth_arg,
|
||||
#endif
|
||||
&speed_arg,
|
||||
&rc_end_usage_arg,
|
||||
&bitrates_arg,
|
||||
NULL };
|
||||
|
||||
static const uint32_t default_frames_to_skip = 0;
|
||||
static const uint32_t default_frames_to_code = 60 * 60;
|
||||
static const uint32_t default_width = 1920;
|
||||
static const uint32_t default_height = 1080;
|
||||
static const uint32_t default_timebase_num = 1;
|
||||
static const uint32_t default_timebase_den = 60;
|
||||
static const uint32_t default_bitrate = 1000;
|
||||
static const uint32_t default_spatial_layers = 5;
|
||||
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 uint32_t default_threads = 0; // zero means use library default.
|
||||
|
||||
typedef struct {
|
||||
const char *input_filename;
|
||||
const char *output_filename;
|
||||
uint32_t frames_to_code;
|
||||
uint32_t frames_to_skip;
|
||||
struct VpxInputContext input_ctx;
|
||||
stats_io_t rc_stats;
|
||||
int passes;
|
||||
int pass;
|
||||
} AppInput;
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <options> input_filename output_filename\n",
|
||||
exec_name);
|
||||
fprintf(stderr, "Options:\n");
|
||||
arg_show_usage(stderr, svc_args);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void parse_command_line(int argc, const char **argv_,
|
||||
AppInput *app_input, SvcContext *svc_ctx,
|
||||
vpx_codec_enc_cfg_t *enc_cfg) {
|
||||
struct arg arg;
|
||||
char **argv = NULL;
|
||||
char **argi = NULL;
|
||||
char **argj = NULL;
|
||||
vpx_codec_err_t res;
|
||||
int passes = 0;
|
||||
int pass = 0;
|
||||
const char *fpf_file_name = NULL;
|
||||
unsigned int min_bitrate = 0;
|
||||
unsigned int max_bitrate = 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;
|
||||
svc_ctx->spatial_layers = default_spatial_layers;
|
||||
svc_ctx->temporal_layers = default_temporal_layers;
|
||||
svc_ctx->temporal_layering_mode = default_temporal_layering_mode;
|
||||
#if OUTPUT_RC_STATS
|
||||
svc_ctx->output_rc_stat = default_output_rc_stats;
|
||||
#endif
|
||||
svc_ctx->speed = default_speed;
|
||||
svc_ctx->threads = default_threads;
|
||||
|
||||
// start with default encoder configuration
|
||||
res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
|
||||
if (res) {
|
||||
die("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
}
|
||||
// update enc_cfg with app default values
|
||||
enc_cfg->g_w = default_width;
|
||||
enc_cfg->g_h = default_height;
|
||||
enc_cfg->g_timebase.num = default_timebase_num;
|
||||
enc_cfg->g_timebase.den = default_timebase_den;
|
||||
enc_cfg->rc_target_bitrate = default_bitrate;
|
||||
enc_cfg->kf_min_dist = default_kf_dist;
|
||||
enc_cfg->kf_max_dist = default_kf_dist;
|
||||
enc_cfg->rc_end_usage = VPX_CQ;
|
||||
|
||||
// initialize AppInput with default values
|
||||
app_input->frames_to_code = default_frames_to_code;
|
||||
app_input->frames_to_skip = default_frames_to_skip;
|
||||
|
||||
// process command line options
|
||||
argv = argv_dup(argc - 1, argv_ + 1);
|
||||
for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
|
||||
arg.argv_step = 1;
|
||||
|
||||
if (arg_match(&arg, &frames_arg, argi)) {
|
||||
app_input->frames_to_code = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &width_arg, argi)) {
|
||||
enc_cfg->g_w = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &height_arg, argi)) {
|
||||
enc_cfg->g_h = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &timebase_arg, argi)) {
|
||||
enc_cfg->g_timebase = arg_parse_rational(&arg);
|
||||
} else if (arg_match(&arg, &bitrate_arg, argi)) {
|
||||
enc_cfg->rc_target_bitrate = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &skip_frames_arg, argi)) {
|
||||
app_input->frames_to_skip = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &spatial_layers_arg, argi)) {
|
||||
svc_ctx->spatial_layers = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &temporal_layers_arg, argi)) {
|
||||
svc_ctx->temporal_layers = arg_parse_uint(&arg);
|
||||
#if OUTPUT_RC_STATS
|
||||
} else if (arg_match(&arg, &output_rc_stats_arg, argi)) {
|
||||
svc_ctx->output_rc_stat = arg_parse_uint(&arg);
|
||||
#endif
|
||||
} else if (arg_match(&arg, &speed_arg, argi)) {
|
||||
svc_ctx->speed = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &aqmode_arg, argi)) {
|
||||
svc_ctx->aqmode = arg_parse_uint(&arg);
|
||||
} 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);
|
||||
if (svc_ctx->temporal_layering_mode) {
|
||||
enc_cfg->g_error_resilient = 1;
|
||||
}
|
||||
} else if (arg_match(&arg, &kf_dist_arg, argi)) {
|
||||
enc_cfg->kf_min_dist = arg_parse_uint(&arg);
|
||||
enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
|
||||
} 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) {
|
||||
die("Error: Invalid number of passes (%d)\n", passes);
|
||||
}
|
||||
} else if (arg_match(&arg, &pass_arg, argi)) {
|
||||
pass = arg_parse_uint(&arg);
|
||||
if (pass < 1 || pass > 2) {
|
||||
die("Error: Invalid pass selected (%d)\n", pass);
|
||||
}
|
||||
} else if (arg_match(&arg, &fpf_name_arg, argi)) {
|
||||
fpf_file_name = arg.val;
|
||||
} else if (arg_match(&arg, &min_q_arg, argi)) {
|
||||
snprintf(string_options, sizeof(string_options), "%s min-quantizers=%s",
|
||||
string_options, arg.val);
|
||||
} else if (arg_match(&arg, &max_q_arg, argi)) {
|
||||
snprintf(string_options, sizeof(string_options), "%s max-quantizers=%s",
|
||||
string_options, arg.val);
|
||||
} else if (arg_match(&arg, &min_bitrate_arg, argi)) {
|
||||
min_bitrate = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &max_bitrate_arg, argi)) {
|
||||
max_bitrate = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &lag_in_frame_arg, argi)) {
|
||||
enc_cfg->g_lag_in_frames = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &rc_end_usage_arg, argi)) {
|
||||
enc_cfg->rc_end_usage = arg_parse_uint(&arg);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
} else if (arg_match(&arg, &bitdepth_arg, argi)) {
|
||||
enc_cfg->g_bit_depth = arg_parse_enum_or_int(&arg);
|
||||
switch (enc_cfg->g_bit_depth) {
|
||||
case VPX_BITS_8:
|
||||
enc_cfg->g_input_bit_depth = 8;
|
||||
enc_cfg->g_profile = 0;
|
||||
break;
|
||||
case VPX_BITS_10:
|
||||
enc_cfg->g_input_bit_depth = 10;
|
||||
enc_cfg->g_profile = 2;
|
||||
break;
|
||||
case VPX_BITS_12:
|
||||
enc_cfg->g_input_bit_depth = 12;
|
||||
enc_cfg->g_profile = 2;
|
||||
break;
|
||||
default:
|
||||
die("Error: Invalid bit depth selected (%d)\n", enc_cfg->g_bit_depth);
|
||||
break;
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
} else {
|
||||
++argj;
|
||||
}
|
||||
}
|
||||
|
||||
// There will be a space in front of the string options
|
||||
if (strlen(string_options) > 0)
|
||||
vpx_svc_set_options(svc_ctx, string_options + 1);
|
||||
|
||||
if (passes == 0 || passes == 1) {
|
||||
if (pass) {
|
||||
fprintf(stderr, "pass is ignored since there's only one pass\n");
|
||||
}
|
||||
enc_cfg->g_pass = VPX_RC_ONE_PASS;
|
||||
} else {
|
||||
if (pass == 0) {
|
||||
die("pass must be specified when passes is 2\n");
|
||||
}
|
||||
|
||||
if (fpf_file_name == NULL) {
|
||||
die("fpf must be specified when passes is 2\n");
|
||||
}
|
||||
|
||||
if (pass == 1) {
|
||||
enc_cfg->g_pass = VPX_RC_FIRST_PASS;
|
||||
if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 0)) {
|
||||
fatal("Failed to open statistics store");
|
||||
}
|
||||
} else {
|
||||
enc_cfg->g_pass = VPX_RC_LAST_PASS;
|
||||
if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 1)) {
|
||||
fatal("Failed to open statistics store");
|
||||
}
|
||||
enc_cfg->rc_twopass_stats_in = stats_get(&app_input->rc_stats);
|
||||
}
|
||||
app_input->passes = passes;
|
||||
app_input->pass = pass;
|
||||
}
|
||||
|
||||
if (enc_cfg->rc_target_bitrate > 0) {
|
||||
if (min_bitrate > 0) {
|
||||
enc_cfg->rc_2pass_vbr_minsection_pct =
|
||||
min_bitrate * 100 / enc_cfg->rc_target_bitrate;
|
||||
}
|
||||
if (max_bitrate > 0) {
|
||||
enc_cfg->rc_2pass_vbr_maxsection_pct =
|
||||
max_bitrate * 100 / enc_cfg->rc_target_bitrate;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for unrecognized options
|
||||
for (argi = argv; *argi; ++argi)
|
||||
if (argi[0][0] == '-' && strlen(argi[0]) > 1)
|
||||
die("Error: Unrecognized option %s\n", *argi);
|
||||
|
||||
if (argv[0] == NULL || argv[1] == 0) {
|
||||
usage_exit();
|
||||
}
|
||||
app_input->input_filename = argv[0];
|
||||
app_input->output_filename = argv[1];
|
||||
free(argv);
|
||||
|
||||
if (enc_cfg->g_w < 16 || enc_cfg->g_w % 2 || enc_cfg->g_h < 16 ||
|
||||
enc_cfg->g_h % 2)
|
||||
die("Invalid resolution: %d x %d\n", enc_cfg->g_w, enc_cfg->g_h);
|
||||
|
||||
printf(
|
||||
"Codec %s\nframes: %d, skip: %d\n"
|
||||
"layers: %d\n"
|
||||
"width %d, height: %d,\n"
|
||||
"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,
|
||||
enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
|
||||
}
|
||||
|
||||
#if OUTPUT_RC_STATS
|
||||
// For rate control encoding stats.
|
||||
struct RateControlStats {
|
||||
// Number of input frames per layer.
|
||||
int layer_input_frames[VPX_MAX_LAYERS];
|
||||
// Total (cumulative) number of encoded frames per layer.
|
||||
int layer_tot_enc_frames[VPX_MAX_LAYERS];
|
||||
// Number of encoded non-key frames per layer.
|
||||
int layer_enc_frames[VPX_MAX_LAYERS];
|
||||
// Framerate per layer (cumulative).
|
||||
double layer_framerate[VPX_MAX_LAYERS];
|
||||
// Target average frame size per layer (per-frame-bandwidth per layer).
|
||||
double layer_pfb[VPX_MAX_LAYERS];
|
||||
// Actual average frame size per layer.
|
||||
double layer_avg_frame_size[VPX_MAX_LAYERS];
|
||||
// Average rate mismatch per layer (|target - actual| / target).
|
||||
double layer_avg_rate_mismatch[VPX_MAX_LAYERS];
|
||||
// Actual encoding bitrate per layer (cumulative).
|
||||
double layer_encoding_bitrate[VPX_MAX_LAYERS];
|
||||
// Average of the short-time encoder actual bitrate.
|
||||
// TODO(marpan): Should we add these short-time stats for each layer?
|
||||
double avg_st_encoding_bitrate;
|
||||
// Variance of the short-time encoder actual bitrate.
|
||||
double variance_st_encoding_bitrate;
|
||||
// Window (number of frames) for computing short-time encoding bitrate.
|
||||
int window_size;
|
||||
// Number of window measurements.
|
||||
int window_count;
|
||||
};
|
||||
|
||||
// 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) {
|
||||
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.
|
||||
const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
|
||||
|
||||
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;
|
||||
if (cfg->ts_number_layers == 1)
|
||||
rc->layer_framerate[layer] = framerate;
|
||||
else
|
||||
rc->layer_framerate[layer] = framerate / cfg->ts_rate_decimator[tl];
|
||||
if (tl > 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]);
|
||||
} else {
|
||||
rc->layer_pfb[layer] = 1000.0 * cfg->layer_target_bitrate[layer] /
|
||||
rc->layer_framerate[layer];
|
||||
}
|
||||
rc->layer_input_frames[layer] = 0;
|
||||
rc->layer_enc_frames[layer] = 0;
|
||||
rc->layer_tot_enc_frames[layer] = 0;
|
||||
rc->layer_encoding_bitrate[layer] = 0.0;
|
||||
rc->layer_avg_frame_size[layer] = 0.0;
|
||||
rc->layer_avg_rate_mismatch[layer] = 0.0;
|
||||
}
|
||||
}
|
||||
rc->window_count = 0;
|
||||
rc->window_size = 15;
|
||||
rc->avg_st_encoding_bitrate = 0.0;
|
||||
rc->variance_st_encoding_bitrate = 0.0;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
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];
|
||||
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];
|
||||
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, "
|
||||
"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]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
|
||||
rc->variance_st_encoding_bitrate =
|
||||
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);
|
||||
printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
|
||||
rc->avg_st_encoding_bitrate, sqrt(rc->variance_st_encoding_bitrate),
|
||||
perc_fluctuation);
|
||||
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) {
|
||||
// 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
|
||||
// not the associated matching marker byte at the front of the index we have
|
||||
// an invalid bitstream and need to return an error.
|
||||
|
||||
uint8_t marker;
|
||||
|
||||
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;
|
||||
const size_t index_sz = 2 + mag * frames;
|
||||
|
||||
// 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;
|
||||
|
||||
{
|
||||
const uint8_t marker2 = *(data + data_sz - index_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;
|
||||
}
|
||||
|
||||
{
|
||||
// Found a valid superframe index.
|
||||
uint32_t i, j;
|
||||
const uint8_t *x = &data[data_sz - index_sz + 1];
|
||||
|
||||
for (i = 0; i < frames; ++i) {
|
||||
uint32_t this_sz = 0;
|
||||
|
||||
for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
|
||||
sizes[i] = this_sz;
|
||||
}
|
||||
*count = frames;
|
||||
}
|
||||
}
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Example pattern for spatial layers and 2 temporal layers used in the
|
||||
// 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 sl, int tl, int num_spatial_layers,
|
||||
int is_key_frame,
|
||||
vpx_svc_ref_frame_config_t *ref_frame_config) {
|
||||
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;
|
||||
} else {
|
||||
if (is_key_frame) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
} else {
|
||||
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)
|
||||
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;
|
||||
ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1;
|
||||
ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
AppInput app_input;
|
||||
VpxVideoWriter *writer = NULL;
|
||||
VpxVideoInfo info;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t enc_cfg;
|
||||
SvcContext svc_ctx;
|
||||
uint32_t i;
|
||||
uint32_t frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
int pts = 0; /* PTS starts at 0 */
|
||||
int frame_duration = 1; /* 1 timebase tick per frame */
|
||||
FILE *infile = NULL;
|
||||
int end_of_stream = 0;
|
||||
int frames_received = 0;
|
||||
#if OUTPUT_RC_STATS
|
||||
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;
|
||||
double sum_bitrate = 0.0;
|
||||
double sum_bitrate2 = 0.0;
|
||||
double framerate = 30.0;
|
||||
#endif
|
||||
struct vpx_usec_timer timer;
|
||||
int64_t cx_time = 0;
|
||||
memset(&svc_ctx, 0, sizeof(svc_ctx));
|
||||
svc_ctx.log_print = 1;
|
||||
exec_name = argv[0];
|
||||
parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
|
||||
|
||||
// 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,
|
||||
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);
|
||||
}
|
||||
#else
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, 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);
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
if (!(infile = fopen(app_input.input_filename, "rb")))
|
||||
die("Failed to open %s for reading\n", app_input.input_filename);
|
||||
|
||||
// Initialize codec
|
||||
if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) !=
|
||||
VPX_CODEC_OK)
|
||||
die("Failed to initialize encoder\n");
|
||||
|
||||
#if OUTPUT_RC_STATS
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
set_rate_control_stats(&rc, &enc_cfg);
|
||||
framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num;
|
||||
}
|
||||
#endif
|
||||
|
||||
info.codec_fourcc = VP9_FOURCC;
|
||||
info.time_base.numerator = enc_cfg.g_timebase.num;
|
||||
info.time_base.denominator = enc_cfg.g_timebase.den;
|
||||
|
||||
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);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing\n", app_input.output_filename);
|
||||
}
|
||||
#if OUTPUT_RC_STATS
|
||||
// For now, just write temporal layer streams.
|
||||
// TODO(marpan): do spatial by re-writing superframe.
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
|
||||
char file_name[PATH_MAX];
|
||||
|
||||
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);
|
||||
|
||||
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, (svc_ctx.threads >> 1));
|
||||
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.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);
|
||||
|
||||
// Encode frames
|
||||
while (!end_of_stream) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *cx_pkt;
|
||||
if (frame_cnt >= app_input.frames_to_code || !vpx_img_read(&raw, infile)) {
|
||||
// We need one extra vpx_svc_encode call at end of stream to flush
|
||||
// encoder and get remaining data
|
||||
end_of_stream = 1;
|
||||
}
|
||||
|
||||
// For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates)
|
||||
// and the buffer indices for each spatial layer of the current
|
||||
// (super)frame to be encoded. The temporal layer_id for the current frame
|
||||
// also needs to be set.
|
||||
// TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS"
|
||||
// mode to "VP9E_LAYERING_MODE_BYPASS".
|
||||
if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
|
||||
layer_id.spatial_layer_id = 0;
|
||||
// Example for 2 temporal layers.
|
||||
if (frame_cnt % 2 == 0)
|
||||
layer_id.temporal_layer_id = 0;
|
||||
else
|
||||
layer_id.temporal_layer_id = 1;
|
||||
// Note that we only set the temporal layer_id, since we are calling
|
||||
// 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);
|
||||
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) {
|
||||
++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
|
||||
layer_id.temporal_layer_id];
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
while ((cx_pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
|
||||
switch (cx_pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT: {
|
||||
SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal;
|
||||
if (cx_pkt->data.frame.sz > 0) {
|
||||
#if OUTPUT_RC_STATS
|
||||
uint64_t sizes[8];
|
||||
int count = 0;
|
||||
#endif
|
||||
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.
|
||||
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, &count);
|
||||
if (enc_cfg.ss_number_layers == 1)
|
||||
sizes[0] = cx_pkt->data.frame.sz;
|
||||
// Note computing input_layer_frames here won't account for frame
|
||||
// drops in rate control stats.
|
||||
// TODO(marpan): Fix this for non-bypass mode so we can get stats
|
||||
// for dropped frames.
|
||||
if (svc_ctx.temporal_layering_mode !=
|
||||
VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
for (tl = layer_id.temporal_layer_id;
|
||||
tl < enc_cfg.ts_number_layers; ++tl) {
|
||||
vpx_video_writer_write_frame(
|
||||
outfile[tl], cx_pkt->data.frame.buf, cx_pkt->data.frame.sz,
|
||||
cx_pkt->data.frame.pts);
|
||||
}
|
||||
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
for (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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
tl = layer_id.temporal_layer_id;
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
|
||||
}
|
||||
if (frame_cnt % rc.window_size == 0) {
|
||||
rc.window_count += 1;
|
||||
rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
|
||||
rc.variance_st_encoding_bitrate +=
|
||||
(sum_bitrate / rc.window_size) *
|
||||
(sum_bitrate / rc.window_size);
|
||||
sum_bitrate = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Second shifted window.
|
||||
if (frame_cnt >
|
||||
(unsigned int)(rc.window_size + rc.window_size / 2)) {
|
||||
tl = layer_id.temporal_layer_id;
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#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,
|
||||
cx_pkt->data.twopass_stats.sz);
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
|
||||
if (!end_of_stream) {
|
||||
++frame_cnt;
|
||||
pts += frame_duration;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
--rc.layer_input_frames[layer];
|
||||
}
|
||||
}
|
||||
|
||||
printf("Processed %d frames\n", frame_cnt);
|
||||
fclose(infile);
|
||||
#if OUTPUT_RC_STATS
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
printout_rate_control_summary(&rc, &enc_cfg, frame_cnt);
|
||||
printf("\n");
|
||||
}
|
||||
#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 (writer) {
|
||||
vpx_video_writer_close(writer);
|
||||
}
|
||||
#if OUTPUT_RC_STATS
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
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),
|
||||
1000000 * (double)frame_cnt / (double)cx_time);
|
||||
vpx_img_free(&raw);
|
||||
// display average size, psnr
|
||||
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;
|
||||
}
|
||||
@@ -1,915 +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.
|
||||
*/
|
||||
|
||||
// This is an example demonstrating how to implement a multi-layer VPx
|
||||
// encoding scheme based on temporal scalability for video applications
|
||||
// that benefit from a scalable bitstream.
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./vpx_config.h"
|
||||
#include "../vpx_ports/vpx_timer.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
|
||||
#define VP8_ROI_MAP 0
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) { exit(EXIT_FAILURE); }
|
||||
|
||||
// Denoiser states for vp8, for temporal denoising.
|
||||
enum denoiserStateVp8 {
|
||||
kVp8DenoiserOff,
|
||||
kVp8DenoiserOnYOnly,
|
||||
kVp8DenoiserOnYUV,
|
||||
kVp8DenoiserOnYUVAggressive,
|
||||
kVp8DenoiserOnAdaptive
|
||||
};
|
||||
|
||||
// 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 };
|
||||
|
||||
// For rate control encoding stats.
|
||||
struct RateControlMetrics {
|
||||
// Number of input frames per layer.
|
||||
int layer_input_frames[VPX_TS_MAX_LAYERS];
|
||||
// Total (cumulative) number of encoded frames per layer.
|
||||
int layer_tot_enc_frames[VPX_TS_MAX_LAYERS];
|
||||
// Number of encoded non-key frames per layer.
|
||||
int layer_enc_frames[VPX_TS_MAX_LAYERS];
|
||||
// Framerate per layer layer (cumulative).
|
||||
double layer_framerate[VPX_TS_MAX_LAYERS];
|
||||
// Target average frame size per layer (per-frame-bandwidth per layer).
|
||||
double layer_pfb[VPX_TS_MAX_LAYERS];
|
||||
// Actual average frame size per layer.
|
||||
double layer_avg_frame_size[VPX_TS_MAX_LAYERS];
|
||||
// Average rate mismatch per layer (|target - actual| / target).
|
||||
double layer_avg_rate_mismatch[VPX_TS_MAX_LAYERS];
|
||||
// Actual encoding bitrate per layer (cumulative).
|
||||
double layer_encoding_bitrate[VPX_TS_MAX_LAYERS];
|
||||
// Average of the short-time encoder actual bitrate.
|
||||
// TODO(marpan): Should we add these short-time stats for each layer?
|
||||
double avg_st_encoding_bitrate;
|
||||
// Variance of the short-time encoder actual bitrate.
|
||||
double variance_st_encoding_bitrate;
|
||||
// Window (number of frames) for computing short-timee encoding bitrate.
|
||||
int window_size;
|
||||
// Number of window measurements.
|
||||
int window_count;
|
||||
int layer_target_bitrate[VPX_MAX_LAYERS];
|
||||
};
|
||||
|
||||
// Note: these rate control metrics assume only 1 key frame in the
|
||||
// sequence (i.e., first frame only). So for temporal pattern# 7
|
||||
// (which has key frame for every frame on base layer), the metrics
|
||||
// computation will be off/wrong.
|
||||
// TODO(marpan): Update these metrics to account for multiple key frames
|
||||
// in the stream.
|
||||
static void set_rate_control_metrics(struct RateControlMetrics *rc,
|
||||
vpx_codec_enc_cfg_t *cfg) {
|
||||
unsigned int i = 0;
|
||||
// Set the layer (cumulative) framerate and the target layer (non-cumulative)
|
||||
// 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];
|
||||
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_target_bitrate[i] -
|
||||
rc->layer_target_bitrate[i - 1]) /
|
||||
(rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
|
||||
}
|
||||
rc->layer_input_frames[i] = 0;
|
||||
rc->layer_enc_frames[i] = 0;
|
||||
rc->layer_tot_enc_frames[i] = 0;
|
||||
rc->layer_encoding_bitrate[i] = 0.0;
|
||||
rc->layer_avg_frame_size[i] = 0.0;
|
||||
rc->layer_avg_rate_mismatch[i] = 0.0;
|
||||
}
|
||||
rc->window_count = 0;
|
||||
rc->window_size = 15;
|
||||
rc->avg_st_encoding_bitrate = 0.0;
|
||||
rc->variance_st_encoding_bitrate = 0.0;
|
||||
}
|
||||
|
||||
static void printout_rate_control_summary(struct RateControlMetrics *rc,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
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("Rate control layer stats for %d layer(s):\n\n",
|
||||
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);
|
||||
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];
|
||||
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],
|
||||
100.0 * num_dropped / rc->layer_input_frames[i]);
|
||||
printf("\n");
|
||||
}
|
||||
rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
|
||||
rc->variance_st_encoding_bitrate =
|
||||
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);
|
||||
printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
|
||||
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 VP8_ROI_MAP
|
||||
static void vp8_set_roi_map(vpx_codec_enc_cfg_t *cfg, vpx_roi_map_t *roi) {
|
||||
unsigned int i, j;
|
||||
memset(roi, 0, sizeof(*roi));
|
||||
|
||||
// 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 + 15) / 16;
|
||||
roi->cols = (cfg->g_w + 15) / 16;
|
||||
|
||||
// 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.
|
||||
roi->delta_q[0] = 0;
|
||||
roi->delta_q[1] = -63;
|
||||
roi->delta_q[2] = 0;
|
||||
roi->delta_q[3] = 0;
|
||||
|
||||
// Applies delta loopfilter strength on the segment blocks, varies from -63 to
|
||||
// 63. Setting to positive means stronger loopfilter.
|
||||
roi->delta_lf[0] = 0;
|
||||
roi->delta_lf[1] = 0;
|
||||
roi->delta_lf[2] = 0;
|
||||
roi->delta_lf[3] = 0;
|
||||
|
||||
// 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.
|
||||
roi->static_threshold[0] = 0;
|
||||
roi->static_threshold[1] = 0;
|
||||
roi->static_threshold[2] = 0;
|
||||
roi->static_threshold[3] = 0;
|
||||
|
||||
// Use 2 states: 1 is center square, 0 is the rest.
|
||||
roi->roi_map =
|
||||
(uint8_t *)calloc(roi->rows * roi->cols, sizeof(*roi->roi_map));
|
||||
for (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
|
||||
// frames should be allocated to layers in the order LAST, GF, ARF.
|
||||
// Other combinations work, but may produce slightly inferior results.
|
||||
static void set_temporal_layer_pattern(int layering_mode,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
int *layer_flags,
|
||||
int *flag_periodicity) {
|
||||
switch (layering_mode) {
|
||||
case 0: {
|
||||
// 1-layer.
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// 2-layers, 2-frame period.
|
||||
int ids[2] = { 0, 1 };
|
||||
cfg->ts_periodicity = 2;
|
||||
*flag_periodicity = 2;
|
||||
cfg->ts_number_layers = 2;
|
||||
cfg->ts_rate_decimator[0] = 2;
|
||||
cfg->ts_rate_decimator[1] = 1;
|
||||
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[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 };
|
||||
cfg->ts_periodicity = 3;
|
||||
*flag_periodicity = 3;
|
||||
cfg->ts_number_layers = 2;
|
||||
cfg->ts_rate_decimator[0] = 3;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// 3-layers, 6-frame period.
|
||||
int ids[6] = { 0, 2, 2, 1, 2, 2 };
|
||||
cfg->ts_periodicity = 6;
|
||||
*flag_periodicity = 6;
|
||||
cfg->ts_number_layers = 3;
|
||||
cfg->ts_rate_decimator[0] = 6;
|
||||
cfg->ts_rate_decimator[1] = 3;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
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 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[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;
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
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 |
|
||||
VP8_EFLAG_NO_UPD_ARF;
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
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.
|
||||
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 };
|
||||
cfg->ts_periodicity = 16;
|
||||
*flag_periodicity = 16;
|
||||
cfg->ts_number_layers = 5;
|
||||
cfg->ts_rate_decimator[0] = 16;
|
||||
cfg->ts_rate_decimator[1] = 8;
|
||||
cfg->ts_rate_decimator[2] = 4;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
// 2-layers, with sync point at first frame of layer 1.
|
||||
int ids[2] = { 0, 1 };
|
||||
cfg->ts_periodicity = 2;
|
||||
*flag_periodicity = 8;
|
||||
cfg->ts_number_layers = 2;
|
||||
cfg->ts_rate_decimator[0] = 2;
|
||||
cfg->ts_rate_decimator[1] = 1;
|
||||
memcpy(cfg->ts_layer_id, ids, sizeof(ids));
|
||||
// 0=L, 1=GF.
|
||||
// ARF is used as predictor for all frames, and is only updated on
|
||||
// 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 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 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 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;
|
||||
// Layer 0.
|
||||
layer_flags[4] = layer_flags[2];
|
||||
// Layer 1.
|
||||
layer_flags[5] = layer_flags[3];
|
||||
// Layer 0.
|
||||
layer_flags[6] = layer_flags[4];
|
||||
// Layer 1.
|
||||
layer_flags[7] = layer_flags[5];
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
// 3-layers: Sync points for layer 1 and 2 every 8 frames.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 8;
|
||||
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.
|
||||
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[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;
|
||||
layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
||||
VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY;
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
// 3-layers structure where ARF is used as predictor for all frames,
|
||||
// and is only updated on key frame.
|
||||
// Sync points for layer 1 and 2 every 8 frames.
|
||||
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 8;
|
||||
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.
|
||||
// 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 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;
|
||||
// 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 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;
|
||||
// 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 2: predict from L, G, ARF; update none.
|
||||
layer_flags[5] = layer_flags[3];
|
||||
// Layer 1: predict from L, G, ARF; update G.
|
||||
layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
|
||||
// Layer 2: predict from L, G, ARF; update none.
|
||||
layer_flags[7] = layer_flags[3];
|
||||
break;
|
||||
}
|
||||
case 11: {
|
||||
// 3-layers structure with one reference frame.
|
||||
// This works same as temporal_layering_mode 3.
|
||||
// This was added to compare with vp9_spatial_svc_encoder.
|
||||
|
||||
// 3-layers, 4-frame period.
|
||||
int ids[4] = { 0, 2, 1, 2 };
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 4;
|
||||
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 disabled.
|
||||
layer_flags[0] = 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] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
|
||||
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;
|
||||
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 };
|
||||
cfg->ts_periodicity = 4;
|
||||
*flag_periodicity = 8;
|
||||
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.
|
||||
// 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[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;
|
||||
layer_flags[3] = layer_flags[1];
|
||||
layer_flags[5] = layer_flags[1];
|
||||
layer_flags[7] = layer_flags[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = { NULL };
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
vpx_image_t raw;
|
||||
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 frame_duration = 1; // 1 timebase tick per frame.
|
||||
int layering_mode = 0;
|
||||
int layer_flags[VPX_TS_MAX_PERIODICITY] = { 0 };
|
||||
int flag_periodicity = 1;
|
||||
#if VP8_ROI_MAP
|
||||
vpx_roi_map_t roi;
|
||||
#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;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
vpx_bit_depth_t bit_depth = VPX_BITS_8;
|
||||
int input_bit_depth = 8;
|
||||
const int min_args = min_args_base + 1;
|
||||
#else
|
||||
const int min_args = min_args_base;
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
double sum_bitrate = 0.0;
|
||||
double sum_bitrate2 = 0.0;
|
||||
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]);
|
||||
#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]);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
}
|
||||
|
||||
encoder = get_vpx_encoder_by_name(argv[3]);
|
||||
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);
|
||||
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);
|
||||
if (layering_mode < 0 || layering_mode > 13) {
|
||||
die("Invalid layering mode (0..12) %s", argv[12]);
|
||||
}
|
||||
|
||||
if (argc != min_args + mode_to_num_layers[layering_mode]) {
|
||||
die("Invalid number of arguments");
|
||||
}
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
switch (strtol(argv[argc - 1], NULL, 0)) {
|
||||
case 8:
|
||||
bit_depth = VPX_BITS_8;
|
||||
input_bit_depth = 8;
|
||||
break;
|
||||
case 10:
|
||||
bit_depth = VPX_BITS_10;
|
||||
input_bit_depth = 10;
|
||||
break;
|
||||
case 12:
|
||||
bit_depth = VPX_BITS_12;
|
||||
input_bit_depth = 12;
|
||||
break;
|
||||
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)) {
|
||||
die("Failed to allocate image", width, height);
|
||||
}
|
||||
#else
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) {
|
||||
die("Failed to allocate image", width, height);
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
// Populate encoder configuration.
|
||||
res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
|
||||
if (res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Update the default configuration with our settings.
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (bit_depth != VPX_BITS_8) {
|
||||
cfg.g_bit_depth = bit_depth;
|
||||
cfg.g_input_bit_depth = input_bit_depth;
|
||||
cfg.g_profile = 2;
|
||||
}
|
||||
#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);
|
||||
|
||||
speed = (int)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);
|
||||
if (strncmp(encoder->name, "vp8", 3) == 0)
|
||||
cfg.ts_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
|
||||
else if (strncmp(encoder->name, "vp9", 3) == 0)
|
||||
cfg.layer_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
|
||||
}
|
||||
|
||||
// Real time parameters.
|
||||
cfg.rc_dropframe_thresh = (unsigned int)strtoul(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;
|
||||
cfg.rc_undershoot_pct = 50;
|
||||
cfg.rc_overshoot_pct = 50;
|
||||
cfg.rc_buf_initial_sz = 600;
|
||||
cfg.rc_buf_optimal_sz = 600;
|
||||
cfg.rc_buf_sz = 1000;
|
||||
|
||||
// Disable dynamic resizing by default.
|
||||
cfg.rc_resize_allowed = 0;
|
||||
|
||||
// Use 1 thread as default.
|
||||
cfg.g_threads = (unsigned int)strtoul(argv[11], NULL, 0);
|
||||
|
||||
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.kf_mode = VPX_KF_AUTO;
|
||||
|
||||
// Disable automatic keyframe placement.
|
||||
cfg.kf_min_dist = cfg.kf_max_dist = 3000;
|
||||
|
||||
cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
|
||||
|
||||
set_temporal_layer_pattern(layering_mode, &cfg, layer_flags,
|
||||
&flag_periodicity);
|
||||
|
||||
set_rate_control_metrics(&rc, &cfg);
|
||||
|
||||
// Target bandwidth for the whole stream.
|
||||
// Set to layer_target_bitrate for highest layer (total bitrate).
|
||||
cfg.rc_target_bitrate = rc.layer_target_bitrate[cfg.ts_number_layers - 1];
|
||||
|
||||
// Open input file.
|
||||
if (!(infile = fopen(argv[1], "rb"))) {
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
}
|
||||
|
||||
framerate = cfg.g_timebase.den / cfg.g_timebase.num;
|
||||
// Open an output file for each stream.
|
||||
for (i = 0; i < cfg.ts_number_layers; ++i) {
|
||||
char file_name[PATH_MAX];
|
||||
VpxVideoInfo info;
|
||||
info.codec_fourcc = encoder->fourcc;
|
||||
info.frame_width = cfg.g_w;
|
||||
info.frame_height = cfg.g_h;
|
||||
info.time_base.numerator = cfg.g_timebase.num;
|
||||
info.time_base.denominator = cfg.g_timebase.den;
|
||||
|
||||
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);
|
||||
|
||||
assert(outfile[i] != NULL);
|
||||
}
|
||||
// No spatial layers in this encoder.
|
||||
cfg.ss_number_layers = 1;
|
||||
|
||||
// Initialize codec.
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (vpx_codec_enc_init(
|
||||
&codec, encoder->codec_interface(), &cfg,
|
||||
bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH))
|
||||
#else
|
||||
if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
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_STATIC_THRESHOLD, 1);
|
||||
vpx_codec_control(&codec, VP8E_SET_GF_CBR_BOOST_PCT, 0);
|
||||
#if VP8_ROI_MAP
|
||||
vp8_set_roi_map(&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, VP8E_SET_STATIC_THRESHOLD, 1);
|
||||
vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
|
||||
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
|
||||
// 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))
|
||||
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;
|
||||
svc_params.min_quantizers[i] = cfg.rc_min_quantizer;
|
||||
}
|
||||
svc_params.scaling_factor_num[0] = cfg.g_h;
|
||||
svc_params.scaling_factor_den[0] = cfg.g_h;
|
||||
vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params);
|
||||
}
|
||||
if (strncmp(encoder->name, "vp8", 3) == 0) {
|
||||
vpx_codec_control(&codec, VP8E_SET_SCREEN_CONTENT_MODE, 0);
|
||||
}
|
||||
vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1);
|
||||
// This controls the maximum target size of the key frame.
|
||||
// For generating smaller key frames, use a smaller max_intra_size_pct
|
||||
// value, like 100 or 200.
|
||||
{
|
||||
const int max_intra_size_pct = 1000;
|
||||
vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
||||
max_intra_size_pct);
|
||||
}
|
||||
|
||||
frame_avail = 1;
|
||||
while (frame_avail || got_data) {
|
||||
struct vpx_usec_timer timer;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
// Update the temporal layer_id. No spatial layers in this test.
|
||||
layer_id.spatial_layer_id = 0;
|
||||
layer_id.temporal_layer_id =
|
||||
cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
|
||||
if (strncmp(encoder->name, "vp9", 3) == 0) {
|
||||
vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
|
||||
} else if (strncmp(encoder->name, "vp8", 3) == 0) {
|
||||
vpx_codec_control(&codec, VP8E_SET_TEMPORAL_LAYER_ID,
|
||||
layer_id.temporal_layer_id);
|
||||
}
|
||||
flags = layer_flags[frame_cnt % flag_periodicity];
|
||||
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];
|
||||
vpx_usec_timer_start(&timer);
|
||||
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);
|
||||
cx_time += vpx_usec_timer_elapsed(&timer);
|
||||
// Reset KF flag.
|
||||
if (layering_mode != 7) {
|
||||
layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
|
||||
}
|
||||
got_data = 0;
|
||||
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) {
|
||||
vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
|
||||
pkt->data.frame.sz, pts);
|
||||
++rc.layer_tot_enc_frames[i];
|
||||
rc.layer_encoding_bitrate[i] += 8.0 * pkt->data.frame.sz;
|
||||
// Keep count of rate control stats per layer (for non-key frames).
|
||||
if (i == cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity] &&
|
||||
!(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
|
||||
rc.layer_avg_frame_size[i] += 8.0 * pkt->data.frame.sz;
|
||||
rc.layer_avg_rate_mismatch[i] +=
|
||||
fabs(8.0 * pkt->data.frame.sz - rc.layer_pfb[i]) /
|
||||
rc.layer_pfb[i];
|
||||
++rc.layer_enc_frames[i];
|
||||
}
|
||||
}
|
||||
// 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 > rc.window_size) {
|
||||
sum_bitrate += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
|
||||
if (frame_cnt % rc.window_size == 0) {
|
||||
rc.window_count += 1;
|
||||
rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
|
||||
rc.variance_st_encoding_bitrate +=
|
||||
(sum_bitrate / rc.window_size) *
|
||||
(sum_bitrate / rc.window_size);
|
||||
sum_bitrate = 0.0;
|
||||
}
|
||||
}
|
||||
// Second shifted window.
|
||||
if (frame_cnt > rc.window_size + rc.window_size / 2) {
|
||||
sum_bitrate2 += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
++frame_cnt;
|
||||
pts += frame_duration;
|
||||
}
|
||||
fclose(infile);
|
||||
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);
|
||||
|
||||
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]);
|
||||
|
||||
vpx_img_free(&raw);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
26
ivfdec.c
26
ivfdec.c
@@ -8,22 +8,17 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vpx_ports/mem_ops.h"
|
||||
|
||||
#include "./ivfdec.h"
|
||||
|
||||
static const char *IVF_SIGNATURE = "DKIF";
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void fix_framerate(int *num, int *den) {
|
||||
// Some versions of vpxenc used 1/(2*fps) for the timebase, so
|
||||
// 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;
|
||||
@@ -42,12 +37,12 @@ int file_is_ivf(struct VpxInputContext *input_ctx) {
|
||||
int is_ivf = 0;
|
||||
|
||||
if (fread(raw_hdr, 1, 32, input_ctx->file) == 32) {
|
||||
if (memcmp(IVF_SIGNATURE, raw_hdr, 4) == 0) {
|
||||
if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K' &&
|
||||
raw_hdr[2] == 'I' && raw_hdr[3] == 'F') {
|
||||
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 +65,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_
|
||||
|
||||
47
ivfenc.c
47
ivfenc.c
@@ -10,42 +10,47 @@
|
||||
|
||||
#include "./ivfenc.h"
|
||||
|
||||
#include "./tools_common.h"
|
||||
#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';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header + 4, 0); // version
|
||||
mem_put_le16(header + 6, 32); // header size
|
||||
mem_put_le32(header + 8, fourcc); // fourcc
|
||||
mem_put_le16(header + 12, cfg->g_w); // width
|
||||
mem_put_le16(header + 14, cfg->g_h); // height
|
||||
mem_put_le32(header + 16, cfg->g_timebase.den); // rate
|
||||
mem_put_le32(header + 20, cfg->g_timebase.num); // scale
|
||||
mem_put_le32(header + 24, frame_cnt); // length
|
||||
mem_put_le32(header + 28, 0); // unused
|
||||
mem_put_le16(header + 4, 0); /* version */
|
||||
mem_put_le16(header + 6, 32); /* headersize */
|
||||
mem_put_le32(header + 8, fourcc); /* four CC */
|
||||
mem_put_le16(header + 12, cfg->g_w); /* width */
|
||||
mem_put_le16(header + 14, cfg->g_h); /* height */
|
||||
mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header + 24, frame_cnt); /* length */
|
||||
mem_put_le32(header + 28, 0); /* unused */
|
||||
|
||||
fwrite(header, 1, 32, outfile);
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) {
|
||||
void ivf_write_frame_header(FILE *outfile, const struct vpx_codec_cx_pkt *pkt) {
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
mem_put_le32(header, (int)frame_size);
|
||||
mem_put_le32(header + 4, (int)(pts & 0xFFFFFFFF));
|
||||
mem_put_le32(header + 8, (int)(pts >> 32));
|
||||
fwrite(header, 1, 12, outfile);
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, (int)pkt->data.frame.sz);
|
||||
mem_put_le32(header + 4, pts & 0xFFFFFFFF);
|
||||
mem_put_le32(header + 8, pts >> 32);
|
||||
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
void ivf_write_frame_size(FILE *outfile, size_t frame_size) {
|
||||
void ivf_write_frame_size(FILE *outfile, size_t size) {
|
||||
char header[4];
|
||||
|
||||
mem_put_le32(header, (int)frame_size);
|
||||
fwrite(header, 1, 4, outfile);
|
||||
mem_put_le32(header, (int)size);
|
||||
(void) fwrite(header, 1, 4, outfile);
|
||||
}
|
||||
|
||||
14
ivfenc.h
14
ivfenc.h
@@ -19,15 +19,15 @@ 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_frame_header(FILE *outfile, int64_t pts, size_t frame_size);
|
||||
|
||||
void ivf_write_frame_size(FILE *outfile, size_t frame_size);
|
||||
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, const struct vpx_codec_cx_pkt *pkt);
|
||||
void ivf_write_frame_size(FILE *outfile, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // IVFENC_H_
|
||||
|
||||
@@ -36,7 +36,7 @@ DOXYFILE_ENCODING = UTF-8
|
||||
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
|
||||
# by quotes) that should identify the project.
|
||||
|
||||
PROJECT_NAME = "WebM Codec SDK"
|
||||
PROJECT_NAME = "WebM VP8 Codec SDK"
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
@@ -415,6 +415,12 @@ MAX_INITIALIZER_LINES = 30
|
||||
|
||||
SHOW_USED_FILES = YES
|
||||
|
||||
# If the sources in your project are distributed over multiple directories
|
||||
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
|
||||
# in the documentation. The default is NO.
|
||||
|
||||
SHOW_DIRECTORIES = NO
|
||||
|
||||
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
|
||||
# doxygen should invoke to get the current version for each file (typically from the
|
||||
# version control system). Doxygen will invoke the program by executing (via
|
||||
@@ -709,6 +715,12 @@ HTML_FOOTER =
|
||||
|
||||
HTML_STYLESHEET =
|
||||
|
||||
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
|
||||
# files or namespaces will be aligned in HTML using tables. If set to
|
||||
# NO a bullet list will be used.
|
||||
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for tools like the
|
||||
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
|
||||
|
||||
370
libs.mk
370
libs.mk
@@ -12,28 +12,68 @@
|
||||
# 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
|
||||
|
||||
#
|
||||
# Calculate platform- and compiler-specific offsets for hand coded assembly
|
||||
#
|
||||
ifeq ($(filter icc gcc,$(TGT_CC)), $(TGT_CC))
|
||||
OFFSET_PATTERN:='^[a-zA-Z0-9_]* EQU'
|
||||
define asm_offsets_template
|
||||
$$(BUILD_PFX)$(1): $$(BUILD_PFX)$(2).S
|
||||
@echo " [CREATE] $$@"
|
||||
$$(qexec)LC_ALL=C grep $$(OFFSET_PATTERN) $$< | tr -d '$$$$\#' $$(ADS2GAS) > $$@
|
||||
$$(BUILD_PFX)$(2).S: $(2)
|
||||
CLEAN-OBJS += $$(BUILD_PFX)$(1) $(2).S
|
||||
endef
|
||||
else
|
||||
ifeq ($(filter rvct,$(TGT_CC)), $(TGT_CC))
|
||||
define asm_offsets_template
|
||||
$$(BUILD_PFX)$(1): obj_int_extract
|
||||
$$(BUILD_PFX)$(1): $$(BUILD_PFX)$(2).o
|
||||
@echo " [CREATE] $$@"
|
||||
$$(qexec)./obj_int_extract rvds $$< $$(ADS2GAS) > $$@
|
||||
OBJS-yes += $$(BUILD_PFX)$(2).o
|
||||
CLEAN-OBJS += $$(BUILD_PFX)$(1)
|
||||
$$(filter %$$(ASM).o,$$(OBJS-yes)): $$(BUILD_PFX)$(1)
|
||||
endef
|
||||
endif # rvct
|
||||
endif # !gcc
|
||||
|
||||
#
|
||||
# Rule to generate runtime cpu detection files
|
||||
#
|
||||
define rtcd_h_template
|
||||
$$(BUILD_PFX)$(1).h: $$(SRC_PATH_BARE)/$(2)
|
||||
@echo " [CREATE] $$@"
|
||||
$$(qexec)$$(SRC_PATH_BARE)/build/make/rtcd.pl --arch=$$(TGT_ISA) \
|
||||
$$(qexec)$$(SRC_PATH_BARE)/build/make/rtcd.sh --arch=$$(TGT_ISA) \
|
||||
--sym=$(1) \
|
||||
--config=$$(CONFIG_DIR)$$(target)-$$(TOOLCHAIN).mk \
|
||||
--config=$$(CONFIG_DIR)$$(target)$$(if $$(FAT_ARCHS),,-$$(TOOLCHAIN)).mk \
|
||||
$$(RTCD_OPTIONS) $$^ > $$@
|
||||
CLEAN-OBJS += $$(BUILD_PFX)$(1).h
|
||||
RTCD += $$(BUILD_PFX)$(1).h
|
||||
endef
|
||||
|
||||
# x86inc.asm is not compatible with pic 32bit builds. Restrict
|
||||
# files which use it to 64bit builds or 32bit without pic
|
||||
USE_X86INC = no
|
||||
ifeq ($(CONFIG_USE_X86INC),yes)
|
||||
USE_X86INC = yes
|
||||
endif
|
||||
|
||||
CODEC_SRCS-yes += CHANGELOG
|
||||
CODEC_SRCS-yes += libs.mk
|
||||
|
||||
# If this is a universal (fat) binary, then all the subarchitectures have
|
||||
# already been built and our job is to stitch them together. The
|
||||
# BUILD_LIBVPX variable indicates whether we should be building
|
||||
# (compiling, linking) the library. The LIPO_LIBVPX variable indicates
|
||||
# that we're stitching.
|
||||
$(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_LIBVPX,BUILD_LIBVPX):=yes)
|
||||
|
||||
include $(SRC_PATH_BARE)/vpx/vpx_codec.mk
|
||||
CODEC_SRCS-yes += $(addprefix vpx/,$(call enabled,API_SRCS))
|
||||
CODEC_DOC_SRCS += $(addprefix vpx/,$(call enabled,API_DOC_SRCS))
|
||||
@@ -47,13 +87,7 @@ CODEC_SRCS-yes += $(addprefix vpx_scale/,$(call enabled,SCALE_SRCS))
|
||||
include $(SRC_PATH_BARE)/vpx_ports/vpx_ports.mk
|
||||
CODEC_SRCS-yes += $(addprefix vpx_ports/,$(call enabled,PORTS_SRCS))
|
||||
|
||||
include $(SRC_PATH_BARE)/vpx_dsp/vpx_dsp.mk
|
||||
CODEC_SRCS-yes += $(addprefix vpx_dsp/,$(call enabled,DSP_SRCS))
|
||||
|
||||
include $(SRC_PATH_BARE)/vpx_util/vpx_util.mk
|
||||
CODEC_SRCS-yes += $(addprefix vpx_util/,$(call enabled,UTIL_SRCS))
|
||||
|
||||
ifeq ($(CONFIG_VP8),yes)
|
||||
ifneq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),)
|
||||
VP8_PREFIX=vp8/
|
||||
include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
|
||||
endif
|
||||
@@ -76,7 +110,7 @@ ifeq ($(CONFIG_VP8_DECODER),yes)
|
||||
CODEC_DOC_SECTIONS += vp8 vp8_decoder
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_VP9),yes)
|
||||
ifneq ($(CONFIG_VP9_ENCODER)$(CONFIG_VP9_DECODER),)
|
||||
VP9_PREFIX=vp9/
|
||||
include $(SRC_PATH_BARE)/$(VP9_PREFIX)vp9_common.mk
|
||||
endif
|
||||
@@ -88,7 +122,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-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h
|
||||
INSTALL-LIBS-yes += 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 +140,7 @@ ifeq ($(CONFIG_VP9_DECODER),yes)
|
||||
CODEC_DOC_SECTIONS += vp9 vp9_decoder
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(CONFIG_ENCODERS),yes)
|
||||
CODEC_DOC_SECTIONS += encoder
|
||||
endif
|
||||
@@ -113,12 +148,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)
|
||||
@@ -139,28 +168,22 @@ INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Release/%)
|
||||
INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Debug/%)
|
||||
endif
|
||||
|
||||
CODEC_SRCS-yes += build/make/version.sh
|
||||
CODEC_SRCS-yes += build/make/rtcd.pl
|
||||
CODEC_SRCS-yes += vpx_ports/emmintrin_compat.h
|
||||
CODEC_SRCS-yes += vpx_ports/mem_ops.h
|
||||
CODEC_SRCS-yes += vpx_ports/mem_ops_aligned.h
|
||||
CODEC_SRCS-yes += vpx_ports/vpx_once.h
|
||||
CODEC_SRCS-yes += $(BUILD_PFX)vpx_config.c
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += build/make/version.sh
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += build/make/rtcd.sh
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/emmintrin_compat.h
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/vpx_once.h
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += $(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
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += third_party/x86inc/x86inc.asm
|
||||
endif
|
||||
CODEC_EXPORTS-yes += vpx/exports_com
|
||||
CODEC_EXPORTS-$(BUILD_LIBVPX) += vpx/exports_com
|
||||
CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc
|
||||
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
|
||||
INSTALL-LIBS-yes += include/vpx/vpx_frame_buffer.h
|
||||
INSTALL-LIBS-yes += include/vpx/vpx_image.h
|
||||
INSTALL-LIBS-yes += include/vpx/vpx_external_frame_buffer.h
|
||||
INSTALL-LIBS-yes += include/vpx/vpx_integer.h
|
||||
INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h
|
||||
INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx/vpx_encoder.h
|
||||
@@ -185,20 +208,29 @@ INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(call enabled,CODEC_EXPORTS)
|
||||
# based build systems.
|
||||
libvpx_srcs.txt:
|
||||
@echo " [CREATE] $@"
|
||||
@echo $(CODEC_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@
|
||||
@echo $(CODEC_SRCS) | xargs -n1 echo | 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)
|
||||
|
||||
obj_int_extract.$(VCPROJ_SFX): $(SRC_PATH_BARE)/build/make/obj_int_extract.c
|
||||
@cp $(SRC_PATH_BARE)/build/$(MSVS_ARCH_DIR)/obj_int_extract.bat .
|
||||
@echo " [CREATE] $@"
|
||||
$(qexec)$(GEN_VCPROJ) \
|
||||
--exe \
|
||||
--target=$(TOOLCHAIN) \
|
||||
--name=obj_int_extract \
|
||||
--ver=$(CONFIG_VS_VERSION) \
|
||||
--proj-guid=E1360C65-D375-4335-8057-7ED99CC3F9B2 \
|
||||
$(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
|
||||
--out=$@ $^ \
|
||||
-I. \
|
||||
-I"$(SRC_PATH_BARE)" \
|
||||
|
||||
PROJECTS-$(BUILD_LIBVPX) += obj_int_extract.$(VCPROJ_SFX)
|
||||
|
||||
vpx.def: $(call enabled,CODEC_EXPORTS)
|
||||
@echo " [CREATE] $@"
|
||||
$(qexec)$(SRC_PATH_BARE)/build/make/gen_msvs_def.sh\
|
||||
@@ -206,7 +238,7 @@ vpx.def: $(call enabled,CODEC_EXPORTS)
|
||||
--out=$@ $^
|
||||
CLEAN-OBJS += vpx.def
|
||||
|
||||
vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def
|
||||
vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def obj_int_extract.$(VCPROJ_SFX)
|
||||
@echo " [CREATE] $@"
|
||||
$(qexec)$(GEN_VCPROJ) \
|
||||
$(if $(CONFIG_SHARED),--dll,--lib) \
|
||||
@@ -216,62 +248,43 @@ vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def
|
||||
--proj-guid=DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74 \
|
||||
--module-def=vpx.def \
|
||||
--ver=$(CONFIG_VS_VERSION) \
|
||||
--src-path-bare="$(SRC_PATH_BARE)" \
|
||||
--out=$@ $(CFLAGS) \
|
||||
$(filter-out $(addprefix %, $(ASM_INCLUDES)), $^) \
|
||||
--out=$@ $(CFLAGS) $^ \
|
||||
--src-path-bare="$(SRC_PATH_BARE)" \
|
||||
|
||||
PROJECTS-yes += vpx.$(VCPROJ_SFX)
|
||||
PROJECTS-$(BUILD_LIBVPX) += vpx.$(VCPROJ_SFX)
|
||||
|
||||
vpx.$(VCPROJ_SFX): vpx_config.asm
|
||||
vpx.$(VCPROJ_SFX): $(RTCD)
|
||||
|
||||
endif
|
||||
else
|
||||
LIBVPX_OBJS=$(call objs, $(filter-out $(ASM_INCLUDES), $(CODEC_SRCS)))
|
||||
OBJS-yes += $(LIBVPX_OBJS)
|
||||
LIBS-$(if yes,$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
|
||||
LIBVPX_OBJS=$(call objs,$(CODEC_SRCS))
|
||||
OBJS-$(BUILD_LIBVPX) += $(LIBVPX_OBJS)
|
||||
LIBS-$(if $(BUILD_LIBVPX),$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
|
||||
$(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS)
|
||||
|
||||
SO_VERSION_MAJOR := 5
|
||||
SO_VERSION_MINOR := 0
|
||||
SO_VERSION_PATCH := 0
|
||||
|
||||
BUILD_LIBVPX_SO := $(if $(BUILD_LIBVPX),$(CONFIG_SHARED))
|
||||
|
||||
ifeq ($(filter darwin%,$(TGT_OS)),$(TGT_OS))
|
||||
LIBVPX_SO := libvpx.$(SO_VERSION_MAJOR).dylib
|
||||
SHARED_LIB_SUF := .dylib
|
||||
LIBVPX_SO := libvpx.$(VERSION_MAJOR).dylib
|
||||
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
|
||||
EXPORT_FILE := libvpx.def
|
||||
LIBVPX_SO_SYMLINKS :=
|
||||
LIBVPX_SO_IMPLIB := libvpx_dll.a
|
||||
else
|
||||
LIBVPX_SO := libvpx.so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR).$(SO_VERSION_PATCH)
|
||||
SHARED_LIB_SUF := .so
|
||||
LIBVPX_SO := libvpx.so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
|
||||
EXPORT_FILE := libvpx.ver
|
||||
SYM_LINK := libvpx.so
|
||||
LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, \
|
||||
libvpx.so libvpx.so.$(SO_VERSION_MAJOR) \
|
||||
libvpx.so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR))
|
||||
endif
|
||||
endif
|
||||
libvpx.so libvpx.so.$(VERSION_MAJOR) \
|
||||
libvpx.so.$(VERSION_MAJOR).$(VERSION_MINOR))
|
||||
endif
|
||||
|
||||
LIBS-$(CONFIG_SHARED) += $(BUILD_PFX)$(LIBVPX_SO)\
|
||||
$(notdir $(LIBVPX_SO_SYMLINKS)) \
|
||||
$(if $(LIBVPX_SO_IMPLIB), $(BUILD_PFX)$(LIBVPX_SO_IMPLIB))
|
||||
LIBS-$(BUILD_LIBVPX_SO) += $(BUILD_PFX)$(LIBVPX_SO)\
|
||||
$(notdir $(LIBVPX_SO_SYMLINKS))
|
||||
$(BUILD_PFX)$(LIBVPX_SO): $(LIBVPX_OBJS) $(EXPORT_FILE)
|
||||
$(BUILD_PFX)$(LIBVPX_SO): extralibs += -lm
|
||||
$(BUILD_PFX)$(LIBVPX_SO): SONAME = libvpx.so.$(SO_VERSION_MAJOR)
|
||||
$(BUILD_PFX)$(LIBVPX_SO): SONAME = libvpx.so.$(VERSION_MAJOR)
|
||||
$(BUILD_PFX)$(LIBVPX_SO): EXPORTS_FILE = $(EXPORT_FILE)
|
||||
|
||||
libvpx.ver: $(call enabled,CODEC_EXPORTS)
|
||||
@@ -286,19 +299,6 @@ libvpx.syms: $(call enabled,CODEC_EXPORTS)
|
||||
$(qexec)awk '{print "_"$$2}' $^ >$@
|
||||
CLEAN-OBJS += libvpx.syms
|
||||
|
||||
libvpx.def: $(call enabled,CODEC_EXPORTS)
|
||||
@echo " [CREATE] $@"
|
||||
$(qexec)echo LIBRARY $(LIBVPX_SO:.dll=) INITINSTANCE TERMINSTANCE > $@
|
||||
$(qexec)echo "DATA MULTIPLE NONSHARED" >> $@
|
||||
$(qexec)echo "EXPORTS" >> $@
|
||||
$(qexec)awk '!/vpx_svc_*/ {print "_"$$2}' $^ >>$@
|
||||
CLEAN-OBJS += libvpx.def
|
||||
|
||||
libvpx_dll.a: $(LIBVPX_SO)
|
||||
@echo " [IMPLIB] $@"
|
||||
$(qexec)emximp -o $@ $<
|
||||
CLEAN-OBJS += libvpx_dll.a
|
||||
|
||||
define libvpx_symlink_template
|
||||
$(1): $(2)
|
||||
@echo " [LN] $(2) $$@"
|
||||
@@ -314,12 +314,11 @@ $(eval $(call libvpx_symlink_template,\
|
||||
$(LIBVPX_SO)))
|
||||
|
||||
|
||||
INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBVPX_SO_SYMLINKS)
|
||||
INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBSUBDIR)/$(LIBVPX_SO)
|
||||
INSTALL-LIBS-$(CONFIG_SHARED) += $(if $(LIBVPX_SO_IMPLIB),$(LIBSUBDIR)/$(LIBVPX_SO_IMPLIB))
|
||||
INSTALL-LIBS-$(BUILD_LIBVPX_SO) += $(LIBVPX_SO_SYMLINKS)
|
||||
INSTALL-LIBS-$(BUILD_LIBVPX_SO) += $(LIBSUBDIR)/$(LIBVPX_SO)
|
||||
|
||||
|
||||
LIBS-yes += vpx.pc
|
||||
LIBS-$(BUILD_LIBVPX) += vpx.pc
|
||||
vpx.pc: config.mk libs.mk
|
||||
@echo " [CREATE] $@"
|
||||
$(qexec)echo '# pkg-config file from libvpx $(VERSION_STRING)' > $@
|
||||
@@ -345,6 +344,9 @@ INSTALL_MAPS += $(LIBSUBDIR)/pkgconfig/%.pc %.pc
|
||||
CLEAN-OBJS += vpx.pc
|
||||
endif
|
||||
|
||||
LIBS-$(LIPO_LIBVPX) += libvpx.a
|
||||
$(eval $(if $(LIPO_LIBVPX),$(call lipo_lib_template,libvpx.a)))
|
||||
|
||||
#
|
||||
# Rule to make assembler configuration file from C configuration file
|
||||
#
|
||||
@@ -365,21 +367,15 @@ CLEAN-OBJS += $(BUILD_PFX)vpx_config.asm
|
||||
endif
|
||||
|
||||
#
|
||||
# Add assembler dependencies for configuration.
|
||||
# Add assembler dependencies for configuration and offsets
|
||||
#
|
||||
$(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
|
||||
|
||||
|
||||
$(shell $(SRC_PATH_BARE)/build/make/version.sh "$(SRC_PATH_BARE)" $(BUILD_PFX)vpx_version.h)
|
||||
CLEAN-OBJS += $(BUILD_PFX)vpx_version.h
|
||||
|
||||
#
|
||||
# Add include path for libwebm sources.
|
||||
#
|
||||
ifeq ($(CONFIG_WEBM_IO),yes)
|
||||
CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/libwebm
|
||||
endif
|
||||
|
||||
##
|
||||
## libvpx test directives
|
||||
@@ -389,44 +385,30 @@ LIBVPX_TEST_DATA_PATH ?= .
|
||||
|
||||
include $(SRC_PATH_BARE)/test/test.mk
|
||||
LIBVPX_TEST_SRCS=$(addprefix test/,$(call enabled,LIBVPX_TEST_SRCS))
|
||||
LIBVPX_TEST_BIN=./test_libvpx$(EXE_SFX)
|
||||
LIBVPX_TEST_BINS=./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)
|
||||
|
||||
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))
|
||||
TEST_INTRA_PRED_SPEED_OBJS := $(sort $(call objs,$(TEST_INTRA_PRED_SPEED_SRCS)))
|
||||
libvpx_test_data_url=http://downloads.webmproject.org/test_data/libvpx/$(1)
|
||||
|
||||
libvpx_test_srcs.txt:
|
||||
@echo " [CREATE] $@"
|
||||
@echo $(LIBVPX_TEST_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@
|
||||
@echo $(LIBVPX_TEST_SRCS) | xargs -n1 echo | sort -u > $@
|
||||
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;\
|
||||
[ -x "$$(which shasum)" ] && sha1sum=shasum;\
|
||||
[ -x "$$(which sha1)" ] && sha1sum=sha1;\
|
||||
if [ -n "$${sha1sum}" ]; then\
|
||||
set -e;\
|
||||
$(qexec)if [ -x "$$(which sha1sum)" ]; then\
|
||||
echo "Checking test data:";\
|
||||
for f in $(call enabled,LIBVPX_TEST_DATA); do\
|
||||
grep $$f $(SRC_PATH_BARE)/test/test-data.sha1 |\
|
||||
(cd $(LIBVPX_TEST_DATA_PATH); $${sha1sum} -c);\
|
||||
done; \
|
||||
if [ -n "$(LIBVPX_TEST_DATA)" ]; then\
|
||||
for f in $(call enabled,LIBVPX_TEST_DATA); do\
|
||||
grep $$f $(SRC_PATH_BARE)/test/test-data.sha1 |\
|
||||
(cd $(LIBVPX_TEST_DATA_PATH); sha1sum -c);\
|
||||
done; \
|
||||
fi; \
|
||||
else\
|
||||
echo "Skipping test data integrity check, sha1sum not found.";\
|
||||
fi
|
||||
@@ -459,34 +441,14 @@ test_libvpx.$(VCPROJ_SFX): $(LIBVPX_TEST_SRCS) vpx.$(VCPROJ_SFX) gtest.$(VCPROJ_
|
||||
-D_VARIADIC_MAX=10 \
|
||||
--proj-guid=CD837F5F-52D8-4314-A370-895D614166A7 \
|
||||
--ver=$(CONFIG_VS_VERSION) \
|
||||
--src-path-bare="$(SRC_PATH_BARE)" \
|
||||
$(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
|
||||
--out=$@ $(INTERNAL_CFLAGS) $(CFLAGS) \
|
||||
-I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" \
|
||||
$(if $(CONFIG_WEBM_IO),-I"$(SRC_PATH_BARE)/third_party/libwebm") \
|
||||
-L. -l$(CODEC_LIB) -l$(GTEST_LIB) $^
|
||||
|
||||
PROJECTS-$(CONFIG_MSVS) += test_libvpx.$(VCPROJ_SFX)
|
||||
|
||||
LIBVPX_TEST_BIN := $(addprefix $(TGT_OS:win64=x64)/Release/,$(notdir $(LIBVPX_TEST_BIN)))
|
||||
|
||||
ifneq ($(strip $(TEST_INTRA_PRED_SPEED_OBJS)),)
|
||||
PROJECTS-$(CONFIG_MSVS) += test_intra_pred_speed.$(VCPROJ_SFX)
|
||||
test_intra_pred_speed.$(VCPROJ_SFX): $(TEST_INTRA_PRED_SPEED_SRCS) vpx.$(VCPROJ_SFX) gtest.$(VCPROJ_SFX)
|
||||
@echo " [CREATE] $@"
|
||||
$(qexec)$(GEN_VCPROJ) \
|
||||
--exe \
|
||||
--target=$(TOOLCHAIN) \
|
||||
--name=test_intra_pred_speed \
|
||||
-D_VARIADIC_MAX=10 \
|
||||
--proj-guid=CD837F5F-52D8-4314-A370-895D614166A7 \
|
||||
--ver=$(CONFIG_VS_VERSION) \
|
||||
--src-path-bare="$(SRC_PATH_BARE)" \
|
||||
$(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
|
||||
--out=$@ $(INTERNAL_CFLAGS) $(CFLAGS) \
|
||||
-I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" \
|
||||
-L. -l$(CODEC_LIB) -l$(GTEST_LIB) $^
|
||||
endif # TEST_INTRA_PRED_SPEED
|
||||
LIBVPX_TEST_BINS := $(addprefix $(TGT_OS:win64=x64)/Release/,$(notdir $(LIBVPX_TEST_BINS)))
|
||||
endif
|
||||
else
|
||||
|
||||
@@ -497,54 +459,45 @@ ifeq ($(filter win%,$(TGT_OS)),$(TGT_OS))
|
||||
# Disabling pthreads globally will cause issues on darwin and possibly elsewhere
|
||||
$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += -DGTEST_HAS_PTHREAD=0
|
||||
endif
|
||||
GTEST_INCLUDES := -I$(SRC_PATH_BARE)/third_party/googletest/src
|
||||
GTEST_INCLUDES += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
|
||||
$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES)
|
||||
OBJS-yes += $(GTEST_OBJS)
|
||||
LIBS-yes += $(BUILD_PFX)libgtest.a $(BUILD_PFX)libgtest_g.a
|
||||
$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
|
||||
$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
|
||||
OBJS-$(BUILD_LIBVPX) += $(GTEST_OBJS)
|
||||
LIBS-$(BUILD_LIBVPX) += $(BUILD_PFX)libgtest.a $(BUILD_PFX)libgtest_g.a
|
||||
$(BUILD_PFX)libgtest_g.a: $(GTEST_OBJS)
|
||||
|
||||
LIBVPX_TEST_OBJS=$(sort $(call objs,$(LIBVPX_TEST_SRCS)))
|
||||
$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES)
|
||||
OBJS-yes += $(LIBVPX_TEST_OBJS)
|
||||
BINS-yes += $(LIBVPX_TEST_BIN)
|
||||
$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
|
||||
$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
|
||||
OBJS-$(BUILD_LIBVPX) += $(LIBVPX_TEST_OBJS)
|
||||
BINS-$(BUILD_LIBVPX) += $(LIBVPX_TEST_BINS)
|
||||
|
||||
CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx)
|
||||
CODEC_LIB_SUF=$(if $(CONFIG_SHARED),$(SHARED_LIB_SUF),.a)
|
||||
TEST_LIBS := lib$(CODEC_LIB)$(CODEC_LIB_SUF) libgtest.a
|
||||
$(LIBVPX_TEST_BIN): $(TEST_LIBS)
|
||||
$(eval $(call linkerxx_template,$(LIBVPX_TEST_BIN), \
|
||||
$(LIBVPX_TEST_OBJS) \
|
||||
-L. -lvpx -lgtest $(extralibs) -lm))
|
||||
CODEC_LIB_SUF=$(if $(CONFIG_SHARED),.so,.a)
|
||||
$(foreach bin,$(LIBVPX_TEST_BINS),\
|
||||
$(if $(BUILD_LIBVPX),$(eval $(bin): \
|
||||
lib$(CODEC_LIB)$(CODEC_LIB_SUF) libgtest.a ))\
|
||||
$(if $(BUILD_LIBVPX),$(eval $(call linkerxx_template,$(bin),\
|
||||
$(LIBVPX_TEST_OBJS) \
|
||||
-L. -lvpx -lgtest $(extralibs) -lm)\
|
||||
)))\
|
||||
$(if $(LIPO_LIBS),$(eval $(call lipo_bin_template,$(bin))))\
|
||||
|
||||
ifneq ($(strip $(TEST_INTRA_PRED_SPEED_OBJS)),)
|
||||
$(TEST_INTRA_PRED_SPEED_OBJS) $(TEST_INTRA_PRED_SPEED_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES)
|
||||
OBJS-yes += $(TEST_INTRA_PRED_SPEED_OBJS)
|
||||
BINS-yes += $(TEST_INTRA_PRED_SPEED_BIN)
|
||||
|
||||
$(TEST_INTRA_PRED_SPEED_BIN): $(TEST_LIBS)
|
||||
$(eval $(call linkerxx_template,$(TEST_INTRA_PRED_SPEED_BIN), \
|
||||
$(TEST_INTRA_PRED_SPEED_OBJS) \
|
||||
-L. -lvpx -lgtest $(extralibs) -lm))
|
||||
endif # TEST_INTRA_PRED_SPEED
|
||||
|
||||
endif # CONFIG_UNIT_TESTS
|
||||
endif
|
||||
|
||||
# Install test sources only if codec source is included
|
||||
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(patsubst $(SRC_PATH_BARE)/%,%,\
|
||||
$(shell find $(SRC_PATH_BARE)/third_party/googletest -type f))
|
||||
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(LIBVPX_TEST_SRCS)
|
||||
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(TEST_INTRA_PRED_SPEED_SRCS)
|
||||
|
||||
define test_shard_template
|
||||
test:: test_shard.$(1)
|
||||
test-no-data-check:: test_shard_ndc.$(1)
|
||||
test_shard.$(1) test_shard_ndc.$(1): $(LIBVPX_TEST_BIN)
|
||||
test_shard.$(1): $(LIBVPX_TEST_BINS) testdata
|
||||
@set -e; \
|
||||
export GTEST_SHARD_INDEX=$(1); \
|
||||
export GTEST_TOTAL_SHARDS=$(2); \
|
||||
$(LIBVPX_TEST_BIN)
|
||||
test_shard.$(1): testdata
|
||||
for t in $(LIBVPX_TEST_BINS); do \
|
||||
export GTEST_SHARD_INDEX=$(1); \
|
||||
export GTEST_TOTAL_SHARDS=$(2); \
|
||||
$$$$t; \
|
||||
done
|
||||
.PHONY: test_shard.$(1)
|
||||
endef
|
||||
|
||||
@@ -563,65 +516,12 @@ libs.doxy: $(CODEC_DOC_SRCS)
|
||||
@echo " [CREATE] $@"
|
||||
@rm -f $@
|
||||
@echo "INPUT += $^" >> $@
|
||||
@echo "PREDEFINED = VPX_CODEC_DISABLE_COMPAT" >> $@
|
||||
@echo "INCLUDE_PATH += ." >> $@;
|
||||
@echo "ENABLED_SECTIONS += $(sort $(CODEC_DOC_SECTIONS))" >> $@
|
||||
|
||||
## Generate rtcd.h for all objects
|
||||
ifeq ($(CONFIG_DEPENDENCY_TRACKING),yes)
|
||||
$(OBJS-yes:.o=.d): $(RTCD)
|
||||
else
|
||||
$(OBJS-yes): $(RTCD)
|
||||
endif
|
||||
|
||||
## Update the global src list
|
||||
SRCS += $(CODEC_SRCS) $(LIBVPX_TEST_SRCS) $(GTEST_SRCS)
|
||||
|
||||
##
|
||||
## vpxdec/vpxenc tests.
|
||||
##
|
||||
ifeq ($(CONFIG_UNIT_TESTS),yes)
|
||||
TEST_BIN_PATH = .
|
||||
ifeq ($(CONFIG_MSVS),yes)
|
||||
# MSVC will build both Debug and Release configurations of tools in a
|
||||
# sub directory named for the current target. Assume the user wants to
|
||||
# run the Release tools, and assign TEST_BIN_PATH accordingly.
|
||||
# TODO(tomfinegan): Is this adequate for ARM?
|
||||
# TODO(tomfinegan): Support running the debug versions of tools?
|
||||
TEST_BIN_PATH := $(addsuffix /$(TGT_OS:win64=x64)/Release, $(TEST_BIN_PATH))
|
||||
endif
|
||||
utiltest utiltest-no-data-check:
|
||||
$(qexec)$(SRC_PATH_BARE)/test/vpxdec.sh \
|
||||
--test-data-path $(LIBVPX_TEST_DATA_PATH) \
|
||||
--bin-path $(TEST_BIN_PATH)
|
||||
$(qexec)$(SRC_PATH_BARE)/test/vpxenc.sh \
|
||||
--test-data-path $(LIBVPX_TEST_DATA_PATH) \
|
||||
--bin-path $(TEST_BIN_PATH)
|
||||
utiltest: testdata
|
||||
else
|
||||
utiltest utiltest-no-data-check:
|
||||
@echo Unit tests must be enabled to make the utiltest target.
|
||||
endif
|
||||
|
||||
##
|
||||
## Example tests.
|
||||
##
|
||||
ifeq ($(CONFIG_UNIT_TESTS),yes)
|
||||
# All non-MSVC targets output example targets in a sub dir named examples.
|
||||
EXAMPLES_BIN_PATH = examples
|
||||
ifeq ($(CONFIG_MSVS),yes)
|
||||
# MSVC will build both Debug and Release configurations of the examples in a
|
||||
# sub directory named for the current target. Assume the user wants to
|
||||
# run the Release tools, and assign EXAMPLES_BIN_PATH accordingly.
|
||||
# TODO(tomfinegan): Is this adequate for ARM?
|
||||
# TODO(tomfinegan): Support running the debug versions of tools?
|
||||
EXAMPLES_BIN_PATH := $(TGT_OS:win64=x64)/Release
|
||||
endif
|
||||
exampletest exampletest-no-data-check: examples
|
||||
$(qexec)$(SRC_PATH_BARE)/test/examples.sh \
|
||||
--test-data-path $(LIBVPX_TEST_DATA_PATH) \
|
||||
--bin-path $(EXAMPLES_BIN_PATH)
|
||||
exampletest: testdata
|
||||
else
|
||||
exampletest exampletest-no-data-check:
|
||||
@echo Unit tests must be enabled to make the exampletest target.
|
||||
endif
|
||||
|
||||
22
mainpage.dox
22
mainpage.dox
@@ -1,4 +1,4 @@
|
||||
/*!\mainpage WebM Codec SDK
|
||||
/*!\mainpage WebM VP8 Codec SDK
|
||||
|
||||
\section main_contents Page Contents
|
||||
- \ref main_intro
|
||||
@@ -6,11 +6,11 @@
|
||||
- \ref main_support
|
||||
|
||||
\section main_intro Introduction
|
||||
Welcome to the WebM Codec SDK. This SDK allows you to integrate your
|
||||
applications with the VP8 and VP9 video codecs, high quality, royalty free,
|
||||
open source codecs deployed on billions of computers and devices worldwide.
|
||||
Welcome to the WebM VP8 Codec SDK. This SDK allows you to integrate your
|
||||
applications with the VP8 video codec, a high quality, royalty free, open
|
||||
source codec deployed on millions of computers and devices worldwide.
|
||||
|
||||
This distribution of the WebM Codec SDK includes the following support:
|
||||
This distribution of the WebM VP8 Codec SDK includes the following support:
|
||||
|
||||
\if vp8_encoder
|
||||
- \ref vp8_encoder
|
||||
@@ -28,12 +28,12 @@
|
||||
- Read the \ref samples "sample code" for examples of how to interact with the
|
||||
codec.
|
||||
- \ref codec reference
|
||||
\if encoder
|
||||
- \ref encoder reference
|
||||
\endif
|
||||
\if decoder
|
||||
- \ref decoder reference
|
||||
\endif
|
||||
\if encoder
|
||||
- \ref encoder reference
|
||||
\endif
|
||||
\if decoder
|
||||
- \ref decoder reference
|
||||
\endif
|
||||
|
||||
\section main_support Support Options & FAQ
|
||||
The WebM project is an open source project supported by its community. For
|
||||
|
||||
44
md5_utils.c
44
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) {
|
||||
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,27 +147,16 @@ 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)
|
||||
|
||||
#if defined(__clang__) && defined(__has_attribute)
|
||||
#if __has_attribute(no_sanitize)
|
||||
#define VPX_NO_UNSIGNED_OVERFLOW_CHECK \
|
||||
__attribute__((no_sanitize("unsigned-integer-overflow")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef VPX_NO_UNSIGNED_OVERFLOW_CHECK
|
||||
#define VPX_NO_UNSIGNED_OVERFLOW_CHECK
|
||||
#endif
|
||||
#define MD5STEP(f,w,x,y,z,in,s) \
|
||||
(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* 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]) {
|
||||
void
|
||||
MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) {
|
||||
register UWORD32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
@@ -244,6 +238,4 @@ VPX_NO_UNSIGNED_OVERFLOW_CHECK void MD5Transform(UWORD32 buf[4],
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
#undef VPX_NO_UNSIGNED_OVERFLOW_CHECK
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
#ifndef MD5_UTILS_H_
|
||||
#define MD5_UTILS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define md5byte unsigned char
|
||||
#define UWORD32 unsigned int
|
||||
|
||||
@@ -42,8 +38,4 @@ void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // MD5_UTILS_H_
|
||||
|
||||
40
nestegg/.gitignore
vendored
Normal file
40
nestegg/.gitignore
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
*.lo
|
||||
*.o
|
||||
*.swp
|
||||
*~
|
||||
.deps
|
||||
.dirstamp
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
_stdint.h
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
docs/Doxyfile
|
||||
docs/doxygen-build.stamp
|
||||
docs/html
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
missing
|
||||
nestegg-uninstalled.pc
|
||||
nestegg.pc
|
||||
src/.dirstamp
|
||||
src/libnestegg.la
|
||||
stamp-h1
|
||||
test/test
|
||||
include/nestegg/nestegg-stdint.h
|
||||
1
nestegg/AUTHORS
Normal file
1
nestegg/AUTHORS
Normal file
@@ -0,0 +1 @@
|
||||
Matthew Gregan <kinetik@flim.org>
|
||||
8
nestegg/INSTALL
Normal file
8
nestegg/INSTALL
Normal file
@@ -0,0 +1,8 @@
|
||||
Build instructions for libnestegg
|
||||
=================================
|
||||
|
||||
0. Change directory into the source directory.
|
||||
1. Run |autoreconf --install| to generate configure.
|
||||
2. Run |./configure| to configure the build.
|
||||
3. Run |make| to build.
|
||||
4. Run |make check| to run the test suite.
|
||||
13
nestegg/LICENSE
Normal file
13
nestegg/LICENSE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright © 2010 Mozilla Foundation
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
51
nestegg/Makefile.am
Normal file
51
nestegg/Makefile.am
Normal file
@@ -0,0 +1,51 @@
|
||||
AUTOMAKE_OPTIONS = foreign 1.11 no-dist-gzip dist-bzip2 subdir-objects
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I. -I$(top_srcdir)/halloc
|
||||
AM_CFLAGS = -ansi -pedantic -Wall -Wextra -Wno-long-long -O0 -g
|
||||
|
||||
SUBDIRS = docs
|
||||
|
||||
EXTRA_DIST = \
|
||||
AUTHORS README LICENSE \
|
||||
nestegg-uninstalled.pc.in \
|
||||
m4/as-ac-expand.m4 \
|
||||
m4/pkg.m4 \
|
||||
m4/ax_create_stdint_h.m4 \
|
||||
halloc/src/halloc.c \
|
||||
halloc/halloc.h \
|
||||
halloc/src/align.h \
|
||||
halloc/src/hlist.h \
|
||||
halloc/src/macros.h
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = nestegg.pc
|
||||
|
||||
nesteggincludedir = $(includedir)/nestegg
|
||||
nestegginclude_HEADERS = include/nestegg/nestegg.h include/nestegg/nestegg-stdint.h
|
||||
|
||||
lib_LTLIBRARIES = src/libnestegg.la
|
||||
|
||||
src_libnestegg_la_SOURCES = \
|
||||
src/nestegg.c \
|
||||
halloc/src/halloc.c \
|
||||
halloc/halloc.h \
|
||||
halloc/src/align.h \
|
||||
halloc/src/hlist.h \
|
||||
halloc/src/macros.h
|
||||
|
||||
check_PROGRAMS = test/test
|
||||
|
||||
test_test_SOURCES = test/test.c
|
||||
test_test_LDADD = src/libnestegg.la
|
||||
|
||||
DISTCLEANFILES = include/nestegg/nestegg-stdint.h
|
||||
|
||||
dist-hook:
|
||||
find $(distdir) -type d -name '.git' | xargs rm -rf
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
||||
6
nestegg/README
Normal file
6
nestegg/README
Normal file
@@ -0,0 +1,6 @@
|
||||
See INSTALL for build instructions.
|
||||
|
||||
Licensed under an ISC-style license. See LICENSE for details.
|
||||
|
||||
The source under the halloc/ directory is licensed under a BSD license. See
|
||||
halloc/halloc.h for details.
|
||||
21
nestegg/TODO
Normal file
21
nestegg/TODO
Normal file
@@ -0,0 +1,21 @@
|
||||
- Document when read, seek, tell callbacks are used.
|
||||
- Add an automated testsuite.
|
||||
- Test (and fix, if necessary) support for unknown sizes.
|
||||
- Test (and fix, if necessary) support for large files.
|
||||
- Read past unknown elements rather than seeking.
|
||||
- Try to handle unknown elements with unknown sizes.
|
||||
- Formalize handling of default element values.
|
||||
- Try to resynchronize stream when read_block fails so that failure to parse
|
||||
a single block can be treated as non-fatal.
|
||||
- Make logging more useful to API users.
|
||||
- Avoid reparsing Cues and ignore any SeekHead at end of file.
|
||||
- Optionally build a Cue index as Clusters are parsed.
|
||||
- Support seeking without Cues.
|
||||
- Avoid building a list of Clusters as they are parsed and retain only the
|
||||
last one parsed.
|
||||
- Add an asynchronous error code to struct nestegg and ensure that API calls
|
||||
continue to fail safely one a fatal error has been returned.
|
||||
- Modify parser/data structures to provide a clean separation. Perhaps the
|
||||
parser should return a generic tree of nodes that a second pass uses to
|
||||
initialize the main data structures.
|
||||
- Use pool allocator for all allocations.
|
||||
124
nestegg/configure.ac
Normal file
124
nestegg/configure.ac
Normal file
@@ -0,0 +1,124 @@
|
||||
dnl ------------------------------------------------
|
||||
dnl Initialization and Versioning
|
||||
dnl ------------------------------------------------
|
||||
|
||||
AC_INIT(libnestegg,[0.1git])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_SRCDIR([src/nestegg.c])
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl Library versioning
|
||||
dnl CURRENT, REVISION, AGE
|
||||
dnl - library source changed -> increment REVISION
|
||||
dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
|
||||
dnl - interfaces added -> increment AGE
|
||||
dnl - interfaces removed -> AGE = 0
|
||||
|
||||
NESTEGG_CURRENT=0
|
||||
NESTEGG_REVISION=0
|
||||
NESTEGG_AGE=1
|
||||
AC_SUBST(NESTEGG_CURRENT)
|
||||
AC_SUBST(NESTEGG_REVISION)
|
||||
AC_SUBST(NESTEGG_AGE)
|
||||
|
||||
|
||||
dnl --------------------------------------------------
|
||||
dnl Check for programs
|
||||
dnl --------------------------------------------------
|
||||
|
||||
dnl save $CFLAGS since AC_PROG_CC likes to insert "-g -O2"
|
||||
dnl if $CFLAGS is blank
|
||||
cflags_save="$CFLAGS"
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
CFLAGS="$cflags_save"
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
dnl Check for doxygen
|
||||
AC_ARG_ENABLE([doc],
|
||||
AS_HELP_STRING([--enable-doc], [Build API documentation]),
|
||||
[ac_enable_doc=$enableval], [ac_enable_doc=auto])
|
||||
|
||||
if test "x$ac_enable_doc" != "xno"; then
|
||||
AC_CHECK_PROG(HAVE_DOXYGEN, doxygen, true, false)
|
||||
|
||||
if test "x$HAVE_DOXYGEN" = "xfalse" -a "x$ac_enable_doc" = "xyes"; then
|
||||
AC_MSG_ERROR([*** API documentation explicitly requested but Doxygen not found])
|
||||
fi
|
||||
else
|
||||
HAVE_DOXYGEN=false
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_DOXYGEN,$HAVE_DOXYGEN)
|
||||
if test $HAVE_DOXYGEN = "false"; then
|
||||
AC_MSG_WARN([*** doxygen not found, API documentation will not be built])
|
||||
fi
|
||||
|
||||
# Generate portable stdint.h replacement
|
||||
AX_CREATE_STDINT_H(include/nestegg/nestegg-stdint.h)
|
||||
|
||||
# Test whenever ld supports -version-script
|
||||
AC_PROG_LD
|
||||
AC_PROG_LD_GNU
|
||||
AC_MSG_CHECKING([how to control symbol export])
|
||||
|
||||
dnl --------------------------------------------------
|
||||
dnl Do substitutions
|
||||
dnl --------------------------------------------------
|
||||
|
||||
AC_SUBST(DEBUG)
|
||||
AC_SUBST(PROFILE)
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
docs/Makefile
|
||||
docs/Doxyfile
|
||||
nestegg.pc
|
||||
nestegg-uninstalled.pc
|
||||
])
|
||||
|
||||
AS_AC_EXPAND(LIBDIR, ${libdir})
|
||||
AS_AC_EXPAND(INCLUDEDIR, ${includedir})
|
||||
AS_AC_EXPAND(BINDIR, ${bindir})
|
||||
AS_AC_EXPAND(DOCDIR, ${docdir})
|
||||
|
||||
if test $HAVE_DOXYGEN = "false"; then
|
||||
doc_build="no"
|
||||
else
|
||||
doc_build="yes"
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([
|
||||
------------------------------------------------------------------------
|
||||
$PACKAGE $VERSION: Automatic configuration OK.
|
||||
|
||||
General configuration:
|
||||
|
||||
API Documentation: .......... ${doc_build}
|
||||
|
||||
Installation paths:
|
||||
|
||||
libnestegg: .................. ${LIBDIR}
|
||||
C header files: .............. ${INCLUDEDIR}/nestegg
|
||||
Documentation: ............... ${DOCDIR}
|
||||
|
||||
Building:
|
||||
|
||||
Type 'make' to compile $PACKAGE.
|
||||
|
||||
Type 'make install' to install $PACKAGE.
|
||||
|
||||
Example programs will be built but not installed.
|
||||
------------------------------------------------------------------------
|
||||
])
|
||||
|
||||
1551
nestegg/docs/Doxyfile.in
Normal file
1551
nestegg/docs/Doxyfile.in
Normal file
File diff suppressed because it is too large
Load Diff
38
nestegg/docs/Makefile.am
Normal file
38
nestegg/docs/Makefile.am
Normal file
@@ -0,0 +1,38 @@
|
||||
doc_DATA = doxygen-build.stamp
|
||||
|
||||
EXTRA_DIST = Doxyfile.in
|
||||
|
||||
if HAVE_DOXYGEN
|
||||
doxygen-build.stamp: Doxyfile
|
||||
doxygen
|
||||
touch doxygen-build.stamp
|
||||
else
|
||||
doxygen-build.stamp:
|
||||
echo "*** Warning: Doxygen not found; documentation will not be built."
|
||||
touch doxygen-build.stamp
|
||||
endif
|
||||
|
||||
dist_docdir = $(distdir)/libnestegg
|
||||
|
||||
dist-hook:
|
||||
if test -d html; then \
|
||||
mkdir $(dist_docdir); \
|
||||
echo -n "copying built documenation..."; \
|
||||
cp -rp html $(dist_docdir)/html; \
|
||||
echo "OK"; \
|
||||
fi
|
||||
|
||||
|
||||
install-data-local: doxygen-build.stamp
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdir)
|
||||
if test -d html; then \
|
||||
cp -rp html $(DESTDIR)$(docdir)/html; \
|
||||
fi
|
||||
|
||||
uninstall-local:
|
||||
rm -rf $(DESTDIR)$(docdir)
|
||||
|
||||
clean-local:
|
||||
if test -d html; then rm -rf html; fi
|
||||
if test -f doxygen-build.stamp; then rm -f doxygen-build.stamp; fi
|
||||
|
||||
45
nestegg/halloc/README
Normal file
45
nestegg/halloc/README
Normal file
@@ -0,0 +1,45 @@
|
||||
halloc 1.2.1
|
||||
============
|
||||
|
||||
Hierarchical memory heap interface - an extension to standard
|
||||
malloc/free interface that simplifies tasks of memory disposal
|
||||
when allocated structures exhibit hierarchical properties.
|
||||
|
||||
http://swapped.cc/halloc
|
||||
=
|
||||
To build libhalloc.a with GNU tools run
|
||||
make
|
||||
|
||||
To install in /usr/include and /usr/lib
|
||||
make install
|
||||
|
||||
To cleanup the build files
|
||||
make clean
|
||||
=
|
||||
halloc-1.2.1
|
||||
* fixed a double-free bug in _set_allocator() as per
|
||||
Matthew Gregan comments
|
||||
|
||||
* switched to using NULL instead of 0 where applicable
|
||||
|
||||
halloc-1.2.0
|
||||
* added missing <string.h> include to halloc.c
|
||||
|
||||
* improved standard compliance thanks to the feedback
|
||||
received from Stan Tobias. Two things were fixed -
|
||||
|
||||
- hblock_t structure no longer uses zero-sized 'data'
|
||||
array, which happened to be common, but non-standard
|
||||
extension;
|
||||
|
||||
- secondly, added the code to test the behaviour of
|
||||
realloc(ptr, 0). Standard allows it NOT to act as
|
||||
free(), in which case halloc will use its own version
|
||||
of allocator calling free() when neccessary.
|
||||
|
||||
halloc-1.1.0
|
||||
* initial public release (rewrite of hhmalloc library)
|
||||
|
||||
=============================================================================
|
||||
Copyright (c) 2004-2010, Alex Pankratov (ap@swapped.cc). All rights reserved.
|
||||
|
||||
43
nestegg/halloc/halloc.h
Normal file
43
nestegg/halloc/halloc.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_HALLOC_H_
|
||||
#define _LIBP_HALLOC_H_
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
/*
|
||||
* Core API
|
||||
*/
|
||||
void * halloc (void * block, size_t len);
|
||||
void hattach(void * block, void * parent);
|
||||
|
||||
/*
|
||||
* standard malloc/free api
|
||||
*/
|
||||
void * h_malloc (size_t len);
|
||||
void * h_calloc (size_t n, size_t len);
|
||||
void * h_realloc(void * p, size_t len);
|
||||
void h_free (void * p);
|
||||
char * h_strdup (const char * str);
|
||||
|
||||
/*
|
||||
* the underlying allocator
|
||||
*/
|
||||
typedef void * (* realloc_t)(void * ptr, size_t len);
|
||||
|
||||
extern realloc_t halloc_allocator;
|
||||
|
||||
#endif
|
||||
|
||||
36
nestegg/halloc/src/align.h
Normal file
36
nestegg/halloc/src/align.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_ALIGN_H_
|
||||
#define _LIBP_ALIGN_H_
|
||||
|
||||
/*
|
||||
* a type with the most strict alignment requirements
|
||||
*/
|
||||
union max_align
|
||||
{
|
||||
char c;
|
||||
short s;
|
||||
long l;
|
||||
int i;
|
||||
float f;
|
||||
double d;
|
||||
void * v;
|
||||
void (*q)(void);
|
||||
};
|
||||
|
||||
typedef union max_align max_align_t;
|
||||
|
||||
#endif
|
||||
|
||||
254
nestegg/halloc/src/halloc.c
Normal file
254
nestegg/halloc/src/halloc.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2004i-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* realloc */
|
||||
#include <string.h> /* memset & co */
|
||||
|
||||
#include "../halloc.h"
|
||||
#include "align.h"
|
||||
#include "hlist.h"
|
||||
|
||||
/*
|
||||
* block control header
|
||||
*/
|
||||
typedef struct hblock
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
#define HH_MAGIC 0x20040518L
|
||||
long magic;
|
||||
#endif
|
||||
hlist_item_t siblings; /* 2 pointers */
|
||||
hlist_head_t children; /* 1 pointer */
|
||||
max_align_t data[1]; /* not allocated, see below */
|
||||
|
||||
} hblock_t;
|
||||
|
||||
#define sizeof_hblock offsetof(hblock_t, data)
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
realloc_t halloc_allocator = NULL;
|
||||
|
||||
#define allocator halloc_allocator
|
||||
|
||||
/*
|
||||
* static methods
|
||||
*/
|
||||
static void _set_allocator(void);
|
||||
static void * _realloc(void * ptr, size_t n);
|
||||
|
||||
static int _relate(hblock_t * b, hblock_t * p);
|
||||
static void _free_children(hblock_t * p);
|
||||
|
||||
/*
|
||||
* Core API
|
||||
*/
|
||||
void * halloc(void * ptr, size_t len)
|
||||
{
|
||||
hblock_t * p;
|
||||
|
||||
/* set up default allocator */
|
||||
if (! allocator)
|
||||
{
|
||||
_set_allocator();
|
||||
assert(allocator);
|
||||
}
|
||||
|
||||
/* calloc */
|
||||
if (! ptr)
|
||||
{
|
||||
if (! len)
|
||||
return NULL;
|
||||
|
||||
p = allocator(0, len + sizeof_hblock);
|
||||
if (! p)
|
||||
return NULL;
|
||||
#ifndef NDEBUG
|
||||
p->magic = HH_MAGIC;
|
||||
#endif
|
||||
hlist_init(&p->children);
|
||||
hlist_init_item(&p->siblings);
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
p = structof(ptr, hblock_t, data);
|
||||
assert(p->magic == HH_MAGIC);
|
||||
|
||||
/* realloc */
|
||||
if (len)
|
||||
{
|
||||
p = allocator(p, len + sizeof_hblock);
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
hlist_relink(&p->siblings);
|
||||
hlist_relink_head(&p->children);
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
/* free */
|
||||
_free_children(p);
|
||||
hlist_del(&p->siblings);
|
||||
allocator(p, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hattach(void * block, void * parent)
|
||||
{
|
||||
hblock_t * b, * p;
|
||||
|
||||
if (! block)
|
||||
{
|
||||
assert(! parent);
|
||||
return;
|
||||
}
|
||||
|
||||
/* detach */
|
||||
b = structof(block, hblock_t, data);
|
||||
assert(b->magic == HH_MAGIC);
|
||||
|
||||
hlist_del(&b->siblings);
|
||||
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
/* attach */
|
||||
p = structof(parent, hblock_t, data);
|
||||
assert(p->magic == HH_MAGIC);
|
||||
|
||||
/* sanity checks */
|
||||
assert(b != p); /* trivial */
|
||||
assert(! _relate(p, b)); /* heavy ! */
|
||||
|
||||
hlist_add(&p->children, &b->siblings);
|
||||
}
|
||||
|
||||
/*
|
||||
* malloc/free api
|
||||
*/
|
||||
void * h_malloc(size_t len)
|
||||
{
|
||||
return halloc(0, len);
|
||||
}
|
||||
|
||||
void * h_calloc(size_t n, size_t len)
|
||||
{
|
||||
void * ptr = halloc(0, len*=n);
|
||||
return ptr ? memset(ptr, 0, len) : NULL;
|
||||
}
|
||||
|
||||
void * h_realloc(void * ptr, size_t len)
|
||||
{
|
||||
return halloc(ptr, len);
|
||||
}
|
||||
|
||||
void h_free(void * ptr)
|
||||
{
|
||||
halloc(ptr, 0);
|
||||
}
|
||||
|
||||
char * h_strdup(const char * str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char * ptr = halloc(0, len + 1);
|
||||
return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* static stuff
|
||||
*/
|
||||
static void _set_allocator(void)
|
||||
{
|
||||
void * p;
|
||||
assert(! allocator);
|
||||
|
||||
/*
|
||||
* the purpose of the test below is to check the behaviour
|
||||
* of realloc(ptr, 0), which is defined in the standard
|
||||
* as an implementation-specific. if it returns zero,
|
||||
* then it's equivalent to free(). it can however return
|
||||
* non-zero, in which case it cannot be used for freeing
|
||||
* memory blocks and we'll need to supply our own version
|
||||
*
|
||||
* Thanks to Stan Tobias for pointing this tricky part out.
|
||||
*/
|
||||
allocator = realloc;
|
||||
if (! (p = malloc(1)))
|
||||
/* hmm */
|
||||
return;
|
||||
|
||||
if ((p = realloc(p, 0)))
|
||||
{
|
||||
/* realloc cannot be used as free() */
|
||||
allocator = _realloc;
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static void * _realloc(void * ptr, size_t n)
|
||||
{
|
||||
/*
|
||||
* free'ing realloc()
|
||||
*/
|
||||
if (n)
|
||||
return realloc(ptr, n);
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _relate(hblock_t * b, hblock_t * p)
|
||||
{
|
||||
hlist_item_t * i;
|
||||
|
||||
if (!b || !p)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* since there is no 'parent' pointer, which would've allowed
|
||||
* O(log(n)) upward traversal, the check must use O(n) downward
|
||||
* iteration of the entire hierarchy; and this can be VERY SLOW
|
||||
*/
|
||||
hlist_for_each(i, &p->children)
|
||||
{
|
||||
hblock_t * q = structof(i, hblock_t, siblings);
|
||||
if (q == b || _relate(b, q))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _free_children(hblock_t * p)
|
||||
{
|
||||
hlist_item_t * i, * tmp;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
* this catches loops in hierarchy with almost zero
|
||||
* overhead (compared to _relate() running time)
|
||||
*/
|
||||
assert(p && p->magic == HH_MAGIC);
|
||||
p->magic = 0;
|
||||
#endif
|
||||
hlist_for_each_safe(i, tmp, &p->children)
|
||||
{
|
||||
hblock_t * q = structof(i, hblock_t, siblings);
|
||||
_free_children(q);
|
||||
allocator(q, 0);
|
||||
}
|
||||
}
|
||||
|
||||
136
nestegg/halloc/src/hlist.h
Normal file
136
nestegg/halloc/src/hlist.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_HLIST_H_
|
||||
#define _LIBP_HLIST_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include "macros.h" /* static_inline */
|
||||
|
||||
/*
|
||||
* weak double-linked list w/ tail sentinel
|
||||
*/
|
||||
typedef struct hlist_head hlist_head_t;
|
||||
typedef struct hlist_item hlist_item_t;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
struct hlist_head
|
||||
{
|
||||
hlist_item_t * next;
|
||||
};
|
||||
|
||||
struct hlist_item
|
||||
{
|
||||
hlist_item_t * next;
|
||||
hlist_item_t ** prev;
|
||||
};
|
||||
|
||||
/*
|
||||
* shared tail sentinel
|
||||
*/
|
||||
struct hlist_item hlist_null;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
#define __hlist_init(h) { &hlist_null }
|
||||
#define __hlist_init_item(i) { &hlist_null, &(i).next }
|
||||
|
||||
static_inline void hlist_init(hlist_head_t * h);
|
||||
static_inline void hlist_init_item(hlist_item_t * i);
|
||||
|
||||
/* static_inline void hlist_purge(hlist_head_t * h); */
|
||||
|
||||
/* static_inline bool_t hlist_empty(const hlist_head_t * h); */
|
||||
|
||||
/* static_inline hlist_item_t * hlist_head(const hlist_head_t * h); */
|
||||
|
||||
/* static_inline hlist_item_t * hlist_next(const hlist_item_t * i); */
|
||||
/* static_inline hlist_item_t * hlist_prev(const hlist_item_t * i,
|
||||
const hlist_head_t * h); */
|
||||
|
||||
static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i);
|
||||
|
||||
/* static_inline void hlist_add_prev(hlist_item_t * l, hlist_item_t * i); */
|
||||
/* static_inline void hlist_add_next(hlist_item_t * l, hlist_item_t * i); */
|
||||
|
||||
static_inline void hlist_del(hlist_item_t * i);
|
||||
|
||||
static_inline void hlist_relink(hlist_item_t * i);
|
||||
static_inline void hlist_relink_head(hlist_head_t * h);
|
||||
|
||||
#define hlist_for_each(i, h) \
|
||||
for (i = (h)->next; i != &hlist_null; i = i->next)
|
||||
|
||||
#define hlist_for_each_safe(i, tmp, h) \
|
||||
for (i = (h)->next, tmp = i->next; \
|
||||
i!= &hlist_null; \
|
||||
i = tmp, tmp = i->next)
|
||||
|
||||
/*
|
||||
* static
|
||||
*/
|
||||
static_inline void hlist_init(hlist_head_t * h)
|
||||
{
|
||||
assert(h);
|
||||
h->next = &hlist_null;
|
||||
}
|
||||
|
||||
static_inline void hlist_init_item(hlist_item_t * i)
|
||||
{
|
||||
assert(i);
|
||||
i->prev = &i->next;
|
||||
i->next = &hlist_null;
|
||||
}
|
||||
|
||||
static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i)
|
||||
{
|
||||
hlist_item_t * next;
|
||||
assert(h && i);
|
||||
|
||||
next = i->next = h->next;
|
||||
next->prev = &i->next;
|
||||
h->next = i;
|
||||
i->prev = &h->next;
|
||||
}
|
||||
|
||||
static_inline void hlist_del(hlist_item_t * i)
|
||||
{
|
||||
hlist_item_t * next;
|
||||
assert(i);
|
||||
|
||||
next = i->next;
|
||||
next->prev = i->prev;
|
||||
*i->prev = next;
|
||||
|
||||
hlist_init_item(i);
|
||||
}
|
||||
|
||||
static_inline void hlist_relink(hlist_item_t * i)
|
||||
{
|
||||
assert(i);
|
||||
*i->prev = i;
|
||||
i->next->prev = &i->next;
|
||||
}
|
||||
|
||||
static_inline void hlist_relink_head(hlist_head_t * h)
|
||||
{
|
||||
assert(h);
|
||||
h->next->prev = &h->next;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
36
nestegg/halloc/src/macros.h
Normal file
36
nestegg/halloc/src/macros.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_MACROS_H_
|
||||
#define _LIBP_MACROS_H_
|
||||
|
||||
#include <stddef.h> /* offsetof */
|
||||
|
||||
/*
|
||||
restore pointer to the structure by a pointer to its field
|
||||
*/
|
||||
#define structof(p,t,f) ((t*)(- (ptrdiff_t) offsetof(t,f) + (char*)(p)))
|
||||
|
||||
/*
|
||||
* redefine for the target compiler
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define static_inline static __inline
|
||||
#else
|
||||
#define static_inline static __inline__
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
293
nestegg/include/nestegg/nestegg.h
Normal file
293
nestegg/include/nestegg/nestegg.h
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright © 2010 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#ifndef NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79
|
||||
#define NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79
|
||||
|
||||
#include "vpx/vpx_integer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @mainpage
|
||||
|
||||
@section intro Introduction
|
||||
|
||||
This is the documentation fot the <tt>libnestegg</tt> C API.
|
||||
<tt>libnestegg</tt> is a demultiplexing library for <a
|
||||
href="http://www.matroska.org/">Matroska</a> and <a
|
||||
href="http://www.webmproject.org/">WebMedia</a> media files.
|
||||
|
||||
@section example Example code
|
||||
|
||||
@code
|
||||
nestegg * demux_ctx;
|
||||
nestegg_init(&demux_ctx, io, NULL);
|
||||
|
||||
nestegg_packet * pkt;
|
||||
while ((r = nestegg_read_packet(demux_ctx, &pkt)) > 0) {
|
||||
unsigned int track;
|
||||
|
||||
nestegg_packet_track(pkt, &track);
|
||||
|
||||
// This example decodes the first track only.
|
||||
if (track == 0) {
|
||||
unsigned int chunk, chunks;
|
||||
|
||||
nestegg_packet_count(pkt, &chunks);
|
||||
|
||||
// Decode each chunk of data.
|
||||
for (chunk = 0; chunk < chunks; ++chunk) {
|
||||
unsigned char * data;
|
||||
size_t data_size;
|
||||
|
||||
nestegg_packet_data(pkt, chunk, &data, &data_size);
|
||||
|
||||
example_codec_decode(codec_ctx, data, data_size);
|
||||
}
|
||||
}
|
||||
|
||||
nestegg_free_packet(pkt);
|
||||
}
|
||||
|
||||
nestegg_destroy(demux_ctx);
|
||||
@endcode
|
||||
*/
|
||||
|
||||
|
||||
/** @file
|
||||
The <tt>libnestegg</tt> C API. */
|
||||
|
||||
#define NESTEGG_TRACK_VIDEO 0 /**< Track is of type video. */
|
||||
#define NESTEGG_TRACK_AUDIO 1 /**< Track is of type audio. */
|
||||
|
||||
#define NESTEGG_CODEC_VP8 0 /**< Track uses Google On2 VP8 codec. */
|
||||
#define NESTEGG_CODEC_VORBIS 1 /**< Track uses Xiph Vorbis codec. */
|
||||
#define NESTEGG_CODEC_VP9 2 /**< Track uses Google On2 VP9 codec. */
|
||||
|
||||
#define NESTEGG_SEEK_SET 0 /**< Seek offset relative to beginning of stream. */
|
||||
#define NESTEGG_SEEK_CUR 1 /**< Seek offset relative to current position in stream. */
|
||||
#define NESTEGG_SEEK_END 2 /**< Seek offset relative to end of stream. */
|
||||
|
||||
#define NESTEGG_LOG_DEBUG 1 /**< Debug level log message. */
|
||||
#define NESTEGG_LOG_INFO 10 /**< Informational level log message. */
|
||||
#define NESTEGG_LOG_WARNING 100 /**< Warning level log message. */
|
||||
#define NESTEGG_LOG_ERROR 1000 /**< Error level log message. */
|
||||
#define NESTEGG_LOG_CRITICAL 10000 /**< Critical level log message. */
|
||||
|
||||
typedef struct nestegg nestegg; /**< Opaque handle referencing the stream state. */
|
||||
typedef struct nestegg_packet nestegg_packet; /**< Opaque handle referencing a packet of data. */
|
||||
|
||||
/** User supplied IO context. */
|
||||
typedef struct {
|
||||
/** User supplied read callback.
|
||||
@param buffer Buffer to read data into.
|
||||
@param length Length of supplied buffer in bytes.
|
||||
@param userdata The #userdata supplied by the user.
|
||||
@retval 1 Read succeeded.
|
||||
@retval 0 End of stream.
|
||||
@retval -1 Error. */
|
||||
int (* read)(void * buffer, size_t length, void * userdata);
|
||||
|
||||
/** User supplied seek callback.
|
||||
@param offset Offset within the stream to seek to.
|
||||
@param whence Seek direction. One of #NESTEGG_SEEK_SET,
|
||||
#NESTEGG_SEEK_CUR, or #NESTEGG_SEEK_END.
|
||||
@param userdata The #userdata supplied by the user.
|
||||
@retval 0 Seek succeeded.
|
||||
@retval -1 Error. */
|
||||
int (* seek)(int64_t offset, int whence, void * userdata);
|
||||
|
||||
/** User supplied tell callback.
|
||||
@param userdata The #userdata supplied by the user.
|
||||
@returns Current position within the stream.
|
||||
@retval -1 Error. */
|
||||
int64_t (* tell)(void * userdata);
|
||||
|
||||
/** User supplied pointer to be passed to the IO callbacks. */
|
||||
void * userdata;
|
||||
} nestegg_io;
|
||||
|
||||
/** Parameters specific to a video track. */
|
||||
typedef struct {
|
||||
unsigned int width; /**< Width of the video frame in pixels. */
|
||||
unsigned int height; /**< Height of the video frame in pixels. */
|
||||
unsigned int display_width; /**< Display width of the video frame in pixels. */
|
||||
unsigned int display_height; /**< Display height of the video frame in pixels. */
|
||||
unsigned int crop_bottom; /**< Pixels to crop from the bottom of the frame. */
|
||||
unsigned int crop_top; /**< Pixels to crop from the top of the frame. */
|
||||
unsigned int crop_left; /**< Pixels to crop from the left of the frame. */
|
||||
unsigned int crop_right; /**< Pixels to crop from the right of the frame. */
|
||||
} nestegg_video_params;
|
||||
|
||||
/** Parameters specific to an audio track. */
|
||||
typedef struct {
|
||||
double rate; /**< Sampling rate in Hz. */
|
||||
unsigned int channels; /**< Number of audio channels. */
|
||||
unsigned int depth; /**< Bits per sample. */
|
||||
} nestegg_audio_params;
|
||||
|
||||
/** Logging callback function pointer. */
|
||||
typedef void (* nestegg_log)(nestegg * context, unsigned int severity, char const * format, ...);
|
||||
|
||||
/** Initialize a nestegg context. During initialization the parser will
|
||||
read forward in the stream processing all elements until the first
|
||||
block of media is reached. All track metadata has been processed at this point.
|
||||
@param context Storage for the new nestegg context. @see nestegg_destroy
|
||||
@param io User supplied IO context.
|
||||
@param callback Optional logging callback function pointer. May be NULL.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback);
|
||||
|
||||
/** Destroy a nestegg context and free associated memory.
|
||||
@param context #nestegg context to be freed. @see nestegg_init */
|
||||
void nestegg_destroy(nestegg * context);
|
||||
|
||||
/** Query the duration of the media stream in nanoseconds.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param duration Storage for the queried duration.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_duration(nestegg * context, uint64_t * duration);
|
||||
|
||||
/** Query the tstamp scale of the media stream in nanoseconds.
|
||||
Timecodes presented by nestegg have been scaled by this value
|
||||
before presentation to the caller.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param scale Storage for the queried scale factor.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_tstamp_scale(nestegg * context, uint64_t * scale);
|
||||
|
||||
/** Query the number of tracks in the media stream.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param tracks Storage for the queried track count.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_count(nestegg * context, unsigned int * tracks);
|
||||
|
||||
/** Seek @a track to @a tstamp. Stream seek will terminate at the earliest
|
||||
key point in the stream at or before @a tstamp. Other tracks in the
|
||||
stream will output packets with unspecified but nearby timestamps.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param tstamp Absolute timestamp in nanoseconds.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_seek(nestegg * context, unsigned int track, uint64_t tstamp);
|
||||
|
||||
/** Query the type specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@retval #NESTEGG_TRACK_VIDEO Track type is video.
|
||||
@retval #NESTEGG_TRACK_AUDIO Track type is audio.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_type(nestegg * context, unsigned int track);
|
||||
|
||||
/** Query the codec ID specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@retval #NESTEGG_CODEC_VP8 Track codec is VP8.
|
||||
@retval #NESTEGG_CODEC_VORBIS Track codec is Vorbis.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_codec_id(nestegg * context, unsigned int track);
|
||||
|
||||
/** Query the number of codec initialization chunks for @a track. Each
|
||||
chunk of data should be passed to the codec initialization functions in
|
||||
the order returned.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param count Storage for the queried chunk count.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_codec_data_count(nestegg * context, unsigned int track,
|
||||
unsigned int * count);
|
||||
|
||||
/** Get a pointer to chunk number @a item of codec initialization data for
|
||||
@a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param item Zero based chunk item number.
|
||||
@param data Storage for the queried data pointer.
|
||||
The data is owned by the #nestegg context.
|
||||
@param length Storage for the queried data size.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_codec_data(nestegg * context, unsigned int track, unsigned int item,
|
||||
unsigned char ** data, size_t * length);
|
||||
|
||||
/** Query the video parameters specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param params Storage for the queried video parameters.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_video_params(nestegg * context, unsigned int track,
|
||||
nestegg_video_params * params);
|
||||
|
||||
/** Query the audio parameters specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param params Storage for the queried audio parameters.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_audio_params(nestegg * context, unsigned int track,
|
||||
nestegg_audio_params * params);
|
||||
|
||||
/** Read a packet of media data. A packet consists of one or more chunks of
|
||||
data associated with a single track. nestegg_read_packet should be
|
||||
called in a loop while the return value is 1 to drive the stream parser
|
||||
forward. @see nestegg_free_packet
|
||||
@param context Context returned by #nestegg_init.
|
||||
@param packet Storage for the returned nestegg_packet.
|
||||
@retval 1 Additional packets may be read in subsequent calls.
|
||||
@retval 0 End of stream.
|
||||
@retval -1 Error. */
|
||||
int nestegg_read_packet(nestegg * context, nestegg_packet ** packet);
|
||||
|
||||
/** Destroy a nestegg_packet and free associated memory.
|
||||
@param packet #nestegg_packet to be freed. @see nestegg_read_packet */
|
||||
void nestegg_free_packet(nestegg_packet * packet);
|
||||
|
||||
/** Query the track number of @a packet.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param track Storage for the queried zero based track index.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_track(nestegg_packet * packet, unsigned int * track);
|
||||
|
||||
/** Query the time stamp in nanoseconds of @a packet.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param tstamp Storage for the queried timestamp in nanoseconds.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_tstamp(nestegg_packet * packet, uint64_t * tstamp);
|
||||
|
||||
/** Query the number of data chunks contained in @a packet.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param count Storage for the queried timestamp in nanoseconds.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_count(nestegg_packet * packet, unsigned int * count);
|
||||
|
||||
/** Get a pointer to chunk number @a item of packet data.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param item Zero based chunk item number.
|
||||
@param data Storage for the queried data pointer.
|
||||
The data is owned by the #nestegg_packet packet.
|
||||
@param length Storage for the queried data size.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_data(nestegg_packet * packet, unsigned int item,
|
||||
unsigned char ** data, size_t * length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79 */
|
||||
43
nestegg/m4/as-ac-expand.m4
Normal file
43
nestegg/m4/as-ac-expand.m4
Normal file
@@ -0,0 +1,43 @@
|
||||
dnl as-ac-expand.m4 0.2.0
|
||||
dnl autostars m4 macro for expanding directories using configure's prefix
|
||||
dnl thomas@apestaart.org
|
||||
|
||||
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
|
||||
dnl example
|
||||
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
|
||||
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
|
||||
|
||||
AC_DEFUN([AS_AC_EXPAND],
|
||||
[
|
||||
EXP_VAR=[$1]
|
||||
FROM_VAR=[$2]
|
||||
|
||||
dnl first expand prefix and exec_prefix if necessary
|
||||
prefix_save=$prefix
|
||||
exec_prefix_save=$exec_prefix
|
||||
|
||||
dnl if no prefix given, then use /usr/local, the default prefix
|
||||
if test "x$prefix" = "xNONE"; then
|
||||
prefix="$ac_default_prefix"
|
||||
fi
|
||||
dnl if no exec_prefix given, then use prefix
|
||||
if test "x$exec_prefix" = "xNONE"; then
|
||||
exec_prefix=$prefix
|
||||
fi
|
||||
|
||||
full_var="$FROM_VAR"
|
||||
dnl loop until it doesn't change anymore
|
||||
while true; do
|
||||
new_full_var="`eval echo $full_var`"
|
||||
if test "x$new_full_var" = "x$full_var"; then break; fi
|
||||
full_var=$new_full_var
|
||||
done
|
||||
|
||||
dnl clean up
|
||||
full_var=$new_full_var
|
||||
AC_SUBST([$1], "$full_var")
|
||||
|
||||
dnl restore prefix and exec_prefix
|
||||
prefix=$prefix_save
|
||||
exec_prefix=$exec_prefix_save
|
||||
])
|
||||
695
nestegg/m4/ax_create_stdint_h.m4
Normal file
695
nestegg/m4/ax_create_stdint_h.m4
Normal file
@@ -0,0 +1,695 @@
|
||||
dnl @synopsis AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])]
|
||||
dnl
|
||||
dnl the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the
|
||||
dnl existence of an include file <stdint.h> that defines a set of
|
||||
dnl typedefs, especially uint8_t,int32_t,uintptr_t. Many older
|
||||
dnl installations will not provide this file, but some will have the
|
||||
dnl very same definitions in <inttypes.h>. In other enviroments we can
|
||||
dnl use the inet-types in <sys/types.h> which would define the typedefs
|
||||
dnl int8_t and u_int8_t respectivly.
|
||||
dnl
|
||||
dnl This macros will create a local "_stdint.h" or the headerfile given
|
||||
dnl as an argument. In many cases that file will just "#include
|
||||
dnl <stdint.h>" or "#include <inttypes.h>", while in other environments
|
||||
dnl it will provide the set of basic 'stdint's definitions/typedefs:
|
||||
dnl
|
||||
dnl int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t
|
||||
dnl int_least32_t.. int_fast32_t.. intmax_t
|
||||
dnl
|
||||
dnl which may or may not rely on the definitions of other files, or
|
||||
dnl using the AC_CHECK_SIZEOF macro to determine the actual sizeof each
|
||||
dnl type.
|
||||
dnl
|
||||
dnl if your header files require the stdint-types you will want to
|
||||
dnl create an installable file mylib-int.h that all your other
|
||||
dnl installable header may include. So if you have a library package
|
||||
dnl named "mylib", just use
|
||||
dnl
|
||||
dnl AX_CREATE_STDINT_H(mylib-int.h)
|
||||
dnl
|
||||
dnl in configure.ac and go to install that very header file in
|
||||
dnl Makefile.am along with the other headers (mylib.h) - and the
|
||||
dnl mylib-specific headers can simply use "#include <mylib-int.h>" to
|
||||
dnl obtain the stdint-types.
|
||||
dnl
|
||||
dnl Remember, if the system already had a valid <stdint.h>, the
|
||||
dnl generated file will include it directly. No need for fuzzy
|
||||
dnl HAVE_STDINT_H things... (oops, GCC 4.2.x has deliberatly disabled
|
||||
dnl its stdint.h for non-c99 compilation and the c99-mode is not the
|
||||
dnl default. Therefore this macro will not use the compiler's stdint.h
|
||||
dnl - please complain to the GCC developers).
|
||||
dnl
|
||||
dnl @category C
|
||||
dnl @author Guido U. Draheim <guidod@gmx.de>
|
||||
dnl @version 2006-10-13
|
||||
dnl @license GPLWithACException
|
||||
|
||||
AC_DEFUN([AX_CHECK_DATA_MODEL],[
|
||||
AC_CHECK_SIZEOF(char)
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(void*)
|
||||
ac_cv_char_data_model=""
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
|
||||
ac_cv_long_data_model=""
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
|
||||
AC_MSG_CHECKING([data model])
|
||||
case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
|
||||
122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;;
|
||||
122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;;
|
||||
122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;;
|
||||
124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
|
||||
124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;;
|
||||
124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
|
||||
124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;;
|
||||
128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
|
||||
128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;;
|
||||
222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
|
||||
333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
|
||||
444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
|
||||
666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
|
||||
888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
|
||||
222/*|333/*|444/*|666/*|888/*) :
|
||||
ac_cv_data_model="iDSP" ; n="unusual dsptype" ;;
|
||||
*) ac_cv_data_model="none" ; n="very unusual model" ;;
|
||||
esac
|
||||
AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
|
||||
])
|
||||
|
||||
dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
|
||||
AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
|
||||
AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
|
||||
ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
|
||||
AC_MSG_RESULT([(..)])
|
||||
for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h])
|
||||
do
|
||||
unset ac_cv_type_uintptr_t
|
||||
unset ac_cv_type_uint64_t
|
||||
AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
|
||||
AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
|
||||
m4_ifvaln([$1],[$1]) break
|
||||
done
|
||||
AC_MSG_CHECKING([for stdint uintptr_t])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
|
||||
AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
|
||||
ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
|
||||
AC_MSG_RESULT([(..)])
|
||||
for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h])
|
||||
do
|
||||
unset ac_cv_type_uint32_t
|
||||
unset ac_cv_type_uint64_t
|
||||
AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
|
||||
AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
|
||||
m4_ifvaln([$1],[$1]) break
|
||||
break;
|
||||
done
|
||||
AC_MSG_CHECKING([for stdint uint32_t])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
|
||||
AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
|
||||
ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
|
||||
AC_MSG_RESULT([(..)])
|
||||
for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
|
||||
unset ac_cv_type_u_int32_t
|
||||
unset ac_cv_type_u_int64_t
|
||||
AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
|
||||
AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
|
||||
m4_ifvaln([$1],[$1]) break
|
||||
break;
|
||||
done
|
||||
AC_MSG_CHECKING([for stdint u_int32_t])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([AX_CREATE_STDINT_H],
|
||||
[# ------ AX CREATE STDINT H -------------------------------------
|
||||
AC_MSG_CHECKING([for stdint types])
|
||||
ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)`
|
||||
# try to shortcircuit - if the default include path of the compiler
|
||||
# can find a "stdint.h" header then we assume that all compilers can.
|
||||
AC_CACHE_VAL([ac_cv_header_stdint_t],[
|
||||
old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS=""
|
||||
old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS=""
|
||||
old_CFLAGS="$CFLAGS" ; CFLAGS=""
|
||||
AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
|
||||
[ac_cv_stdint_result="(assuming C99 compatible system)"
|
||||
ac_cv_header_stdint_t="stdint.h"; ],
|
||||
[ac_cv_header_stdint_t=""])
|
||||
if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then
|
||||
CFLAGS="-std=c99"
|
||||
AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
|
||||
[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)])
|
||||
fi
|
||||
CXXFLAGS="$old_CXXFLAGS"
|
||||
CPPFLAGS="$old_CPPFLAGS"
|
||||
CFLAGS="$old_CFLAGS" ])
|
||||
|
||||
v="... $ac_cv_header_stdint_h"
|
||||
if test "$ac_stdint_h" = "stdint.h" ; then
|
||||
AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)])
|
||||
elif test "$ac_stdint_h" = "inttypes.h" ; then
|
||||
AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)])
|
||||
elif test "_$ac_cv_header_stdint_t" = "_" ; then
|
||||
AC_MSG_RESULT([(putting them into $ac_stdint_h)$v])
|
||||
else
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_t"
|
||||
AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)])
|
||||
fi
|
||||
|
||||
if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
|
||||
|
||||
dnl .....intro message done, now do a few system checks.....
|
||||
dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type,
|
||||
dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW
|
||||
dnl instead that is triggered with 3 or more arguments (see types.m4)
|
||||
|
||||
inttype_headers=`echo $2 | sed -e 's/,/ /g'`
|
||||
|
||||
ac_cv_stdint_result="(no helpful system typedefs seen)"
|
||||
AX_CHECK_HEADER_STDINT_X(dnl
|
||||
stdint.h inttypes.h sys/inttypes.h $inttype_headers,
|
||||
ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
|
||||
|
||||
if test "_$ac_cv_header_stdint_x" = "_" ; then
|
||||
AX_CHECK_HEADER_STDINT_O(dnl,
|
||||
inttypes.h sys/inttypes.h stdint.h $inttype_headers,
|
||||
ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
|
||||
fi
|
||||
|
||||
if test "_$ac_cv_header_stdint_x" = "_" ; then
|
||||
if test "_$ac_cv_header_stdint_o" = "_" ; then
|
||||
AX_CHECK_HEADER_STDINT_U(dnl,
|
||||
sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
|
||||
ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
|
||||
fi fi
|
||||
|
||||
dnl if there was no good C99 header file, do some typedef checks...
|
||||
if test "_$ac_cv_header_stdint_x" = "_" ; then
|
||||
AC_MSG_CHECKING([for stdint datatype model])
|
||||
AC_MSG_RESULT([(..)])
|
||||
AX_CHECK_DATA_MODEL
|
||||
fi
|
||||
|
||||
if test "_$ac_cv_header_stdint_x" != "_" ; then
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_x"
|
||||
elif test "_$ac_cv_header_stdint_o" != "_" ; then
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_o"
|
||||
elif test "_$ac_cv_header_stdint_u" != "_" ; then
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_u"
|
||||
else
|
||||
ac_cv_header_stdint="stddef.h"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for extra inttypes in chosen header])
|
||||
AC_MSG_RESULT([($ac_cv_header_stdint)])
|
||||
dnl see if int_least and int_fast types are present in _this_ header.
|
||||
unset ac_cv_type_int_least32_t
|
||||
unset ac_cv_type_int_fast32_t
|
||||
AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>])
|
||||
AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>])
|
||||
AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>])
|
||||
|
||||
fi # shortcircut to system "stdint.h"
|
||||
# ------------------ PREPARE VARIABLES ------------------------------
|
||||
if test "$GCC" = "yes" ; then
|
||||
ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1`
|
||||
else
|
||||
ac_cv_stdint_message="using $CC"
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
|
||||
$ac_cv_stdint_result])
|
||||
|
||||
dnl -----------------------------------------------------------------
|
||||
# ----------------- DONE inttypes.h checks START header -------------
|
||||
AC_CONFIG_COMMANDS([$ac_stdint_h],[
|
||||
AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
|
||||
ac_stdint=$tmp/_stdint.h
|
||||
|
||||
echo "#ifndef" $_ac_stdint_h >$ac_stdint
|
||||
echo "#define" $_ac_stdint_h "1" >>$ac_stdint
|
||||
echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint
|
||||
echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
|
||||
echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_t" != "_" ; then
|
||||
echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
|
||||
echo "#include <stdint.h>" >>$ac_stdint
|
||||
echo "#endif" >>$ac_stdint
|
||||
echo "#endif" >>$ac_stdint
|
||||
else
|
||||
|
||||
cat >>$ac_stdint <<STDINT_EOF
|
||||
|
||||
/* ................... shortcircuit part ........................... */
|
||||
|
||||
#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <stddef.h>
|
||||
|
||||
/* .................... configured part ............................ */
|
||||
|
||||
STDINT_EOF
|
||||
|
||||
echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_x" != "_" ; then
|
||||
ac_header="$ac_cv_header_stdint_x"
|
||||
echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint
|
||||
fi
|
||||
|
||||
echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_o" != "_" ; then
|
||||
ac_header="$ac_cv_header_stdint_o"
|
||||
echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint
|
||||
fi
|
||||
|
||||
echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_u" != "_" ; then
|
||||
ac_header="$ac_cv_header_stdint_u"
|
||||
echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint
|
||||
fi
|
||||
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then
|
||||
echo "#include <$ac_header>" >>$ac_stdint
|
||||
echo "" >>$ac_stdint
|
||||
fi fi
|
||||
|
||||
echo "/* which 64bit typedef has been found */" >>$ac_stdint
|
||||
if test "$ac_cv_type_uint64_t" = "yes" ; then
|
||||
echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint
|
||||
fi
|
||||
if test "$ac_cv_type_u_int64_t" = "yes" ; then
|
||||
echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
echo "/* which type model has been detected */" >>$ac_stdint
|
||||
if test "_$ac_cv_char_data_model" != "_" ; then
|
||||
echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
|
||||
echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
|
||||
echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
|
||||
fi
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
echo "/* whether int_least types were detected */" >>$ac_stdint
|
||||
if test "$ac_cv_type_int_least32_t" = "yes"; then
|
||||
echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "/* whether int_fast types were detected */" >>$ac_stdint
|
||||
if test "$ac_cv_type_int_fast32_t" = "yes"; then
|
||||
echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "/* whether intmax_t type was detected */" >>$ac_stdint
|
||||
if test "$ac_cv_type_intmax_t" = "yes"; then
|
||||
echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
cat >>$ac_stdint <<STDINT_EOF
|
||||
/* .................... detections part ............................ */
|
||||
|
||||
/* whether we need to define bitspecific types from compiler base types */
|
||||
#ifndef _STDINT_HEADER_INTPTR
|
||||
#ifndef _STDINT_HEADER_UINT32
|
||||
#ifndef _STDINT_HEADER_U_INT32
|
||||
#define _STDINT_NEED_INT_MODEL_T
|
||||
#else
|
||||
#define _STDINT_HAVE_U_INT_TYPES
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_HAVE_U_INT_TYPES
|
||||
#undef _STDINT_NEED_INT_MODEL_T
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_CHAR_MODEL
|
||||
#if _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124
|
||||
#ifndef _STDINT_BYTE_MODEL
|
||||
#define _STDINT_BYTE_MODEL 12
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _STDINT_HAVE_INT_LEAST32_T
|
||||
#define _STDINT_NEED_INT_LEAST_T
|
||||
#endif
|
||||
|
||||
#ifndef _STDINT_HAVE_INT_FAST32_T
|
||||
#define _STDINT_NEED_INT_FAST_T
|
||||
#endif
|
||||
|
||||
#ifndef _STDINT_HEADER_INTPTR
|
||||
#define _STDINT_NEED_INTPTR_T
|
||||
#ifndef _STDINT_HAVE_INTMAX_T
|
||||
#define _STDINT_NEED_INTMAX_T
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* .................... definition part ............................ */
|
||||
|
||||
/* some system headers have good uint64_t */
|
||||
#ifndef _HAVE_UINT64_T
|
||||
#if defined _STDINT_HAVE_UINT64_T || defined HAVE_UINT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
#elif defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
typedef u_int64_t uint64_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _HAVE_UINT64_T
|
||||
/* .. here are some common heuristics using compiler runtime specifics */
|
||||
#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
|
||||
#define _HAVE_UINT64_T
|
||||
#define _HAVE_LONGLONG_UINT64_T
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#elif !defined __STRICT_ANSI__
|
||||
#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__
|
||||
#define _HAVE_UINT64_T
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__
|
||||
/* note: all ELF-systems seem to have loff-support which needs 64-bit */
|
||||
#if !defined _NO_LONGLONG
|
||||
#define _HAVE_UINT64_T
|
||||
#define _HAVE_LONGLONG_UINT64_T
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#endif
|
||||
|
||||
#elif defined __alpha || (defined __mips && defined _ABIN32)
|
||||
#if !defined _NO_LONGLONG
|
||||
typedef long int64_t;
|
||||
typedef unsigned long uint64_t;
|
||||
#endif
|
||||
/* compiler/cpu type to define int64_t */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined _STDINT_HAVE_U_INT_TYPES
|
||||
/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */
|
||||
typedef u_int8_t uint8_t;
|
||||
typedef u_int16_t uint16_t;
|
||||
typedef u_int32_t uint32_t;
|
||||
|
||||
/* glibc compatibility */
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_NEED_INT_MODEL_T
|
||||
/* we must guess all the basic types. Apart from byte-adressable system, */
|
||||
/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */
|
||||
/* (btw, those nibble-addressable systems are way off, or so we assume) */
|
||||
|
||||
dnl /* have a look at "64bit and data size neutrality" at */
|
||||
dnl /* http://unix.org/version2/whatsnew/login_64bit.html */
|
||||
dnl /* (the shorthand "ILP" types always have a "P" part) */
|
||||
|
||||
#if defined _STDINT_BYTE_MODEL
|
||||
#if _STDINT_LONG_MODEL+0 == 242
|
||||
/* 2:4:2 = IP16 = a normal 16-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned long uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef long int32_t;
|
||||
#endif
|
||||
#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444
|
||||
/* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */
|
||||
/* 4:4:4 = ILP32 = a normal 32-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
#endif
|
||||
#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488
|
||||
/* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */
|
||||
/* 4:8:8 = LP64 = a normal 64-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
#endif
|
||||
/* this system has a "long" of 64bit */
|
||||
#ifndef _HAVE_UINT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
typedef unsigned long uint64_t;
|
||||
typedef long int64_t;
|
||||
#endif
|
||||
#elif _STDINT_LONG_MODEL+0 == 448
|
||||
/* LLP64 a 64-bit system derived from a 32-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
#endif
|
||||
/* assuming the system has a "long long" */
|
||||
#ifndef _HAVE_UINT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
#define _HAVE_LONGLONG_UINT64_T
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef long long int64_t;
|
||||
#endif
|
||||
#else
|
||||
#define _STDINT_NO_INT32_T
|
||||
#endif
|
||||
#else
|
||||
#define _STDINT_NO_INT8_T
|
||||
#define _STDINT_NO_INT32_T
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* quote from SunOS-5.8 sys/inttypes.h:
|
||||
* Use at your own risk. As of February 1996, the committee is squarely
|
||||
* behind the fixed sized types; the "least" and "fast" types are still being
|
||||
* discussed. The probability that the "fast" types may be removed before
|
||||
* the standard is finalized is high enough that they are not currently
|
||||
* implemented.
|
||||
*/
|
||||
|
||||
#if defined _STDINT_NEED_INT_LEAST_T
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef int64_t int_least64_t;
|
||||
#endif
|
||||
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef uint64_t uint_least64_t;
|
||||
#endif
|
||||
/* least types */
|
||||
#endif
|
||||
|
||||
#if defined _STDINT_NEED_INT_FAST_T
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef int64_t int_fast64_t;
|
||||
#endif
|
||||
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef unsigned uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef uint64_t uint_fast64_t;
|
||||
#endif
|
||||
/* fast types */
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_NEED_INTMAX_T
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
#else
|
||||
typedef long intmax_t;
|
||||
typedef unsigned long uintmax_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_NEED_INTPTR_T
|
||||
#ifndef __intptr_t_defined
|
||||
#define __intptr_t_defined
|
||||
/* we encourage using "long" to store pointer values, never use "int" ! */
|
||||
#if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484
|
||||
typedef unsigned int uintptr_t;
|
||||
typedef int intptr_t;
|
||||
#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef long intptr_t;
|
||||
#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T
|
||||
typedef uint64_t uintptr_t;
|
||||
typedef int64_t intptr_t;
|
||||
#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef long intptr_t;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The ISO C99 standard specifies that in C++ implementations these
|
||||
should only be defined if explicitly requested. */
|
||||
#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
|
||||
#ifndef UINT32_C
|
||||
|
||||
/* Signed. */
|
||||
# define INT8_C(c) c
|
||||
# define INT16_C(c) c
|
||||
# define INT32_C(c) c
|
||||
# ifdef _HAVE_LONGLONG_UINT64_T
|
||||
# define INT64_C(c) c ## L
|
||||
# else
|
||||
# define INT64_C(c) c ## LL
|
||||
# endif
|
||||
|
||||
/* Unsigned. */
|
||||
# define UINT8_C(c) c ## U
|
||||
# define UINT16_C(c) c ## U
|
||||
# define UINT32_C(c) c ## U
|
||||
# ifdef _HAVE_LONGLONG_UINT64_T
|
||||
# define UINT64_C(c) c ## UL
|
||||
# else
|
||||
# define UINT64_C(c) c ## ULL
|
||||
# endif
|
||||
|
||||
/* Maximal type. */
|
||||
# ifdef _HAVE_LONGLONG_UINT64_T
|
||||
# define INTMAX_C(c) c ## L
|
||||
# define UINTMAX_C(c) c ## UL
|
||||
# else
|
||||
# define INTMAX_C(c) c ## LL
|
||||
# define UINTMAX_C(c) c ## ULL
|
||||
# endif
|
||||
|
||||
/* literalnumbers */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* These limits are merily those of a two complement byte-oriented system */
|
||||
|
||||
/* Minimum of signed integral types. */
|
||||
# define INT8_MIN (-128)
|
||||
# define INT16_MIN (-32767-1)
|
||||
# define INT32_MIN (-2147483647-1)
|
||||
# define INT64_MIN (-__INT64_C(9223372036854775807)-1)
|
||||
/* Maximum of signed integral types. */
|
||||
# define INT8_MAX (127)
|
||||
# define INT16_MAX (32767)
|
||||
# define INT32_MAX (2147483647)
|
||||
# define INT64_MAX (__INT64_C(9223372036854775807))
|
||||
|
||||
/* Maximum of unsigned integral types. */
|
||||
# define UINT8_MAX (255)
|
||||
# define UINT16_MAX (65535)
|
||||
# define UINT32_MAX (4294967295U)
|
||||
# define UINT64_MAX (__UINT64_C(18446744073709551615))
|
||||
|
||||
/* Minimum of signed integral types having a minimum size. */
|
||||
# define INT_LEAST8_MIN INT8_MIN
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# define INT_LEAST64_MIN INT64_MIN
|
||||
/* Maximum of signed integral types having a minimum size. */
|
||||
# define INT_LEAST8_MAX INT8_MAX
|
||||
# define INT_LEAST16_MAX INT16_MAX
|
||||
# define INT_LEAST32_MAX INT32_MAX
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
|
||||
/* Maximum of unsigned integral types having a minimum size. */
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
# define UINT_LEAST16_MAX UINT16_MAX
|
||||
# define UINT_LEAST32_MAX UINT32_MAX
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
/* shortcircuit*/
|
||||
#endif
|
||||
/* once */
|
||||
#endif
|
||||
#endif
|
||||
STDINT_EOF
|
||||
fi
|
||||
if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
|
||||
AC_MSG_NOTICE([$ac_stdint_h is unchanged])
|
||||
else
|
||||
ac_dir=`AS_DIRNAME(["$ac_stdint_h"])`
|
||||
AS_MKDIR_P(["$ac_dir"])
|
||||
rm -f $ac_stdint_h
|
||||
mv $ac_stdint $ac_stdint_h
|
||||
fi
|
||||
],[# variables for create stdint.h replacement
|
||||
PACKAGE="$PACKAGE"
|
||||
VERSION="$VERSION"
|
||||
ac_stdint_h="$ac_stdint_h"
|
||||
_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h)
|
||||
ac_cv_stdint_message="$ac_cv_stdint_message"
|
||||
ac_cv_header_stdint_t="$ac_cv_header_stdint_t"
|
||||
ac_cv_header_stdint_x="$ac_cv_header_stdint_x"
|
||||
ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
|
||||
ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
|
||||
ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
|
||||
ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model"
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model"
|
||||
ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
|
||||
ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
|
||||
ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
|
||||
])
|
||||
])
|
||||
157
nestegg/m4/pkg.m4
Normal file
157
nestegg/m4/pkg.m4
Normal file
@@ -0,0 +1,157 @@
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
#
|
||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
# ----------------------------------
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
|
||||
fi[]dnl
|
||||
])# PKG_PROG_PKG_CONFIG
|
||||
|
||||
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
# Check to see whether a particular set of modules exists. Similar
|
||||
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
#
|
||||
#
|
||||
# Similar to PKG_CHECK_MODULES, make sure that the first instance of
|
||||
# this or PKG_CHECK_MODULES is called, or make sure to call
|
||||
# PKG_CHECK_EXISTS manually
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||
m4_ifval([$2], [$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
|
||||
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
# ---------------------------------------------
|
||||
m4_define([_PKG_CONFIG],
|
||||
[if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$$1"; then
|
||||
pkg_cv_[]$1="$$1"
|
||||
else
|
||||
PKG_CHECK_EXISTS([$3],
|
||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||
[pkg_failed=yes])
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi[]dnl
|
||||
])# _PKG_CONFIG
|
||||
|
||||
# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
# -----------------------------
|
||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
# [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
#
|
||||
# Note that if there is a possibility the first call to
|
||||
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
#
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_MODULES],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
pkg_failed=no
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
|
||||
else
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
ifelse([$4], , [AC_MSG_ERROR(dnl
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_PKG_TEXT
|
||||
])],
|
||||
[AC_MSG_RESULT([no])
|
||||
$4])
|
||||
elif test $pkg_failed = untried; then
|
||||
ifelse([$4], , [AC_MSG_FAILURE(dnl
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
|
||||
[$4])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
ifelse([$3], , :, [$3])
|
||||
fi[]dnl
|
||||
])# PKG_CHECK_MODULES
|
||||
13
nestegg/nestegg-uninstalled.pc.in
Normal file
13
nestegg/nestegg-uninstalled.pc.in
Normal file
@@ -0,0 +1,13 @@
|
||||
# nestegg uninstalled pkg-config file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: nestegg
|
||||
Description: WebM/Matroska demuxer
|
||||
Version: @VERSION@
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -lnestegg
|
||||
Cflags: -I${includedir}
|
||||
13
nestegg/nestegg.pc.in
Normal file
13
nestegg/nestegg.pc.in
Normal file
@@ -0,0 +1,13 @@
|
||||
# nestegg installed pkg-config file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: nestegg
|
||||
Description: WebM/Matroska demuxer
|
||||
Version: @VERSION@
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -lnestegg
|
||||
Cflags: -I${includedir}
|
||||
1942
nestegg/src/nestegg.c
Normal file
1942
nestegg/src/nestegg.c
Normal file
File diff suppressed because it is too large
Load Diff
248
nestegg/test/test.c
Normal file
248
nestegg/test/test.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright © 2010 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "nestegg/nestegg.h"
|
||||
|
||||
#undef DEBUG
|
||||
#define SEEK_TEST
|
||||
|
||||
static int
|
||||
stdio_read(void * p, size_t length, void * fp)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
r = fread(p, length, 1, fp);
|
||||
if (r == 0 && feof(fp))
|
||||
return 0;
|
||||
return r == 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
static int
|
||||
stdio_seek(int64_t offset, int whence, void * fp)
|
||||
{
|
||||
return fseek(fp, offset, whence);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
stdio_tell(void * fp)
|
||||
{
|
||||
return ftell(fp);
|
||||
}
|
||||
|
||||
static void
|
||||
log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char const * sev = NULL;
|
||||
|
||||
#ifndef DEBUG
|
||||
if (severity < NESTEGG_LOG_WARNING)
|
||||
return;
|
||||
#endif
|
||||
|
||||
switch (severity) {
|
||||
case NESTEGG_LOG_DEBUG:
|
||||
sev = "debug: ";
|
||||
break;
|
||||
case NESTEGG_LOG_WARNING:
|
||||
sev = "warning: ";
|
||||
break;
|
||||
case NESTEGG_LOG_CRITICAL:
|
||||
sev = "critical:";
|
||||
break;
|
||||
default:
|
||||
sev = "unknown: ";
|
||||
}
|
||||
|
||||
fprintf(stderr, "%p %s ", (void *) ctx, sev);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char * argv[])
|
||||
{
|
||||
FILE * fp;
|
||||
int r, type;
|
||||
nestegg * ctx;
|
||||
nestegg_audio_params aparams;
|
||||
nestegg_packet * pkt;
|
||||
nestegg_video_params vparams;
|
||||
size_t length, size;
|
||||
uint64_t duration, tstamp, pkt_tstamp;
|
||||
unsigned char * codec_data, * ptr;
|
||||
unsigned int cnt, i, j, track, tracks, pkt_cnt, pkt_track;
|
||||
unsigned int data_items = 0;
|
||||
nestegg_io io = {
|
||||
stdio_read,
|
||||
stdio_seek,
|
||||
stdio_tell,
|
||||
NULL
|
||||
};
|
||||
|
||||
if (argc != 2)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
fp = fopen(argv[1], "rb");
|
||||
if (!fp)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
io.userdata = fp;
|
||||
|
||||
ctx = NULL;
|
||||
r = nestegg_init(&ctx, io, log_callback);
|
||||
if (r != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
nestegg_track_count(ctx, &tracks);
|
||||
nestegg_duration(ctx, &duration);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "media has %u tracks and duration %fs\n", tracks, duration / 1e9);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < tracks; ++i) {
|
||||
type = nestegg_track_type(ctx, i);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "track %u: type: %d codec: %d", i,
|
||||
type, nestegg_track_codec_id(ctx, i));
|
||||
#endif
|
||||
nestegg_track_codec_data_count(ctx, i, &data_items);
|
||||
for (j = 0; j < data_items; ++j) {
|
||||
nestegg_track_codec_data(ctx, i, j, &codec_data, &length);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " (%p, %u)", codec_data, (unsigned int) length);
|
||||
#endif
|
||||
}
|
||||
if (type == NESTEGG_TRACK_VIDEO) {
|
||||
nestegg_track_video_params(ctx, i, &vparams);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " video: %ux%u (d: %ux%u %ux%ux%ux%u)",
|
||||
vparams.width, vparams.height,
|
||||
vparams.display_width, vparams.display_height,
|
||||
vparams.crop_top, vparams.crop_left, vparams.crop_bottom, vparams.crop_right);
|
||||
#endif
|
||||
} else if (type == NESTEGG_TRACK_AUDIO) {
|
||||
nestegg_track_audio_params(ctx, i, &aparams);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " audio: %.2fhz %u bit %u channels",
|
||||
aparams.rate, aparams.depth, aparams.channels);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SEEK_TEST
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "seek to middle\n");
|
||||
#endif
|
||||
r = nestegg_track_seek(ctx, 0, duration / 2);
|
||||
if (r == 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "middle ");
|
||||
#endif
|
||||
r = nestegg_read_packet(ctx, &pkt);
|
||||
if (r == 1) {
|
||||
nestegg_packet_track(pkt, &track);
|
||||
nestegg_packet_count(pkt, &cnt);
|
||||
nestegg_packet_tstamp(pkt, &tstamp);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
|
||||
#endif
|
||||
nestegg_free_packet(pkt);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "middle seek failed\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "seek to ~end\n");
|
||||
#endif
|
||||
r = nestegg_track_seek(ctx, 0, duration - (duration / 10));
|
||||
if (r == 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "end ");
|
||||
#endif
|
||||
r = nestegg_read_packet(ctx, &pkt);
|
||||
if (r == 1) {
|
||||
nestegg_packet_track(pkt, &track);
|
||||
nestegg_packet_count(pkt, &cnt);
|
||||
nestegg_packet_tstamp(pkt, &tstamp);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
|
||||
#endif
|
||||
nestegg_free_packet(pkt);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "end seek failed\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "seek to ~start\n");
|
||||
#endif
|
||||
r = nestegg_track_seek(ctx, 0, duration / 10);
|
||||
if (r == 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "start ");
|
||||
#endif
|
||||
r = nestegg_read_packet(ctx, &pkt);
|
||||
if (r == 1) {
|
||||
nestegg_packet_track(pkt, &track);
|
||||
nestegg_packet_count(pkt, &cnt);
|
||||
nestegg_packet_tstamp(pkt, &tstamp);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
|
||||
#endif
|
||||
nestegg_free_packet(pkt);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "start seek failed\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (nestegg_read_packet(ctx, &pkt) > 0) {
|
||||
nestegg_packet_track(pkt, &pkt_track);
|
||||
nestegg_packet_count(pkt, &pkt_cnt);
|
||||
nestegg_packet_tstamp(pkt, &pkt_tstamp);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "t %u pts %f frames %u: ", pkt_track, pkt_tstamp / 1e9, pkt_cnt);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < pkt_cnt; ++i) {
|
||||
nestegg_packet_data(pkt, i, &ptr, &size);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%u ", (unsigned int) size);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
nestegg_free_packet(pkt);
|
||||
}
|
||||
|
||||
nestegg_destroy(ctx);
|
||||
fclose(fp);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
289
rate_hist.c
289
rate_hist.c
@@ -1,289 +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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "./rate_hist.h"
|
||||
|
||||
#define RATE_BINS 100
|
||||
#define HIST_BAR_MAX 40
|
||||
|
||||
struct hist_bucket {
|
||||
int low;
|
||||
int high;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct rate_hist {
|
||||
int64_t *pts;
|
||||
int *sz;
|
||||
int samples;
|
||||
int frames;
|
||||
struct hist_bucket bucket[RATE_BINS];
|
||||
int total;
|
||||
};
|
||||
|
||||
struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
|
||||
const vpx_rational_t *fps) {
|
||||
int i;
|
||||
struct rate_hist *hist = calloc(1, sizeof(*hist));
|
||||
|
||||
if (hist == NULL || cfg == NULL || fps == NULL || fps->num == 0 ||
|
||||
fps->den == 0) {
|
||||
destroy_rate_histogram(hist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Determine the number of samples in the buffer. Use the file's framerate
|
||||
// to determine the number of frames in rc_buf_sz milliseconds, with an
|
||||
// adjustment (5/4) to account for alt-refs
|
||||
hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
|
||||
|
||||
// prevent division by zero
|
||||
if (hist->samples == 0) hist->samples = 1;
|
||||
|
||||
hist->frames = 0;
|
||||
hist->total = 0;
|
||||
|
||||
hist->pts = calloc(hist->samples, sizeof(*hist->pts));
|
||||
hist->sz = calloc(hist->samples, sizeof(*hist->sz));
|
||||
for (i = 0; i < RATE_BINS; i++) {
|
||||
hist->bucket[i].low = INT_MAX;
|
||||
hist->bucket[i].high = 0;
|
||||
hist->bucket[i].count = 0;
|
||||
}
|
||||
|
||||
return hist;
|
||||
}
|
||||
|
||||
void destroy_rate_histogram(struct rate_hist *hist) {
|
||||
if (hist) {
|
||||
free(hist->pts);
|
||||
free(hist->sz);
|
||||
free(hist);
|
||||
}
|
||||
}
|
||||
|
||||
void update_rate_histogram(struct rate_hist *hist,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
const vpx_codec_cx_pkt_t *pkt) {
|
||||
int i;
|
||||
int64_t then = 0;
|
||||
int64_t avg_bitrate = 0;
|
||||
int64_t sum_sz = 0;
|
||||
const int64_t now = pkt->data.frame.pts * 1000 *
|
||||
(uint64_t)cfg->g_timebase.num /
|
||||
(uint64_t)cfg->g_timebase.den;
|
||||
|
||||
int idx;
|
||||
|
||||
if (hist == NULL || cfg == NULL || pkt == NULL) return;
|
||||
|
||||
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 (!cfg->rc_target_bitrate) return;
|
||||
|
||||
then = now;
|
||||
|
||||
/* Sum the size over the past rc_buf_sz ms */
|
||||
for (i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--) {
|
||||
const int i_idx = (i - 1) % hist->samples;
|
||||
|
||||
then = hist->pts[i_idx];
|
||||
if (now - then > cfg->rc_buf_sz) break;
|
||||
sum_sz += hist->sz[i_idx];
|
||||
}
|
||||
|
||||
if (now == then) return;
|
||||
|
||||
avg_bitrate = sum_sz * 8 * 1000 / (now - then);
|
||||
idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000));
|
||||
if (idx < 0) idx = 0;
|
||||
if (idx > RATE_BINS - 1) idx = RATE_BINS - 1;
|
||||
if (hist->bucket[idx].low > avg_bitrate)
|
||||
hist->bucket[idx].low = (int)avg_bitrate;
|
||||
if (hist->bucket[idx].high < avg_bitrate)
|
||||
hist->bucket[idx].high = (int)avg_bitrate;
|
||||
hist->bucket[idx].count++;
|
||||
hist->total++;
|
||||
}
|
||||
|
||||
static int merge_hist_buckets(struct hist_bucket *bucket, int max_buckets,
|
||||
int *num_buckets) {
|
||||
int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
|
||||
int buckets;
|
||||
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 we have too many buckets, merge the smallest with an adjacent
|
||||
* bucket.
|
||||
*/
|
||||
while (buckets > max_buckets) {
|
||||
int last_bucket = buckets - 1;
|
||||
|
||||
/* merge the small bucket with an adjacent one. */
|
||||
if (small_bucket == 0)
|
||||
merge_bucket = 1;
|
||||
else if (small_bucket == last_bucket)
|
||||
merge_bucket = last_bucket - 1;
|
||||
else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
|
||||
merge_bucket = small_bucket - 1;
|
||||
else
|
||||
merge_bucket = small_bucket + 1;
|
||||
|
||||
assert(abs(merge_bucket - small_bucket) <= 1);
|
||||
assert(small_bucket < buckets);
|
||||
assert(big_bucket < buckets);
|
||||
assert(merge_bucket < buckets);
|
||||
|
||||
if (merge_bucket < small_bucket) {
|
||||
bucket[merge_bucket].high = bucket[small_bucket].high;
|
||||
bucket[merge_bucket].count += bucket[small_bucket].count;
|
||||
} else {
|
||||
bucket[small_bucket].high = bucket[merge_bucket].high;
|
||||
bucket[small_bucket].count += bucket[merge_bucket].count;
|
||||
merge_bucket = small_bucket;
|
||||
}
|
||||
|
||||
assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
|
||||
|
||||
buckets--;
|
||||
|
||||
/* Remove the merge_bucket from the list, and find the new small
|
||||
* and big buckets while we're at it
|
||||
*/
|
||||
big_bucket = small_bucket = 0;
|
||||
for (i = 0; i < buckets; i++) {
|
||||
if (i > merge_bucket) bucket[i] = bucket[i + 1];
|
||||
|
||||
if (bucket[i].count < bucket[small_bucket].count) small_bucket = i;
|
||||
if (bucket[i].count > bucket[big_bucket].count) big_bucket = i;
|
||||
}
|
||||
}
|
||||
|
||||
*num_buckets = buckets;
|
||||
return bucket[big_bucket].count;
|
||||
}
|
||||
|
||||
static void show_histogram(const struct hist_bucket *bucket, int buckets,
|
||||
int total, int scale) {
|
||||
const char *pat1, *pat2;
|
||||
int i;
|
||||
|
||||
assert(bucket != NULL);
|
||||
|
||||
switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) {
|
||||
case 1:
|
||||
case 2:
|
||||
pat1 = "%4d %2s: ";
|
||||
pat2 = "%4d-%2d: ";
|
||||
break;
|
||||
case 3:
|
||||
pat1 = "%5d %3s: ";
|
||||
pat2 = "%5d-%3d: ";
|
||||
break;
|
||||
case 4:
|
||||
pat1 = "%6d %4s: ";
|
||||
pat2 = "%6d-%4d: ";
|
||||
break;
|
||||
case 5:
|
||||
pat1 = "%7d %5s: ";
|
||||
pat2 = "%7d-%5d: ";
|
||||
break;
|
||||
case 6:
|
||||
pat1 = "%8d %6s: ";
|
||||
pat2 = "%8d-%6d: ";
|
||||
break;
|
||||
case 7:
|
||||
pat1 = "%9d %7s: ";
|
||||
pat2 = "%9d-%7d: ";
|
||||
break;
|
||||
default:
|
||||
pat1 = "%12d %10s: ";
|
||||
pat2 = "%12d-%10d: ";
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < buckets; i++) {
|
||||
int len;
|
||||
int j;
|
||||
float pct;
|
||||
|
||||
pct = (float)(100.0 * bucket[i].count / total);
|
||||
len = HIST_BAR_MAX * bucket[i].count / scale;
|
||||
if (len < 1) len = 1;
|
||||
assert(len <= HIST_BAR_MAX);
|
||||
|
||||
if (bucket[i].low == bucket[i].high)
|
||||
fprintf(stderr, pat1, bucket[i].low, "");
|
||||
else
|
||||
fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
|
||||
|
||||
for (j = 0; j < HIST_BAR_MAX; j++) fprintf(stderr, j < len ? "=" : " ");
|
||||
fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
|
||||
}
|
||||
}
|
||||
|
||||
void show_q_histogram(const int counts[64], int max_buckets) {
|
||||
struct hist_bucket bucket[64];
|
||||
int buckets = 0;
|
||||
int total = 0;
|
||||
int scale;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (counts[i]) {
|
||||
bucket[buckets].low = bucket[buckets].high = i;
|
||||
bucket[buckets].count = counts[i];
|
||||
buckets++;
|
||||
total += counts[i];
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nQuantizer Selection:\n");
|
||||
scale = merge_hist_buckets(bucket, max_buckets, &buckets);
|
||||
show_histogram(bucket, buckets, total, scale);
|
||||
}
|
||||
|
||||
void show_rate_histogram(struct rate_hist *hist, const vpx_codec_enc_cfg_t *cfg,
|
||||
int max_buckets) {
|
||||
int i, scale;
|
||||
int buckets = 0;
|
||||
|
||||
if (hist == NULL || cfg == NULL) return;
|
||||
|
||||
for (i = 0; i < RATE_BINS; i++) {
|
||||
if (hist->bucket[i].low == INT_MAX) continue;
|
||||
hist->bucket[buckets++] = hist->bucket[i];
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
|
||||
scale = merge_hist_buckets(hist->bucket, max_buckets, &buckets);
|
||||
show_histogram(hist->bucket, buckets, hist->total, scale);
|
||||
}
|
||||
40
rate_hist.h
40
rate_hist.h
@@ -1,40 +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.
|
||||
*/
|
||||
|
||||
#ifndef RATE_HIST_H_
|
||||
#define RATE_HIST_H_
|
||||
|
||||
#include "vpx/vpx_encoder.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct rate_hist;
|
||||
|
||||
struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
|
||||
const vpx_rational_t *fps);
|
||||
|
||||
void destroy_rate_histogram(struct rate_hist *hist);
|
||||
|
||||
void update_rate_histogram(struct rate_hist *hist,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
const vpx_codec_cx_pkt_t *pkt);
|
||||
|
||||
void show_q_histogram(const int counts[64], int max_buckets);
|
||||
|
||||
void show_rate_histogram(struct rate_hist *hist, const vpx_codec_enc_cfg_t *cfg,
|
||||
int max_buckets);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // RATE_HIST_H_
|
||||
@@ -9,7 +9,7 @@
|
||||
##
|
||||
|
||||
# libvpx reverse dependencies (targets that depend on libvpx)
|
||||
VPX_NONDEPS=$(addsuffix .$(VCPROJ_SFX),vpx gtest)
|
||||
VPX_NONDEPS=$(addsuffix .$(VCPROJ_SFX),vpx gtest obj_int_extract)
|
||||
VPX_RDEPS=$(foreach vcp,\
|
||||
$(filter-out $(VPX_NONDEPS),$^), --dep=$(vcp:.$(VCPROJ_SFX)=):vpx)
|
||||
|
||||
@@ -17,6 +17,7 @@ vpx.sln: $(wildcard *.$(VCPROJ_SFX))
|
||||
@echo " [CREATE] $@"
|
||||
$(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \
|
||||
$(if $(filter vpx.$(VCPROJ_SFX),$^),$(VPX_RDEPS)) \
|
||||
--dep=vpx:obj_int_extract \
|
||||
--dep=test_libvpx:gtest \
|
||||
--ver=$(CONFIG_VS_VERSION)\
|
||||
--out=$@ $^
|
||||
|
||||
@@ -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,24 +23,20 @@ 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);
|
||||
return (value >> 15) & 0xffff;
|
||||
}
|
||||
|
||||
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 (value >> 16) & 0xffff;
|
||||
}
|
||||
|
||||
uint8_t Rand8(void) {
|
||||
const uint32_t value =
|
||||
random_.Generate(testing::internal::Random::kMaxRange);
|
||||
// There's a bit more entropy in the upper bits of this implementation.
|
||||
return (value >> 23) & 0xff;
|
||||
return (value >> 24) & 0xff;
|
||||
}
|
||||
|
||||
uint8_t Rand8Extremes(void) {
|
||||
@@ -54,18 +46,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_;
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 <algorithm>
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
#include "test/codec_factory.h"
|
||||
#include "test/encode_test_driver.h"
|
||||
#include "test/util.h"
|
||||
#include "test/y4m_video_source.h"
|
||||
|
||||
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) {
|
||||
for (int plane = 0; plane < 3; plane++) {
|
||||
int r = 16 * mb_r;
|
||||
int c0 = 16 * mb_c;
|
||||
int r_top = std::min(r + 16, static_cast<int>(current.d_h));
|
||||
int c_top = std::min(c0 + 16, static_cast<int>(current.d_w));
|
||||
r = std::max(r, 0);
|
||||
c0 = std::max(c0, 0);
|
||||
if (plane > 0 && current.x_chroma_shift) {
|
||||
c_top = (c_top + 1) >> 1;
|
||||
c0 >>= 1;
|
||||
}
|
||||
if (plane > 0 && current.y_chroma_shift) {
|
||||
r_top = (r_top + 1) >> 1;
|
||||
r >>= 1;
|
||||
}
|
||||
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]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GenerateMap(int mb_rows, int mb_cols, const vpx_image_t ¤t,
|
||||
const vpx_image_t &previous, uint8_t *map) {
|
||||
for (int mb_r = 0; mb_r < mb_rows; ++mb_r) {
|
||||
for (int mb_c = 0; mb_c < mb_cols; ++mb_c) {
|
||||
map[mb_r * mb_cols + mb_c] = CheckMb(current, previous, mb_r, mb_c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int kAqModeCyclicRefresh = 3;
|
||||
|
||||
class ActiveMapRefreshTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
ActiveMapRefreshTest() : EncoderTest(GET_PARAM(0)) {}
|
||||
virtual ~ActiveMapRefreshTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
InitializeConfig();
|
||||
SetMode(GET_PARAM(1));
|
||||
cpu_used_ = GET_PARAM(2);
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
::libvpx_test::Y4mVideoSource *y4m_video =
|
||||
static_cast<libvpx_test::Y4mVideoSource *>(video);
|
||||
if (video->frame() == 1) {
|
||||
encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
|
||||
encoder->Control(VP9E_SET_AQ_MODE, kAqModeCyclicRefresh);
|
||||
} else if (video->frame() >= 2 && video->img()) {
|
||||
vpx_image_t *current = video->img();
|
||||
vpx_image_t *previous = y4m_holder_->img();
|
||||
ASSERT_TRUE(previous != NULL);
|
||||
vpx_active_map_t map = vpx_active_map_t();
|
||||
const int width = static_cast<int>(current->d_w);
|
||||
const int height = static_cast<int>(current->d_h);
|
||||
const int mb_width = (width + 15) / 16;
|
||||
const int mb_height = (height + 15) / 16;
|
||||
uint8_t *active_map = new uint8_t[mb_width * mb_height];
|
||||
GenerateMap(mb_height, mb_width, *current, *previous, active_map);
|
||||
map.cols = mb_width;
|
||||
map.rows = mb_height;
|
||||
map.active_map = active_map;
|
||||
encoder->Control(VP8E_SET_ACTIVEMAP, &map);
|
||||
delete[] active_map;
|
||||
}
|
||||
if (video->img()) {
|
||||
y4m_video->SwapBuffers(y4m_holder_);
|
||||
}
|
||||
}
|
||||
|
||||
int cpu_used_;
|
||||
::libvpx_test::Y4mVideoSource *y4m_holder_;
|
||||
};
|
||||
|
||||
TEST_P(ActiveMapRefreshTest, Test) {
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
cfg_.g_profile = 1;
|
||||
cfg_.rc_target_bitrate = 600;
|
||||
cfg_.rc_resize_allowed = 0;
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 30;
|
||||
cfg_.g_pass = VPX_RC_ONE_PASS;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.kf_max_dist = 90000;
|
||||
|
||||
::libvpx_test::Y4mVideoSource video("desktop_credits.y4m", 0, 30);
|
||||
::libvpx_test::Y4mVideoSource video_holder("desktop_credits.y4m", 0, 30);
|
||||
video_holder.Begin();
|
||||
y4m_holder_ = &video_holder;
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(ActiveMapRefreshTest,
|
||||
::testing::Values(::libvpx_test::kRealTime),
|
||||
::testing::Range(5, 6));
|
||||
} // namespace
|
||||
@@ -1,91 +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 <climits>
|
||||
#include <vector>
|
||||
#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 ActiveMapTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
static const int kWidth = 208;
|
||||
static const int kHeight = 144;
|
||||
|
||||
ActiveMapTest() : EncoderTest(GET_PARAM(0)) {}
|
||||
virtual ~ActiveMapTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
InitializeConfig();
|
||||
SetMode(GET_PARAM(1));
|
||||
cpu_used_ = GET_PARAM(2);
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
if (video->frame() == 1) {
|
||||
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,
|
||||
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,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1,
|
||||
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);
|
||||
ASSERT_EQ(map.rows, 9u);
|
||||
map.active_map = active_map;
|
||||
encoder->Control(VP8E_SET_ACTIVEMAP, &map);
|
||||
} else if (video->frame() == 15) {
|
||||
vpx_active_map_t map = vpx_active_map_t();
|
||||
map.cols = (kWidth + 15) / 16;
|
||||
map.rows = (kHeight + 15) / 16;
|
||||
map.active_map = NULL;
|
||||
encoder->Control(VP8E_SET_ACTIVEMAP, &map);
|
||||
}
|
||||
}
|
||||
|
||||
int cpu_used_;
|
||||
};
|
||||
|
||||
TEST_P(ActiveMapTest, Test) {
|
||||
// Validate that this non multiple of 64 wide clip encodes
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
cfg_.rc_target_bitrate = 400;
|
||||
cfg_.rc_resize_allowed = 0;
|
||||
cfg_.g_pass = VPX_RC_ONE_PASS;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.kf_max_dist = 90000;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", kWidth, kHeight, 30, 1,
|
||||
0, 20);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(ActiveMapTest,
|
||||
::testing::Values(::libvpx_test::kRealTime),
|
||||
::testing::Range(0, 9));
|
||||
} // namespace
|
||||
@@ -1,136 +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 <math.h>
|
||||
#include "test/clear_system_state.h"
|
||||
#include "test/register_state_check.h"
|
||||
#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);
|
||||
|
||||
class AddNoiseTest : public ::testing::TestWithParam<AddNoiseFunc> {
|
||||
public:
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
virtual ~AddNoiseTest() {}
|
||||
};
|
||||
|
||||
double stddev6(char a, char b, char c, char d, char e, char f) {
|
||||
const double n = (a + b + c + d + e + f) / 6.0;
|
||||
const double v = ((a - n) * (a - n) + (b - n) * (b - n) + (c - n) * (c - n) +
|
||||
(d - n) * (d - n) + (e - n) * (e - n) + (f - n) * (f - n)) /
|
||||
6.0;
|
||||
return sqrt(v);
|
||||
}
|
||||
|
||||
TEST_P(AddNoiseTest, CheckNoiseAdded) {
|
||||
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));
|
||||
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
GetParam()(s, noise, clamp, clamp, width, height, width));
|
||||
|
||||
// Check to make sure we don't end up having either the same or no added
|
||||
// noise either vertically or horizontally.
|
||||
for (int i = 0; i < image_size - 6 * width - 6; ++i) {
|
||||
const double hd = stddev6(s[i] - 99, s[i + 1] - 99, s[i + 2] - 99,
|
||||
s[i + 3] - 99, s[i + 4] - 99, s[i + 5] - 99);
|
||||
const double vd = stddev6(s[i] - 99, s[i + width] - 99,
|
||||
s[i + 2 * width] - 99, s[i + 3 * width] - 99,
|
||||
s[i + 4 * width] - 99, s[i + 5 * width] - 99);
|
||||
|
||||
EXPECT_NE(hd, 0);
|
||||
EXPECT_NE(vd, 0);
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
vpx_free(s);
|
||||
}
|
||||
|
||||
TEST_P(AddNoiseTest, CheckCvsAssembly) {
|
||||
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, 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));
|
||||
srand(0);
|
||||
ASM_REGISTER_STATE_CHECK(
|
||||
vpx_plane_add_noise_c(d, noise, clamp, clamp, 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;
|
||||
}
|
||||
|
||||
vpx_free(d);
|
||||
vpx_free(s);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, AddNoiseTest,
|
||||
::testing::Values(vpx_plane_add_noise_c));
|
||||
|
||||
#if HAVE_SSE2
|
||||
INSTANTIATE_TEST_CASE_P(SSE2, AddNoiseTest,
|
||||
::testing::Values(vpx_plane_add_noise_sse2));
|
||||
#endif
|
||||
|
||||
#if HAVE_MSA
|
||||
INSTANTIATE_TEST_CASE_P(MSA, AddNoiseTest,
|
||||
::testing::Values(vpx_plane_add_noise_msa));
|
||||
#endif
|
||||
} // namespace
|
||||
@@ -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
|
||||
@@ -14,14 +14,12 @@
|
||||
#include "test/util.h"
|
||||
namespace {
|
||||
|
||||
#if CONFIG_VP8_ENCODER
|
||||
|
||||
// lookahead range: [kLookAheadMin, kLookAheadMax).
|
||||
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 +29,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) {
|
||||
@@ -63,90 +63,7 @@ TEST_P(AltRefTest, MonotonicTimestamps) {
|
||||
EXPECT_GE(altref_count(), 1);
|
||||
}
|
||||
|
||||
|
||||
VP8_INSTANTIATE_TEST_CASE(AltRefTest,
|
||||
::testing::Range(kLookAheadMin, kLookAheadMax));
|
||||
|
||||
#endif // CONFIG_VP8_ENCODER
|
||||
|
||||
class AltRefForcedKeyTestLarge
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
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) {}
|
||||
virtual ~AltRefForcedKeyTestLarge() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
InitializeConfig();
|
||||
SetMode(encoding_mode_);
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
cfg_.g_threads = 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(VP8E_SET_ENABLEAUTOALTREF, 1);
|
||||
#if CONFIG_VP9_ENCODER
|
||||
// override test default for tile columns if necessary.
|
||||
if (GET_PARAM(0) == &libvpx_test::kVP9) {
|
||||
encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
frame_flags_ =
|
||||
(video->frame() == forced_kf_frame_num_) ? VPX_EFLAG_FORCE_KF : 0;
|
||||
}
|
||||
|
||||
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
if (frame_num_ == forced_kf_frame_num_) {
|
||||
ASSERT_TRUE(!!(pkt->data.frame.flags & VPX_FRAME_IS_KEY))
|
||||
<< "Frame #" << frame_num_ << " isn't a keyframe!";
|
||||
}
|
||||
++frame_num_;
|
||||
}
|
||||
|
||||
::libvpx_test::TestMode encoding_mode_;
|
||||
int cpu_used_;
|
||||
unsigned int forced_kf_frame_num_;
|
||||
unsigned int frame_num_;
|
||||
};
|
||||
|
||||
TEST_P(AltRefForcedKeyTestLarge, Frame1IsKey) {
|
||||
const vpx_rational timebase = { 1, 30 };
|
||||
const int lag_values[] = { 3, 15, 25, -1 };
|
||||
|
||||
forced_kf_frame_num_ = 1;
|
||||
for (int i = 0; lag_values[i] != -1; ++i) {
|
||||
frame_num_ = 0;
|
||||
cfg_.g_lag_in_frames = lag_values[i];
|
||||
libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
timebase.den, timebase.num, 0, 30);
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(AltRefForcedKeyTestLarge, ForcedFrameIsKey) {
|
||||
const vpx_rational timebase = { 1, 30 };
|
||||
const int lag_values[] = { 3, 15, 25, -1 };
|
||||
|
||||
for (int i = 0; lag_values[i] != -1; ++i) {
|
||||
frame_num_ = 0;
|
||||
forced_kf_frame_num_ = lag_values[i] - 1;
|
||||
cfg_.g_lag_in_frames = lag_values[i];
|
||||
libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
timebase.den, timebase.num, 0, 30);
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
} // namespace
|
||||
|
||||
@@ -14,14 +14,8 @@ CUR_WD := $(call my-dir)
|
||||
BINDINGS_DIR := $(CUR_WD)/../../..
|
||||
LOCAL_PATH := $(CUR_WD)/../../..
|
||||
|
||||
#libwebm
|
||||
include $(CLEAR_VARS)
|
||||
include $(BINDINGS_DIR)/libvpx/third_party/libwebm/Android.mk
|
||||
LOCAL_PATH := $(CUR_WD)/../../..
|
||||
|
||||
#libvpx
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_STATIC_LIBRARIES := libwebm
|
||||
include $(BINDINGS_DIR)/libvpx/build/make/Android.mk
|
||||
LOCAL_PATH := $(CUR_WD)/../..
|
||||
|
||||
@@ -32,7 +26,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)
|
||||
|
||||
@@ -40,18 +33,10 @@ include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_ARM_MODE := arm
|
||||
LOCAL_MODULE := libvpx_test
|
||||
LOCAL_STATIC_LIBRARIES := gtest libwebm
|
||||
|
||||
ifeq ($(ENABLE_SHARED),1)
|
||||
LOCAL_SHARED_LIBRARIES := vpx
|
||||
else
|
||||
LOCAL_STATIC_LIBRARIES += vpx
|
||||
endif
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := gtest
|
||||
LOCAL_SHARED_LIBRARIES := vpx
|
||||
include $(LOCAL_PATH)/test/test.mk
|
||||
LOCAL_C_INCLUDES := $(BINDINGS_DIR)
|
||||
FILTERED_SRC := $(sort $(filter %.cc %.c, $(LIBVPX_TEST_SRCS-yes)))
|
||||
LOCAL_SRC_FILES := $(addprefix ./test/, $(FILTERED_SRC))
|
||||
# some test files depend on *_rtcd.h, ensure they're generated first.
|
||||
$(eval $(call rtcd_dep_template))
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
@@ -3,7 +3,7 @@ Android.mk will build vpx unittests on android.
|
||||
./libvpx/configure --target=armv7-android-gcc --enable-external-build \
|
||||
--enable-postproc --disable-install-srcs --enable-multi-res-encoding \
|
||||
--enable-temporal-denoising --disable-unit-tests --disable-install-docs \
|
||||
--disable-examples --disable-runtime-cpu-detect --sdk-path=$NDK
|
||||
--disable-examples --disable-runtime-cpu-detect --sdk=$NDK
|
||||
|
||||
2) From the parent directory, invoke ndk-build:
|
||||
NDK_PROJECT_PATH=. ndk-build APP_BUILD_SCRIPT=./libvpx/test/android/Android.mk \
|
||||
|
||||
@@ -1,57 +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.
|
||||
|
||||
"""Standalone script which parses a gtest log for json.
|
||||
|
||||
Json is returned returns as an array. This script is used by the libvpx
|
||||
waterfall to gather json results mixed in with gtest logs. This is
|
||||
dubious software engineering.
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
print "Expects a file to write json to!"
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
opts, _ = \
|
||||
getopt.getopt(sys.argv[1:], \
|
||||
'o:', ['output-json='])
|
||||
except getopt.GetOptError:
|
||||
print 'scrape_gtest_log.py -o <output_json>'
|
||||
sys.exit(2)
|
||||
|
||||
output_json = ''
|
||||
for opt, arg in opts:
|
||||
if opt in ('-o', '--output-json'):
|
||||
output_json = os.path.join(arg)
|
||||
|
||||
blob = sys.stdin.read()
|
||||
json_string = '[' + ','.join('{' + x + '}' for x in
|
||||
re.findall(r'{([^}]*.?)}', blob)) + ']'
|
||||
print blob
|
||||
|
||||
output = json.dumps(json.loads(json_string), indent=4, sort_keys=True)
|
||||
print output
|
||||
|
||||
path = os.path.dirname(output_json)
|
||||
if path and not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
outfile = open(output_json, 'w')
|
||||
outfile.write(output)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -1,109 +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 AqSegmentTest
|
||||
: public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
AqSegmentTest() : EncoderTest(GET_PARAM(0)) {}
|
||||
virtual ~AqSegmentTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
InitializeConfig();
|
||||
SetMode(GET_PARAM(1));
|
||||
set_cpu_used_ = GET_PARAM(2);
|
||||
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_AQ_MODE, aq_mode_);
|
||||
encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 100);
|
||||
}
|
||||
}
|
||||
|
||||
int set_cpu_used_;
|
||||
int aq_mode_;
|
||||
};
|
||||
|
||||
// Validate that this AQ segmentation mode (AQ=1, variance_ap)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AqSegmentTest, TestNoMisMatchAQ1) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
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;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
// Validate that this AQ segmentation mode (AQ=2, complexity_aq)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AqSegmentTest, TestNoMisMatchAQ2) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
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;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
// Validate that this AQ segmentation mode (AQ=3, cyclic_refresh_aq)
|
||||
// encodes and decodes without a mismatch.
|
||||
TEST_P(AqSegmentTest, TestNoMisMatchAQ3) {
|
||||
cfg_.rc_min_quantizer = 8;
|
||||
cfg_.rc_max_quantizer = 56;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
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;
|
||||
|
||||
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
30, 1, 0, 100);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(AqSegmentTest,
|
||||
::testing::Values(::libvpx_test::kRealTime,
|
||||
::libvpx_test::kOnePassGood),
|
||||
::testing::Range(3, 9));
|
||||
} // namespace
|
||||
581
test/avg_test.cc
581
test/avg_test.cc
@@ -1,581 +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 <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
|
||||
#include "./vp9_rtcd.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 "vpx_mem/vpx_mem.h"
|
||||
#include "vpx_ports/vpx_timer.h"
|
||||
|
||||
using libvpx_test::ACMRandom;
|
||||
|
||||
namespace {
|
||||
class AverageTestBase : public ::testing::Test {
|
||||
public:
|
||||
AverageTestBase(int width, int height) : width_(width), height_(height) {}
|
||||
|
||||
static void SetUpTestCase() {
|
||||
source_data_ = reinterpret_cast<uint8_t *>(
|
||||
vpx_memalign(kDataAlignment, kDataBlockSize));
|
||||
}
|
||||
|
||||
static void TearDownTestCase() {
|
||||
vpx_free(source_data_);
|
||||
source_data_ = NULL;
|
||||
}
|
||||
|
||||
virtual void TearDown() { libvpx_test::ClearSystemState(); }
|
||||
|
||||
protected:
|
||||
// Handle blocks up to 4 blocks 64x64 with stride up to 128
|
||||
static const int kDataAlignment = 16;
|
||||
static const int kDataBlockSize = 64 * 128;
|
||||
|
||||
virtual void SetUp() {
|
||||
source_stride_ = (width_ + 31) & ~31;
|
||||
rnd_.Reset(ACMRandom::DeterministicSeed());
|
||||
}
|
||||
|
||||
// Sum Pixels
|
||||
static 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];
|
||||
}
|
||||
return ((average + 32) >> 6);
|
||||
}
|
||||
|
||||
static 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];
|
||||
}
|
||||
return ((average + 8) >> 4);
|
||||
}
|
||||
|
||||
void FillConstant(uint8_t fill_constant) {
|
||||
for (int i = 0; i < width_ * height_; ++i) {
|
||||
source_data_[i] = fill_constant;
|
||||
}
|
||||
}
|
||||
|
||||
void FillRandom() {
|
||||
for (int i = 0; i < width_ * height_; ++i) {
|
||||
source_data_[i] = rnd_.Rand8();
|
||||
}
|
||||
}
|
||||
|
||||
int width_, height_;
|
||||
static uint8_t *source_data_;
|
||||
int source_stride_;
|
||||
|
||||
ACMRandom rnd_;
|
||||
};
|
||||
typedef unsigned int (*AverageFunction)(const uint8_t *s, int pitch);
|
||||
|
||||
typedef std::tr1::tuple<int, int, int, int, AverageFunction> 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_);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref,
|
||||
const int ref_stride, const int height);
|
||||
|
||||
typedef std::tr1::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam;
|
||||
|
||||
class IntProRowTest : public AverageTestBase,
|
||||
public ::testing::WithParamInterface<IntProRowParam> {
|
||||
public:
|
||||
IntProRowTest()
|
||||
: 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 *>(
|
||||
vpx_memalign(kDataAlignment, sizeof(*hbuf_asm_) * 16));
|
||||
hbuf_c_ = reinterpret_cast<int16_t *>(
|
||||
vpx_memalign(kDataAlignment, sizeof(*hbuf_c_) * 16));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
vpx_free(hbuf_c_);
|
||||
hbuf_c_ = NULL;
|
||||
vpx_free(hbuf_asm_);
|
||||
hbuf_asm_ = NULL;
|
||||
}
|
||||
|
||||
void RunComparison() {
|
||||
ASM_REGISTER_STATE_CHECK(c_func_(hbuf_c_, source_data_, 0, height_));
|
||||
ASM_REGISTER_STATE_CHECK(asm_func_(hbuf_asm_, source_data_, 0, height_));
|
||||
EXPECT_EQ(0, memcmp(hbuf_c_, hbuf_asm_, sizeof(*hbuf_c_) * 16))
|
||||
<< "Output mismatch";
|
||||
}
|
||||
|
||||
private:
|
||||
IntProRowFunc asm_func_;
|
||||
IntProRowFunc c_func_;
|
||||
int16_t *hbuf_asm_;
|
||||
int16_t *hbuf_c_;
|
||||
};
|
||||
|
||||
typedef int16_t (*IntProColFunc)(uint8_t const *ref, const int width);
|
||||
|
||||
typedef std::tr1::tuple<int, IntProColFunc, IntProColFunc> 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);
|
||||
c_func_ = GET_PARAM(2);
|
||||
}
|
||||
|
||||
protected:
|
||||
void RunComparison() {
|
||||
ASM_REGISTER_STATE_CHECK(sum_c_ = c_func_(source_data_, width_));
|
||||
ASM_REGISTER_STATE_CHECK(sum_asm_ = asm_func_(source_data_, width_));
|
||||
EXPECT_EQ(sum_c_, sum_asm_) << "Output mismatch";
|
||||
}
|
||||
|
||||
private:
|
||||
IntProColFunc asm_func_;
|
||||
IntProColFunc c_func_;
|
||||
int16_t sum_asm_;
|
||||
int16_t sum_c_;
|
||||
};
|
||||
|
||||
typedef int (*SatdFunc)(const tran_low_t *coeffs, int length);
|
||||
typedef std::tr1::tuple<int, SatdFunc> 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 *>(
|
||||
vpx_memalign(16, sizeof(*src_) * satd_size_));
|
||||
ASSERT_TRUE(src_ != NULL);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
libvpx_test::ClearSystemState();
|
||||
vpx_free(src_);
|
||||
}
|
||||
|
||||
void FillConstant(const tran_low_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;
|
||||
}
|
||||
}
|
||||
|
||||
void Check(const int expected) {
|
||||
int total;
|
||||
ASM_REGISTER_STATE_CHECK(total = satd_func_(src_, satd_size_));
|
||||
EXPECT_EQ(expected, total);
|
||||
}
|
||||
|
||||
int satd_size_;
|
||||
|
||||
private:
|
||||
tran_low_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 std::tr1::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;
|
||||
|
||||
TEST_P(AverageTest, MinValue) {
|
||||
FillConstant(0);
|
||||
CheckAverages();
|
||||
}
|
||||
|
||||
TEST_P(AverageTest, MaxValue) {
|
||||
FillConstant(255);
|
||||
CheckAverages();
|
||||
}
|
||||
|
||||
TEST_P(AverageTest, Random) {
|
||||
// The reference frame, but not the source frame, may be unaligned for
|
||||
// certain types of searches.
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
FillRandom();
|
||||
CheckAverages();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(IntProRowTest, MinValue) {
|
||||
FillConstant(0);
|
||||
RunComparison();
|
||||
}
|
||||
|
||||
TEST_P(IntProRowTest, MaxValue) {
|
||||
FillConstant(255);
|
||||
RunComparison();
|
||||
}
|
||||
|
||||
TEST_P(IntProRowTest, Random) {
|
||||
FillRandom();
|
||||
RunComparison();
|
||||
}
|
||||
|
||||
TEST_P(IntProColTest, MinValue) {
|
||||
FillConstant(0);
|
||||
RunComparison();
|
||||
}
|
||||
|
||||
TEST_P(IntProColTest, MaxValue) {
|
||||
FillConstant(255);
|
||||
RunComparison();
|
||||
}
|
||||
|
||||
TEST_P(IntProColTest, Random) {
|
||||
FillRandom();
|
||||
RunComparison();
|
||||
}
|
||||
|
||||
TEST_P(SatdTest, MinValue) {
|
||||
const int kMin = -32640;
|
||||
const int expected = -kMin * satd_size_;
|
||||
FillConstant(kMin);
|
||||
Check(expected);
|
||||
}
|
||||
|
||||
TEST_P(SatdTest, MaxValue) {
|
||||
const int kMax = 32640;
|
||||
const int expected = kMax * satd_size_;
|
||||
FillConstant(kMax);
|
||||
Check(expected);
|
||||
}
|
||||
|
||||
TEST_P(SatdTest, Random) {
|
||||
int expected;
|
||||
switch (satd_size_) {
|
||||
case 16: expected = 205298; break;
|
||||
case 64: expected = 1113950; break;
|
||||
case 256: expected = 4268415; break;
|
||||
case 1024: expected = 16954082; break;
|
||||
default:
|
||||
FAIL() << "Invalid satd size (" << satd_size_
|
||||
<< ") valid: 16/64/256/1024";
|
||||
}
|
||||
FillRandom();
|
||||
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 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)));
|
||||
|
||||
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)));
|
||||
|
||||
#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)));
|
||||
|
||||
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)));
|
||||
|
||||
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)));
|
||||
|
||||
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)));
|
||||
#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)));
|
||||
|
||||
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)));
|
||||
|
||||
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)));
|
||||
|
||||
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
|
||||
|
||||
#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
|
||||
|
||||
} // namespace
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user