Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
dav1d
Manage
Activity
Members
Labels
Plan
Issues
25
Issue boards
Milestones
Wiki
Code
Merge requests
13
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Analyze
Contributor analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
VideoLAN
dav1d
Commits
6649ca3f
Commit
6649ca3f
authored
6 years ago
by
Marvin Scholz
Browse files
Options
Downloads
Patches
Plain Diff
Build: Re-structure and cleanup meson.build files
parent
f5b7e2ff
No related branches found
Branches containing commit
No related tags found
Tags containing commit
1 merge request
!96
Meson refactor
Pipeline
#652
passed with stage
in 1 minute and 5 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
include/meson.build
+4
-0
4 additions, 0 deletions
include/meson.build
meson.build
+101
-199
101 additions, 199 deletions
meson.build
src/meson.build
+181
-0
181 additions, 0 deletions
src/meson.build
tools/meson.build
+49
-0
49 additions, 0 deletions
tools/meson.build
with
335 additions
and
199 deletions
include/meson.build
+
4
−
0
View file @
6649ca3f
...
...
@@ -22,6 +22,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Revision file (version.h) generation
dav1d_git_dir
=
join_paths
(
dav1d_src_root
,
'.git'
)
rev_target
=
vcs_tag
(
command
:
[
'git'
,
'--git-dir'
,
dav1d_git_dir
,
...
...
@@ -31,3 +32,6 @@ rev_target = vcs_tag(command: [
input
:
'version.h.in'
,
output
:
'version.h'
)
# Install include/dav1d headers
install_subdir
(
'dav1d'
,
install_dir
:
'include'
)
This diff is collapsed.
Click to expand it.
meson.build
+
101
−
199
View file @
6649ca3f
...
...
@@ -33,50 +33,117 @@ dav1d_version_minor = dav1d_version_array[1]
dav1d_version_revision
=
dav1d_version_array
[
2
]
dav1d_src_root
=
meson
.
current_source_dir
()
cc
=
meson
.
get_compiler
(
'c'
)
# Configuratin data for config.h
cdata
=
configuration_data
()
# Configuration data for config.asm
cdata_asm
=
configuration_data
()
cc
=
meson
.
get_compiler
(
'c'
)
# On windows, we use a compatibility layer to emulate pthread
if
host_machine
.
system
()
!=
'windows'
thread_dependency
=
dependency
(
'threads'
)
else
thread_dependency
=
declare_dependency
(
sources
:
[
'src/win32/thread.c'
])
endif
# Include directories
dav1d_inc_dirs
=
include_directories
([
'.'
,
'include'
,
'include/dav1d'
])
if
cc
.
has_function
(
'getopt_long'
,
prefix
:
'#include <getopt.h>'
)
cdata
.
set
(
'HAVE_GETOPT_H'
,
1
)
endif
#
# Option handling
#
# Bitdepth option
dav1d_bitdepths
=
get_option
(
'bitdepths'
)
foreach
bitdepth
:
dav1d_bitdepths
cdata
.
set
(
'CONFIG_@0@BPC'
.
format
(
bitdepth
),
1
)
endforeach
# ASM option
is_asm_enabled
=
(
get_option
(
'build_asm'
)
==
true
and
host_machine
.
cpu_family
().
startswith
(
'x86'
))
cdata
.
set10
(
'HAVE_ASM'
,
is_asm_enabled
)
#
# OS/Compiler
feature detection
# OS/Compiler
checks and defines
#
feature_defines
=
[
[
'_POSIX_C_SOURCE'
,
'200112L'
],
# POSIX.1–2001 (IEEE Std 1003.1-2001)
]
# Arguments in test_args will be used even on feature tests
test_args
=
[]
# Define _POSIX_C_SOURCE to POSIX.1–2001 (IEEE Std 1003.1-2001)
test_args
+=
'-D_POSIX_C_SOURCE=200112L'
add_project_arguments
(
'-D_POSIX_C_SOURCE=200112L'
,
language
:
'c'
)
if
host_machine
.
system
()
==
'windows'
cdata
.
set
(
'_WIN32_WINNT'
,
'0x0601'
)
cdata
.
set
(
'UNICODE'
,
1
)
# Define to 1 for Unicode (Wide Chars) APIs
cdata
.
set
(
'_UNICODE'
,
1
)
# Define to 1 for Unicode (Wide Chars) APIs
cdata
.
set
(
'__USE_MINGW_ANSI_STDIO'
,
1
)
# Define to force use of MinGW printf
endif
# On Windows, we use a compatibility layer to emulate pthread
if
host_machine
.
system
()
==
'windows'
feature_defines
+=
[
[
'_WIN32_WINNT'
,
0x0601
],
[
'UNICODE'
,
1
],
# Define to 1 for Unicode (Wide Chars) APIs
[
'_UNICODE'
,
1
],
# Define to 1 for Unicode (Wide Chars) APIs
[
'__USE_MINGW_ANSI_STDIO'
,
1
],
# Define to force use of MinGW printf
]
thread_dependency
=
declare_dependency
(
sources
:
files
(
'src/win32/thread.c'
))
else
thread_dependency
=
dependency
(
'threads'
)
endif
# Header checks
if
not
cc
.
check_header
(
'stdatomic.h'
)
error
(
'Atomics not supported'
)
endif
if
cc
.
check_header
(
'unistd.h'
)
cdata
.
set
(
'HAVE_UNISTD_H'
,
1
)
endif
# Function checks
if
not
cc
.
has_function
(
'getopt_long'
,
prefix
:
'#include <getopt.h>'
,
args
:
test_args
)
getopt_dependency
=
declare_dependency
(
sources
:
files
(
'tools/compat/getopt.c'
),
include_directories
:
include_directories
(
'include/compat'
),
)
else
getopt_dependency
=
[]
endif
if
cc
.
has_function
(
'posix_memalign'
,
prefix
:
'#include <stdlib.h>'
,
args
:
test_args
)
cdata
.
set
(
'HAVE_POSIX_MEMALIGN'
,
1
)
elif
cc
.
has_function
(
'_aligned_malloc'
,
prefix
:
'#include <malloc.h>'
,
args
:
test_args
)
cdata
.
set
(
'HAVE_ALIGNED_MALLOC'
,
1
)
endif
# Compiler flag tests
if
cc
.
has_argument
(
'-fvisibility=hidden'
)
add_project_arguments
(
'-fvisibility=hidden'
,
language
:
'c'
)
else
warning
(
'Compiler does not support -fvisibility=hidden, all symbols will be public!'
)
endif
# Compiler flags that should be set
# But when the compiler does not supports them
# it is not an error and silently tolerated
optional_arguments
=
[
'-Wundef'
,
'-Wvla'
,
# should be '-Werror=vla
]
if
(
get_option
(
'buildtype'
)
!=
'debug'
and
get_option
(
'buildtype'
)
!=
'plain'
)
optional_arguments
+=
'-fomit-frame-pointer'
optional_arguments
+=
'-ffast-math'
endif
add_project_arguments
(
cc
.
get_supported_arguments
(
optional_arguments
),
language
:
'c'
)
# Stack alignments flags
stackalign_flag
=
[]
stackrealign_flag
=
[]
...
...
@@ -132,122 +199,21 @@ if cc.symbols_have_underscore_prefix()
cdata_asm
.
set10
(
'PREFIX'
,
true
)
endif
if
cc
.
has_argument
(
'-fvisibility=hidden'
)
add_project_arguments
(
'-fvisibility=hidden'
,
language
:
'c'
)
else
warning
(
'Compiler does not support -fvisibility=hidden, all symbols will be public!'
)
endif
if
cc
.
has_function
(
'posix_memalign'
,
prefix
:
'#include <stdlib.h>'
,
args
:
[
'-D_POSIX_C_SOURCE=200112L'
])
cdata
.
set
(
'HAVE_POSIX_MEMALIGN'
,
1
)
elif
cc
.
has_function
(
'_aligned_malloc'
,
prefix
:
'#include <malloc.h>'
)
cdata
.
set
(
'HAVE_ALIGNED_MALLOC'
,
1
)
endif
if
cc
.
check_header
(
'unistd.h'
)
cdata
.
set
(
'HAVE_UNISTD_H'
,
1
)
endif
if
(
get_option
(
'buildtype'
)
!=
'debug'
and
get_option
(
'buildtype'
)
!=
'plain'
)
add_project_arguments
(
'-fomit-frame-pointer'
,
'-ffast-math'
,
language
:
'c'
)
endif
warning_flags
=
[
'-Wundef'
,
'-Wvla'
,
# should be '-Werror=vla
]
add_project_arguments
(
cc
.
get_supported_arguments
(
warning_flags
),
language
:
'c'
)
# Generate config.h
config_h_target
=
configure_file
(
output
:
'config.h'
,
configuration
:
cdata
)
foreach
f
:
feature_defines
cdata
.
set
(
f
.
get
(
0
),
f
.
get
(
1
))
endforeach
is_asm_enabled
=
(
get_option
(
'build_asm'
)
==
true
and
host_machine
.
cpu_family
().
startswith
(
'x86'
))
cdata
.
set10
(
'HAVE_ASM'
,
is_asm_enabled
)
#
#
Generate config headers
#
ASM specific stuff
#
if
cdata
.
has
(
'HAVE_GETOPT_H'
)
dav1d_inc_dirs
=
include_directories
([
'.'
,
'include'
,
'include/dav1d'
])
else
dav1d_inc_dirs
=
include_directories
([
'.'
,
'include'
,
'include/dav1d'
,
'include/compat'
])
endif
config_h_target
=
configure_file
(
output
:
'config.h'
,
configuration
:
cdata
)
if
is_asm_enabled
config_asm_target
=
configure_file
(
output
:
'config.asm'
,
output_format
:
'nasm'
,
configuration
:
cdata_asm
)
endif
subdir
(
'include'
)
#
# dav1d library
#
libdav1d_tmpl_sources
=
files
(
'src/ipred.c'
,
'src/itx.c'
,
'src/ipred_prepare.c'
,
'src/lf_apply.c'
,
'src/loopfilter.c'
,
'src/mc.c'
,
'src/cdef_apply.c'
,
'src/cdef.c'
,
'src/lr_apply.c'
,
'src/looprestoration.c'
,
'src/recon.c'
)
# Generate config.asm
config_asm_target
=
configure_file
(
output
:
'config.asm'
,
output_format
:
'nasm'
,
configuration
:
cdata_asm
)
entrypoints_src
=
files
(
'src/lib.c'
,
'src/thread_task.c'
)
entrypoints_lib
=
static_library
(
'libdav1dentrypoint'
,
entrypoints_src
,
rev_target
,
include_directories
:
dav1d_inc_dirs
,
c_args
:
stackrealign_flag
,
install
:
false
,
build_by_default
:
false
,
)
entrypoints_objs
=
entrypoints_lib
.
extract_all_objects
()
libdav1d_sources
=
files
(
'src/picture.c'
,
'src/data.c'
,
'src/ref.c'
,
'src/getbits.c'
,
'src/obu.c'
,
'src/decode.c'
,
'src/cdf.c'
,
'src/msac.c'
,
'src/tables.c'
,
'src/scan.c'
,
'src/dequant_tables.c'
,
'src/intra_edge.c'
,
'src/lf_mask.c'
,
'src/ref_mvs.c'
,
'src/warpmv.c'
,
'src/wedge.c'
,
'src/qm.c'
,
)
if
is_asm_enabled
libdav1d_sources
+=
files
(
'src/x86/cpu.c'
,
)
libdav1d_tmpl_sources
+=
files
(
'src/x86/mc_init.c'
,
)
libdav1d_sources_asm
=
files
(
'src/x86/cpuid.asm'
,
'src/x86/mc.asm'
,
)
# NASM compiler support
nasm
=
find_program
(
'nasm'
)
...
...
@@ -275,90 +241,26 @@ if is_asm_enabled
'@INPUT@'
,
'-o'
,
'@OUTPUT@'
])
nasm_objs
=
nasm_gen
.
process
(
libdav1d_sources_asm
)
else
nasm_objs
=
[]
endif
# Build a helper library for each bitdepth
bitdepth_objs
=
[]
foreach
bitdepth
:
dav1d_bitdepths
bitdepth_lib
=
static_library
(
'dav1d_bitdepth_@0@'
.
format
(
bitdepth
),
libdav1d_tmpl_sources
,
config_h_target
,
include_directories
:
dav1d_inc_dirs
,
c_args
:
[
'-DBITDEPTH=@0@'
.
format
(
bitdepth
)]
+
stackalign_flag
,
install
:
false
,
build_by_default
:
false
,
)
bitdepth_objs
+=
bitdepth_lib
.
extract_all_objects
()
endforeach
if
host_machine
.
system
()
==
'windows'
winmod
=
import
(
'windows'
)
rc_data
=
configuration_data
()
rc_data
.
set
(
'VERSION_MAJOR'
,
dav1d_version_major
)
rc_data
.
set
(
'VERSION_MINOR'
,
dav1d_version_minor
)
rc_data
.
set
(
'VERSION_REVISION'
,
dav1d_version_revision
)
rc_data
.
set
(
'VERSION_EXTRA'
,
'0'
)
rc_data
.
set
(
'COPYRIGHT_YEARS'
,
'2018'
)
rc_file
=
configure_file
(
input
:
'src/dav1d.rc.in'
,
output
:
'dav1d.rc'
,
configuration
:
rc_data
)
rc_source
=
winmod
.
compile_resources
(
rc_file
,
include_directories
:
include_directories
(
'src'
))
libdav1d_sources
+=
rc_source
#entrypoints_objs += rc_source
endif
libdav1d_private
=
static_library
(
'dav1d_private'
,
libdav1d_sources
,
nasm_objs
,
objects
:
[
bitdepth_objs
,
entrypoints_objs
],
include_directories
:
dav1d_inc_dirs
,
c_args
:
[
stackalign_flag
],
install
:
false
,
build_by_default
:
false
,
)
#
# Include subdir meson.build files
# The order is important!
libdav1d
=
library
(
'dav1d'
,
version
:
meson
.
project_version
(),
link_whole
:
libdav1d_private
,
dependencies
:
thread_dependency
,
install
:
true
,
)
subdir
(
'include'
)
install_subdir
(
'include/dav1d/'
,
install_dir
:
'include
'
)
subdir
(
'src
'
)
#
# dav1d cli tool
#
dav1d_sources
=
files
(
'tools/dav1d.c'
,
'tools/dav1d_cli_parse.c'
,
'tools/input/input.c'
,
'tools/input/ivf.c'
,
'tools/output/md5.c'
,
'tools/output/output.c'
,
'tools/output/y4m2.c'
,
'tools/output/yuv.c'
)
subdir
(
'tools'
)
if
not
cdata
.
has
(
'HAVE_GETOPT_H'
)
dav1d_sources
+=
files
(
'tools/compat/getopt.c'
)
endif
subdir
(
'tests'
)
dav1d
=
executable
(
'dav1d'
,
dav1d_sources
,
rev_target
,
link_with
:
libdav1d
,
include_directories
:
[
dav1d_inc_dirs
,
include_directories
(
'tools'
)],
install
:
true
,
)
subdir
(
'tests'
)
#
# pkg-config
boilerplat
e
#
Generate
pkg-config
.pc fil
e
#
pkg_mod
=
import
(
'pkgconfig'
)
pkg_mod
.
generate
(
libraries
:
libdav1d
,
...
...
This diff is collapsed.
Click to expand it.
src/meson.build
0 → 100644
+
181
−
0
View file @
6649ca3f
# Copyright © 2018, VideoLAN and dav1d authors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Build definition for the dav1d library
#
# libdav1d source files
libdav1d_sources
=
files
(
'picture.c'
,
'data.c'
,
'ref.c'
,
'getbits.c'
,
'obu.c'
,
'decode.c'
,
'cdf.c'
,
'msac.c'
,
'tables.c'
,
'scan.c'
,
'dequant_tables.c'
,
'intra_edge.c'
,
'lf_mask.c'
,
'ref_mvs.c'
,
'warpmv.c'
,
'wedge.c'
,
'qm.c'
,
)
# libdav1d bitdepth source files
# These files are compiled for each bitdepth with
# `BITDEPTH` defined to the currently built bitdepth.
libdav1d_tmpl_sources
=
files
(
'ipred.c'
,
'itx.c'
,
'ipred_prepare.c'
,
'lf_apply.c'
,
'loopfilter.c'
,
'mc.c'
,
'cdef_apply.c'
,
'cdef.c'
,
'lr_apply.c'
,
'looprestoration.c'
,
'recon.c'
)
# libdav1d entrypoint source files
# These source files contain library entry points and are
# built with the stack-realign flag set, where necessary.
libdav1d_entrypoints_sources
=
files
(
'lib.c'
,
'thread_task.c'
)
# ASM specific sources
if
is_asm_enabled
libdav1d_sources
+=
files
(
'x86/cpu.c'
,
)
libdav1d_tmpl_sources
+=
files
(
'x86/mc_init.c'
,
)
# NASM source files
libdav1d_sources_asm
=
files
(
'x86/cpuid.asm'
,
'x86/mc.asm'
,
)
# Compile the ASM sources with NASM
libdav1d_nasm_objs
=
nasm_gen
.
process
(
libdav1d_sources_asm
)
else
libdav1d_nasm_objs
=
[]
endif
#
# Windows .rc file
#
if
host_machine
.
system
()
==
'windows'
winmod
=
import
(
'windows'
)
rc_data
=
configuration_data
()
rc_data
.
set
(
'VERSION_MAJOR'
,
dav1d_version_major
)
rc_data
.
set
(
'VERSION_MINOR'
,
dav1d_version_minor
)
rc_data
.
set
(
'VERSION_REVISION'
,
dav1d_version_revision
)
rc_data
.
set
(
'VERSION_EXTRA'
,
'0'
)
rc_data
.
set
(
'COPYRIGHT_YEARS'
,
'2018'
)
rc_file
=
configure_file
(
input
:
'dav1d.rc.in'
,
output
:
'dav1d.rc'
,
configuration
:
rc_data
)
libdav1d_rc_obj
=
winmod
.
compile_resources
(
rc_file
)
else
libdav1d_rc_obj
=
[]
endif
#
# Library definitions
#
# Helper library for dav1d entrypoints
libdav1d_entrypoints_objs
=
static_library
(
'dav1d_entrypoint'
,
libdav1d_entrypoints_sources
,
rev_target
,
include_directories
:
dav1d_inc_dirs
,
c_args
:
stackrealign_flag
,
install
:
false
,
build_by_default
:
false
,
).
extract_all_objects
()
# Helper library for each bitdepth
libdav1d_bitdepth_objs
=
[]
foreach
bitdepth
:
dav1d_bitdepths
libdav1d_bitdepth_objs
+=
static_library
(
'dav1d_bitdepth_@0@'
.
format
(
bitdepth
),
libdav1d_tmpl_sources
,
config_h_target
,
include_directories
:
dav1d_inc_dirs
,
c_args
:
[
'-DBITDEPTH=@0@'
.
format
(
bitdepth
)]
+
stackalign_flag
,
install
:
false
,
build_by_default
:
false
,
).
extract_all_objects
()
endforeach
# Static private helper library
# This is primarily needed to link with tests so that
# the tests can use all symbols, even the non-exported.
libdav1d_private
=
static_library
(
'dav1d_private'
,
libdav1d_sources
,
libdav1d_nasm_objs
,
libdav1d_rc_obj
,
objects
:
[
libdav1d_bitdepth_objs
,
libdav1d_entrypoints_objs
],
include_directories
:
dav1d_inc_dirs
,
c_args
:
[
stackalign_flag
],
install
:
false
,
build_by_default
:
false
,
)
# The final dav1d library
libdav1d
=
library
(
'dav1d'
,
version
:
meson
.
project_version
(),
link_whole
:
libdav1d_private
,
dependencies
:
thread_dependency
,
include_directories
:
dav1d_inc_dirs
,
install
:
true
,
)
This diff is collapsed.
Click to expand it.
tools/meson.build
0 → 100644
+
49
−
0
View file @
6649ca3f
# Copyright © 2018, VideoLAN and dav1d authors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Build definition for the dav1d tools
#
# dav1d cli tool sources
dav1d_sources
=
files
(
'dav1d.c'
,
'dav1d_cli_parse.c'
,
'input/input.c'
,
'input/ivf.c'
,
'output/md5.c'
,
'output/output.c'
,
'output/y4m2.c'
,
'output/yuv.c'
,
)
dav1d
=
executable
(
'dav1d'
,
dav1d_sources
,
rev_target
,
link_with
:
libdav1d
,
include_directories
:
[
dav1d_inc_dirs
],
dependencies
:
[
getopt_dependency
],
install
:
true
,
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment